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 43 #include "acl_support.h" 44 45 /* 46 * acl_to_text - generate a text form of an acl 47 * spec says nothing about output ordering, so leave in acl order 48 * 49 * This function will not produce nice results if it is called with 50 * a non-POSIX.1e semantics ACL. 51 */ 52 53 char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags); 54 55 static char * 56 _posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags) 57 { 58 struct acl *acl_int; 59 char *buf, *tmpbuf; 60 char name_buf[MAXLOGNAME]; 61 char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1], 62 effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1]; 63 int i, error, len; 64 uid_t ae_id; 65 acl_tag_t ae_tag; 66 acl_perm_t ae_perm, effective_perm, mask_perm; 67 68 buf = strdup(""); 69 if (buf == NULL) 70 return(NULL); 71 72 acl_int = &acl->ats_acl; 73 74 mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */ 75 for (i = 0; i < acl_int->acl_cnt; i++) 76 if (acl_int->acl_entry[i].ae_tag == ACL_MASK) 77 mask_perm = acl_int->acl_entry[i].ae_perm; 78 79 for (i = 0; i < acl_int->acl_cnt; i++) { 80 ae_tag = acl_int->acl_entry[i].ae_tag; 81 ae_id = acl_int->acl_entry[i].ae_id; 82 ae_perm = acl_int->acl_entry[i].ae_perm; 83 84 switch(ae_tag) { 85 case ACL_USER_OBJ: 86 error = _posix1e_acl_perm_to_string(ae_perm, 87 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 88 if (error) 89 goto error_label; 90 len = asprintf(&tmpbuf, "%suser::%s\n", buf, 91 perm_buf); 92 if (len == -1) 93 goto error_label; 94 free(buf); 95 buf = tmpbuf; 96 break; 97 98 case ACL_USER: 99 error = _posix1e_acl_perm_to_string(ae_perm, 100 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 101 if (error) 102 goto error_label; 103 104 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 105 MAXLOGNAME, name_buf, flags); 106 if (error) 107 goto error_label; 108 109 effective_perm = ae_perm & mask_perm; 110 if (effective_perm != ae_perm) { 111 error = _posix1e_acl_perm_to_string( 112 effective_perm, 113 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 114 effective_perm_buf); 115 if (error) 116 goto error_label; 117 len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# " 118 "effective: %s\n", 119 buf, name_buf, perm_buf, 120 effective_perm_buf); 121 } else { 122 len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf, 123 name_buf, perm_buf); 124 } 125 if (len == -1) 126 goto error_label; 127 free(buf); 128 buf = tmpbuf; 129 break; 130 131 case ACL_GROUP_OBJ: 132 error = _posix1e_acl_perm_to_string(ae_perm, 133 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 134 if (error) 135 goto error_label; 136 137 effective_perm = ae_perm & mask_perm; 138 if (effective_perm != ae_perm) { 139 error = _posix1e_acl_perm_to_string( 140 effective_perm, 141 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 142 effective_perm_buf); 143 if (error) 144 goto error_label; 145 len = asprintf(&tmpbuf, "%sgroup::%s\t\t# " 146 "effective: %s\n", 147 buf, perm_buf, effective_perm_buf); 148 } else { 149 len = asprintf(&tmpbuf, "%sgroup::%s\n", buf, 150 perm_buf); 151 } 152 if (len == -1) 153 goto error_label; 154 free(buf); 155 buf = tmpbuf; 156 break; 157 158 case ACL_GROUP: 159 error = _posix1e_acl_perm_to_string(ae_perm, 160 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 161 if (error) 162 goto error_label; 163 164 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 165 MAXLOGNAME, name_buf, flags); 166 if (error) 167 goto error_label; 168 169 effective_perm = ae_perm & mask_perm; 170 if (effective_perm != ae_perm) { 171 error = _posix1e_acl_perm_to_string( 172 effective_perm, 173 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 174 effective_perm_buf); 175 if (error) 176 goto error_label; 177 len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# " 178 "effective: %s\n", 179 buf, name_buf, perm_buf, 180 effective_perm_buf); 181 } else { 182 len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf, 183 name_buf, perm_buf); 184 } 185 if (len == -1) 186 goto error_label; 187 free(buf); 188 buf = tmpbuf; 189 break; 190 191 case ACL_MASK: 192 error = _posix1e_acl_perm_to_string(ae_perm, 193 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 194 if (error) 195 goto error_label; 196 197 len = asprintf(&tmpbuf, "%smask::%s\n", buf, 198 perm_buf); 199 if (len == -1) 200 goto error_label; 201 free(buf); 202 buf = tmpbuf; 203 break; 204 205 case ACL_OTHER: 206 error = _posix1e_acl_perm_to_string(ae_perm, 207 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 208 if (error) 209 goto error_label; 210 211 len = asprintf(&tmpbuf, "%sother::%s\n", buf, 212 perm_buf); 213 if (len == -1) 214 goto error_label; 215 free(buf); 216 buf = tmpbuf; 217 break; 218 219 default: 220 errno = EINVAL; 221 goto error_label; 222 } 223 } 224 225 if (len_p) { 226 *len_p = strlen(buf); 227 } 228 return (buf); 229 230 error_label: 231 /* jump to here sets errno already, we just clean up */ 232 if (buf) free(buf); 233 return (NULL); 234 } 235 236 char * 237 acl_to_text_np(acl_t acl, ssize_t *len_p, int flags) 238 { 239 240 if (acl == NULL) { 241 errno = EINVAL; 242 return(NULL); 243 } 244 245 switch (_acl_brand(acl)) { 246 case ACL_BRAND_POSIX: 247 return (_posix1e_acl_to_text(acl, len_p, flags)); 248 case ACL_BRAND_NFS4: 249 return (_nfs4_acl_to_text_np(acl, len_p, flags)); 250 default: 251 errno = EINVAL; 252 return (NULL); 253 } 254 } 255 256 char * 257 acl_to_text(acl_t acl, ssize_t *len_p) 258 { 259 260 return (acl_to_text_np(acl, len_p, 0)); 261 } 262