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