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