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