1 /*- 2 * Copyright (c) 1999 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 *$FreeBSD: src/lib/libposix1e/acl_to_text.c,v 1.2 2000/01/26 04:19:38 rwatson Exp $ 27 *$DragonFly: src/lib/libposix1e/acl_to_text.c,v 1.3 2005/08/04 17:27:09 drhodus Exp $ 28 */ 29 /* 30 * acl_to_text - return a text string with a text representation of the acl 31 * in it. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/acl.h> 36 #include <sys/errno.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <utmp.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 char * 52 acl_to_text(acl_t acl, ssize_t *len_p) 53 { 54 char *buf, *tmpbuf; 55 char name_buf[UT_NAMESIZE+1]; 56 char perm_buf[ACL_STRING_PERM_MAXSIZE+1], 57 effective_perm_buf[ACL_STRING_PERM_MAXSIZE+1]; 58 int i, error, len; 59 uid_t ae_id; 60 acl_tag_t ae_tag; 61 acl_perm_t ae_perm, effective_perm, mask_perm; 62 63 buf = strdup(""); 64 65 mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */ 66 for (i = 0; i < acl->acl_cnt; i++) 67 if (acl->acl_entry[i].ae_tag == ACL_MASK) 68 mask_perm = acl->acl_entry[i].ae_perm; 69 70 for (i = 0; i < acl->acl_cnt; i++) { 71 ae_tag = acl->acl_entry[i].ae_tag; 72 ae_id = acl->acl_entry[i].ae_id; 73 ae_perm = acl->acl_entry[i].ae_perm; 74 75 switch(ae_tag) { 76 case ACL_USER_OBJ: 77 error = acl_perm_to_string(ae_perm, 78 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 79 if (error) 80 goto error_label; 81 len = asprintf(&tmpbuf, "%suser::%s\n", buf, 82 perm_buf); 83 if (len == -1) { 84 errno = ENOMEM; 85 goto error_label; 86 } 87 free(buf); 88 buf = tmpbuf; 89 break; 90 91 case ACL_USER: 92 error = acl_perm_to_string(ae_perm, 93 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 94 if (error) 95 goto error_label; 96 97 error = acl_id_to_name(ae_tag, ae_id, UT_NAMESIZE+1, 98 name_buf); 99 if (error) 100 goto error_label; 101 102 effective_perm = ae_perm & mask_perm; 103 if (effective_perm != ae_perm) { 104 error = acl_perm_to_string(effective_perm, 105 ACL_STRING_PERM_MAXSIZE+1, 106 effective_perm_buf); 107 if (error) 108 goto error_label; 109 len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# " 110 "effective: %s\n", 111 buf, name_buf, perm_buf, 112 effective_perm_buf); 113 } else { 114 len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf, 115 name_buf, perm_buf); 116 } 117 if (len == -1) { 118 errno = ENOMEM; 119 goto error_label; 120 } 121 free(buf); 122 buf = tmpbuf; 123 break; 124 125 case ACL_GROUP_OBJ: 126 error = acl_perm_to_string(ae_perm, 127 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 128 if (error) 129 goto error_label; 130 131 effective_perm = ae_perm & mask_perm; 132 if (effective_perm != ae_perm) { 133 error = acl_perm_to_string(effective_perm, 134 ACL_STRING_PERM_MAXSIZE+1, 135 effective_perm_buf); 136 if (error) 137 goto error_label; 138 len = asprintf(&tmpbuf, "%sgroup::%s\t\t# " 139 "effective: %s\n", 140 buf, perm_buf, effective_perm_buf); 141 } else { 142 len = asprintf(&tmpbuf, "%sgroup::%s\n", buf, 143 perm_buf); 144 } 145 if (len == -1) { 146 errno = ENOMEM; 147 goto error_label; 148 } 149 free(buf); 150 buf = tmpbuf; 151 break; 152 153 case ACL_GROUP: 154 error = acl_perm_to_string(ae_perm, 155 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 156 if (error) 157 goto error_label; 158 159 error = acl_id_to_name(ae_tag, ae_id, UT_NAMESIZE+1, 160 name_buf); 161 if (error) 162 goto error_label; 163 164 effective_perm = ae_perm & mask_perm; 165 if (effective_perm != ae_perm) { 166 error = acl_perm_to_string(effective_perm, 167 ACL_STRING_PERM_MAXSIZE+1, 168 effective_perm_buf); 169 if (error) 170 goto error_label; 171 len = asprintf(&tmpbuf, "%sgroup::%s\t\t# " 172 "effective: %s\n", 173 buf, perm_buf, effective_perm_buf); 174 } else { 175 len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf, 176 name_buf, perm_buf); 177 } 178 if (len == -1) { 179 errno = ENOMEM; 180 goto error_label; 181 } 182 free(buf); 183 buf = tmpbuf; 184 break; 185 186 case ACL_MASK: 187 error = acl_perm_to_string(ae_perm, 188 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 189 if (error) 190 goto error_label; 191 192 len = asprintf(&tmpbuf, "%smask::%s\n", buf, 193 perm_buf); 194 if (len == -1) { 195 errno = ENOMEM; 196 goto error_label; 197 } 198 free(buf); 199 buf = tmpbuf; 200 break; 201 202 case ACL_OTHER: 203 error = acl_perm_to_string(ae_perm, 204 ACL_STRING_PERM_MAXSIZE+1, perm_buf); 205 if (error) 206 goto error_label; 207 208 len = asprintf(&tmpbuf, "%sother::%s\n", buf, 209 perm_buf); 210 if (len == -1) { 211 errno = ENOMEM; 212 goto error_label; 213 } 214 free(buf); 215 buf = tmpbuf; 216 break; 217 218 default: 219 free(buf); 220 errno = EINVAL; 221 return (0); 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 (0); 234 } 235