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 if (acl == NULL) { 74 errno = EINVAL; 75 return(NULL); 76 } 77 78 acl_int = &acl->ats_acl; 79 80 mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */ 81 for (i = 0; i < acl_int->acl_cnt; i++) 82 if (acl_int->acl_entry[i].ae_tag == ACL_MASK) 83 mask_perm = acl_int->acl_entry[i].ae_perm; 84 85 for (i = 0; i < acl_int->acl_cnt; i++) { 86 ae_tag = acl_int->acl_entry[i].ae_tag; 87 ae_id = acl_int->acl_entry[i].ae_id; 88 ae_perm = acl_int->acl_entry[i].ae_perm; 89 90 switch(ae_tag) { 91 case ACL_USER_OBJ: 92 error = _posix1e_acl_perm_to_string(ae_perm, 93 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 94 if (error) 95 goto error_label; 96 len = asprintf(&tmpbuf, "%suser::%s\n", buf, 97 perm_buf); 98 if (len == -1) 99 goto error_label; 100 free(buf); 101 buf = tmpbuf; 102 break; 103 104 case ACL_USER: 105 error = _posix1e_acl_perm_to_string(ae_perm, 106 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 107 if (error) 108 goto error_label; 109 110 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 111 UT_NAMESIZE+1, name_buf, flags); 112 if (error) 113 goto error_label; 114 115 effective_perm = ae_perm & mask_perm; 116 if (effective_perm != ae_perm) { 117 error = _posix1e_acl_perm_to_string( 118 effective_perm, 119 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 120 effective_perm_buf); 121 if (error) 122 goto error_label; 123 len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# " 124 "effective: %s\n", 125 buf, name_buf, perm_buf, 126 effective_perm_buf); 127 } else { 128 len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf, 129 name_buf, perm_buf); 130 } 131 if (len == -1) 132 goto error_label; 133 free(buf); 134 buf = tmpbuf; 135 break; 136 137 case ACL_GROUP_OBJ: 138 error = _posix1e_acl_perm_to_string(ae_perm, 139 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 140 if (error) 141 goto error_label; 142 143 effective_perm = ae_perm & mask_perm; 144 if (effective_perm != ae_perm) { 145 error = _posix1e_acl_perm_to_string( 146 effective_perm, 147 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 148 effective_perm_buf); 149 if (error) 150 goto error_label; 151 len = asprintf(&tmpbuf, "%sgroup::%s\t\t# " 152 "effective: %s\n", 153 buf, perm_buf, effective_perm_buf); 154 } else { 155 len = asprintf(&tmpbuf, "%sgroup::%s\n", buf, 156 perm_buf); 157 } 158 if (len == -1) 159 goto error_label; 160 free(buf); 161 buf = tmpbuf; 162 break; 163 164 case ACL_GROUP: 165 error = _posix1e_acl_perm_to_string(ae_perm, 166 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 167 if (error) 168 goto error_label; 169 170 error = _posix1e_acl_id_to_name(ae_tag, ae_id, 171 UT_NAMESIZE+1, name_buf, flags); 172 if (error) 173 goto error_label; 174 175 effective_perm = ae_perm & mask_perm; 176 if (effective_perm != ae_perm) { 177 error = _posix1e_acl_perm_to_string( 178 effective_perm, 179 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, 180 effective_perm_buf); 181 if (error) 182 goto error_label; 183 len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# " 184 "effective: %s\n", 185 buf, name_buf, perm_buf, 186 effective_perm_buf); 187 } else { 188 len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf, 189 name_buf, perm_buf); 190 } 191 if (len == -1) 192 goto error_label; 193 free(buf); 194 buf = tmpbuf; 195 break; 196 197 case ACL_MASK: 198 error = _posix1e_acl_perm_to_string(ae_perm, 199 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 200 if (error) 201 goto error_label; 202 203 len = asprintf(&tmpbuf, "%smask::%s\n", buf, 204 perm_buf); 205 if (len == -1) 206 goto error_label; 207 free(buf); 208 buf = tmpbuf; 209 break; 210 211 case ACL_OTHER: 212 error = _posix1e_acl_perm_to_string(ae_perm, 213 _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf); 214 if (error) 215 goto error_label; 216 217 len = asprintf(&tmpbuf, "%sother::%s\n", buf, 218 perm_buf); 219 if (len == -1) 220 goto error_label; 221 free(buf); 222 buf = tmpbuf; 223 break; 224 225 default: 226 errno = EINVAL; 227 goto error_label; 228 } 229 } 230 231 if (len_p) { 232 *len_p = strlen(buf); 233 } 234 return (buf); 235 236 error_label: 237 /* jump to here sets errno already, we just clean up */ 238 if (buf) free(buf); 239 return (NULL); 240 } 241 242 char * 243 acl_to_text_np(acl_t acl, ssize_t *len_p, int flags) 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