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