acl_from_text.c revision 91034
1/*- 2 * Copyright (c) 1999, 2000, 2001 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: head/lib/libc/posix1e/acl_from_text.c 91034 2002-02-21 23:17:19Z jedgar $ 27 */ 28/* 29 * acl_from_text: Convert a text-form ACL from a string to an acl_t. 30 */ 31 32#include <sys/types.h> 33#include "namespace.h" 34#include <sys/acl.h> 35#include "un-namespace.h" 36#include <sys/errno.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40 41#include "acl_support.h" 42 43static acl_tag_t acl_string_to_tag(char *tag, char *qualifier); 44static char *string_skip_whitespace(char *string); 45static void string_trim_trailing_whitespace(char *string); 46 47static char * 48string_skip_whitespace(char *string) 49{ 50 51 while (*string && ((*string == ' ') || (*string == '\t'))) { 52 string++; 53 } 54 return (string); 55} 56 57static void 58string_trim_trailing_whitespace(char *string) 59{ 60 char *end; 61 62 if (*string == '\0') 63 return; 64 65 end = string + strlen(string) - 1; 66 67 while (end != string) { 68 if ((*end == ' ') || (*end == '\t')) { 69 *end = '\0'; 70 end--; 71 } else { 72 return; 73 } 74 } 75 76 return; 77} 78 79static acl_tag_t 80acl_string_to_tag(char *tag, char *qualifier) 81{ 82 83 if (*qualifier == '\0') { 84 if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 85 return (ACL_USER_OBJ); 86 } else 87 if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 88 return (ACL_GROUP_OBJ); 89 } else 90 if ((!strcmp(tag, "mask")) || (!strcmp(tag, "m"))) { 91 return (ACL_MASK); 92 } else 93 if ((!strcmp(tag, "other")) || (!strcmp(tag, "o"))) { 94 return (ACL_OTHER); 95 } else 96 return(-1); 97 } else { 98 if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 99 return(ACL_USER); 100 } else 101 if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 102 return(ACL_GROUP); 103 } else 104 return(-1); 105 } 106} 107 108/* 109 * acl_from_text -- Convert a string into an ACL. 110 * Postpone most validity checking until the end and call acl_valid() to do 111 * that. 112 */ 113acl_t 114acl_from_text(const char *buf_p) 115{ 116 acl_tag_t t; 117 acl_perm_t p; 118 acl_t acl; 119 char *mybuf_p, *line, *cur, *notcomment, *comment, *entry; 120 char *tag, *qualifier, *permission; 121 int error; 122 uid_t id; 123 124 /* Local copy we can mess up. */ 125 mybuf_p = strdup(buf_p); 126 if (mybuf_p == NULL) 127 return(NULL); 128 129 acl = acl_init(3); 130 if (acl == NULL) { 131 free(mybuf_p); 132 return(NULL); 133 } 134 135 /* Outer loop: delimit at \n boundaries. */ 136 cur = mybuf_p; 137 while ((line = strsep(&cur, "\n"))) { 138 /* Now split the line on the first # to strip out comments. */ 139 comment = line; 140 notcomment = strsep(&comment, "#"); 141 142 /* Inner loop: delimit at ',' boundaries. */ 143 while ((entry = strsep(¬comment, ","))) { 144 /* Now split into three ':' delimited fields. */ 145 tag = strsep(&entry, ":"); 146 if (tag == NULL) { 147 errno = EINVAL; 148 goto error_label; 149 } 150 tag = string_skip_whitespace(tag); 151 if ((*tag == '\0') && (!entry)) { 152 /* 153 * Is an entirely comment line, skip to next 154 * comma. 155 */ 156 continue; 157 } 158 string_trim_trailing_whitespace(tag); 159 160 qualifier = strsep(&entry, ":"); 161 if (qualifier == NULL) { 162 errno = EINVAL; 163 goto error_label; 164 } 165 qualifier = string_skip_whitespace(qualifier); 166 string_trim_trailing_whitespace(qualifier); 167 168 permission = strsep(&entry, ":"); 169 if (permission == NULL || entry) { 170 errno = EINVAL; 171 goto error_label; 172 } 173 permission = string_skip_whitespace(permission); 174 string_trim_trailing_whitespace(permission); 175 176 t = acl_string_to_tag(tag, qualifier); 177 if (t == -1) { 178 errno = EINVAL; 179 goto error_label; 180 } 181 182 error = _posix1e_acl_string_to_perm(permission, &p); 183 if (error == -1) { 184 errno = EINVAL; 185 goto error_label; 186 } 187 188 switch(t) { 189 case ACL_USER_OBJ: 190 case ACL_GROUP_OBJ: 191 case ACL_MASK: 192 case ACL_OTHER: 193 if (*qualifier != '\0') { 194 errno = EINVAL; 195 goto error_label; 196 } 197 id = 0; 198 break; 199 200 case ACL_USER: 201 case ACL_GROUP: 202 error = _posix1e_acl_name_to_id(t, qualifier, 203 &id); 204 if (error == -1) 205 goto error_label; 206 break; 207 208 default: 209 errno = EINVAL; 210 goto error_label; 211 } 212 213 error = _posix1e_acl_add_entry(acl, t, id, p); 214 if (error == -1) 215 goto error_label; 216 } 217 } 218 219#if 0 220 /* XXX Should we only return ACLs valid according to acl_valid? */ 221 /* Verify validity of the ACL we read in. */ 222 if (acl_valid(acl) == -1) { 223 errno = EINVAL; 224 goto error_label; 225 } 226#endif 227 228 return(acl); 229 230error_label: 231 acl_free(acl); 232 free(mybuf_p); 233 return(NULL); 234} 235 236 237 238