1 /*- 2 * Copyright (c) 1999-2002 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 /* 27 * acl_to_text - return a text string with a text representation of the acl 28 * in it. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/types.h> 35 #include "namespace.h" 36 #include <sys/acl.h> 37 #include "un-namespace.h" 38 #include <sys/errno.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <utmp.h> 43 44 #include "acl_support.h" 45 46 /* 47 * acl_to_text - generate a text form of an acl 48 * spec says nothing about output ordering, so leave in acl order 49 * 50 * This function will not produce nice results if it is called with 51 * a non-POSIX.1e semantics ACL. 52 */ 53 54 char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags); 55 56 static char * 57 _posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags) 58 { 59 struct acl *acl_int; 60 char *buf, *tmpbuf; 61 char name_buf[UT_NAMESIZE+1]; 62 char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1], 63 effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1]; 64 int i, error, len; 65 uid_t ae_id; 66 acl_tag_t ae_tag; 67 acl_perm_t ae_perm, effective_perm, mask_perm; 68 69 buf = strdup(""); 70 if (buf == NULL) 71 return(NULL); 72 73 acl_int = &acl->ats_acl; 74 75 mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */ 76 for (i = 0; i < acl_int->acl_cnt; i++) 77 if (acl_int->acl_entry[i].ae_tag == ACL_MASK) 78 mask_perm = acl_int->acl_entry[i].ae_perm; 79 80 for (i = 0; i < acl_int->acl_cnt; i++) { 81 ae_tag = acl_int->acl_entry[i].ae_tag; 82 ae_id = acl_int->acl_entry[i].ae_id; 83 ae_perm = acl_int->acl_entry[i].ae_perm; 84 85 switch(ae_tag) { 86 case ACL_USER_OBJ: 87 error = _posix1e_acl_perm_to_string(ae_perm, 88 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 89 if (error) 90 goto error_label; 91 len = asprintf(&tmpbuf, "%suser::%s\n", buf, 92 perm_buf); 93 if (len == -1) 94 goto error_label; 95 free(buf); 96 buf = tmpbuf; 97 break; 98 99 case ACL_USER: 100 error = _posix1e_acl_perm_to_string(ae_perm, 101 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 102 if (error) 103 goto error_label; 104 105 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 106 UT_NAMESIZE+1, name_buf, flags); 107 if (error) 108 goto error_label; 109 110 effective_perm = ae_perm & mask_perm; 111 if (effective_perm != ae_perm) { 112 error = _posix1e_acl_perm_to_string( 113 effective_perm, 114 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 115 effective_perm_buf); 116 if (error) 117 goto error_label; 118 len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# " 119 "effective: %s\n", 120 buf, name_buf, perm_buf, 121 effective_perm_buf); 122 } else { 123 len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf, 124 name_buf, perm_buf); 125 } 126 if (len == -1) 127 goto error_label; 128 free(buf); 129 buf = tmpbuf; 130 break; 131 132 case ACL_GROUP_OBJ: 133 error = _posix1e_acl_perm_to_string(ae_perm, 134 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 135 if (error) 136 goto error_label; 137 138 effective_perm = ae_perm & mask_perm; 139 if (effective_perm != ae_perm) { 140 error = _posix1e_acl_perm_to_string( 141 effective_perm, 142 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 143 effective_perm_buf); 144 if (error) 145 goto error_label; 146 len = asprintf(&tmpbuf, "%sgroup::%s\t\t# " 147 "effective: %s\n", 148 buf, perm_buf, effective_perm_buf); 149 } else { 150 len = asprintf(&tmpbuf, "%sgroup::%s\n", buf, 151 perm_buf); 152 } 153 if (len == -1) 154 goto error_label; 155 free(buf); 156 buf = tmpbuf; 157 break; 158 159 case ACL_GROUP: 160 error = _posix1e_acl_perm_to_string(ae_perm, 161 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 162 if (error) 163 goto error_label; 164 165 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 166 UT_NAMESIZE+1, name_buf, flags); 167 if (error) 168 goto error_label; 169 170 effective_perm = ae_perm & mask_perm; 171 if (effective_perm != ae_perm) { 172 error = _posix1e_acl_perm_to_string( 173 effective_perm, 174 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 175 effective_perm_buf); 176 if (error) 177 goto error_label; 178 len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# " 179 "effective: %s\n", 180 buf, name_buf, perm_buf, 181 effective_perm_buf); 182 } else { 183 len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf, 184 name_buf, perm_buf); 185 } 186 if (len == -1) 187 goto error_label; 188 free(buf); 189 buf = tmpbuf; 190 break; 191 192 case ACL_MASK: 193 error = _posix1e_acl_perm_to_string(ae_perm, 194 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 195 if (error) 196 goto error_label; 197 198 len = asprintf(&tmpbuf, "%smask::%s\n", buf, 199 perm_buf); 200 if (len == -1) 201 goto error_label; 202 free(buf); 203 buf = tmpbuf; 204 break; 205 206 case ACL_OTHER: 207 error = _posix1e_acl_perm_to_string(ae_perm, 208 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 209 if (error) 210 goto error_label; 211 212 len = asprintf(&tmpbuf, "%sother::%s\n", buf, 213 perm_buf); 214 if (len == -1) 215 goto error_label; 216 free(buf); 217 buf = tmpbuf; 218 break; 219 220 default: 221 errno = EINVAL; 222 goto error_label; 223 } 224 } 225 226 if (len_p) { 227 *len_p = strlen(buf); 228 } 229 return (buf); 230 231 error_label: 232 /* jump to here sets errno already, we just clean up */ 233 if (buf) free(buf); 234 return (NULL); 235 } 236 237 char * 238 acl_to_text_np(acl_t acl, ssize_t *len_p, int flags) 239 { 240 241 if (acl == NULL) { 242 errno = EINVAL; 243 return(NULL); 244 } 245 246 switch (_acl_brand(acl)) { 247 case ACL_BRAND_POSIX: 248 return (_posix1e_acl_to_text(acl, len_p, flags)); 249 case ACL_BRAND_NFS4: 250 return (_nfs4_acl_to_text_np(acl, len_p, flags)); 251 default: 252 errno = EINVAL; 253 return (NULL); 254 } 255 } 256 257 char * 258 acl_to_text(acl_t acl, ssize_t *len_p) 259 { 260 261 return (acl_to_text_np(acl, len_p, 0)); 262 } 263