acl_from_text.c revision 66259
156055Srwatson/*- 266259Srwatson * Copyright (c) 1999, 2000 Robert N. M. Watson 356055Srwatson * All rights reserved. 456055Srwatson * 556055Srwatson * Redistribution and use in source and binary forms, with or without 656055Srwatson * modification, are permitted provided that the following conditions 756055Srwatson * are met: 856055Srwatson * 1. Redistributions of source code must retain the above copyright 956055Srwatson * notice, this list of conditions and the following disclaimer. 1056055Srwatson * 2. Redistributions in binary form must reproduce the above copyright 1156055Srwatson * notice, this list of conditions and the following disclaimer in the 1256055Srwatson * documentation and/or other materials provided with the distribution. 1356055Srwatson * 1456055Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1556055Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1656055Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1756055Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1856055Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1956055Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2056055Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2156055Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2256055Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2356055Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2456055Srwatson * SUCH DAMAGE. 2556055Srwatson * 2666259Srwatson * $FreeBSD: head/lib/libc/posix1e/acl_from_text.c 66259 2000-09-22 16:36:04Z rwatson $ 2756055Srwatson */ 2856055Srwatson/* 2966259Srwatson * acl_from_text: Convert a text-form ACL from a string to an acl_t. 3056055Srwatson */ 3156055Srwatson 3256055Srwatson#include <sys/types.h> 3356055Srwatson#include <sys/acl.h> 3456055Srwatson#include <sys/errno.h> 3556055Srwatson#include <stdio.h> 3656055Srwatson#include <stdlib.h> 3756055Srwatson#include <string.h> 3856055Srwatson 3956055Srwatson#include "acl_support.h" 4056055Srwatson 4156055Srwatsonstatic char * 4256055Srwatsonstring_skip_whitespace(char *string) 4356055Srwatson{ 4456055Srwatson 4556055Srwatson while (*string && ((*string == ' ') || (*string == '\t'))) { 4656055Srwatson string++; 4756055Srwatson } 4856055Srwatson return (string); 4956055Srwatson} 5056055Srwatson 5156055Srwatsonstatic void 5256055Srwatsonstring_trim_trailing_whitespace(char *string) 5356055Srwatson{ 5456055Srwatson char *end; 5556055Srwatson 5656055Srwatson if (*string == '\0') 5756055Srwatson return; 5856055Srwatson 5956055Srwatson end = string + strlen(string) - 1; 6056055Srwatson 6156055Srwatson while (end != string) { 6256055Srwatson if ((*end == ' ') || (*end == '\t')) { 6356055Srwatson *end = '\0'; 6456055Srwatson end--; 6556055Srwatson } else { 6656055Srwatson return; 6756055Srwatson } 6856055Srwatson } 6956055Srwatson 7056055Srwatson return; 7156055Srwatson} 7256055Srwatson 7356055Srwatsonacl_tag_t 7456055Srwatsonacl_string_to_tag(char *tag, char *qualifier) 7556055Srwatson{ 7656055Srwatson 7756055Srwatson if (*qualifier == '\0') { 7856055Srwatson if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 7956055Srwatson return (ACL_USER_OBJ); 8056055Srwatson } else 8156055Srwatson if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 8256055Srwatson return (ACL_GROUP_OBJ); 8356055Srwatson } else 8456055Srwatson if ((!strcmp(tag, "mask")) || (!strcmp(tag, "m"))) { 8556055Srwatson return (ACL_MASK); 8656055Srwatson } else 8756055Srwatson if ((!strcmp(tag, "other")) || (!strcmp(tag, "o"))) { 8856055Srwatson return (ACL_OTHER); 8956055Srwatson } else 9056055Srwatson return(-1); 9156055Srwatson } else { 9256055Srwatson if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 9356055Srwatson return(ACL_USER); 9456055Srwatson } else 9556055Srwatson if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 9656055Srwatson return(ACL_GROUP); 9756055Srwatson } else 9856055Srwatson return(-1); 9956055Srwatson } 10056055Srwatson} 10156055Srwatson 10256055Srwatson/* 10366259Srwatson * acl_from_text -- Convert a string into an ACL. 10466259Srwatson * Postpone most validity checking until the end and call acl_valid() to do 10556055Srwatson * that. 10656055Srwatson */ 10756055Srwatsonacl_t 10856055Srwatsonacl_from_text(const char *buf_p) 10956055Srwatson{ 11056055Srwatson acl_tag_t t; 11156055Srwatson acl_perm_t p; 11256055Srwatson acl_t acl; 11356055Srwatson uid_t id; 11456055Srwatson char *mybuf_p, *line, *cur, *notcomment, *comment, *entry; 11556055Srwatson char *tag, *qualifier, *permission; 11656055Srwatson int error; 11756055Srwatson 11866259Srwatson /* Local copy we can mess up. */ 11956055Srwatson mybuf_p = strdup(buf_p); 12056055Srwatson if (!mybuf_p) { 12156055Srwatson errno = ENOMEM; 12256055Srwatson return(0); 12356055Srwatson } 12456055Srwatson 12556055Srwatson acl = acl_init(3); 12656055Srwatson if (!acl) { 12756055Srwatson free(mybuf_p); 12856055Srwatson errno = ENOMEM; 12956055Srwatson return(0); 13056055Srwatson } 13156055Srwatson 13266259Srwatson /* Outer loop: delimit at \n boundaries. */ 13356055Srwatson cur = mybuf_p; 13456055Srwatson while ((line = strsep(&cur, "\n"))) { 13566259Srwatson /* Now split the line on the first # to strip out comments. */ 13656055Srwatson comment = line; 13756055Srwatson notcomment = strsep(&comment, "#"); 13856055Srwatson 13966259Srwatson /* Inner loop: delimit at ',' boundaries. */ 14056055Srwatson while ((entry = strsep(¬comment, ","))) { 14166259Srwatson /* Now split into three ':' delimited fields. */ 14256055Srwatson tag = strsep(&entry, ":"); 14356055Srwatson if (!tag) { 14456055Srwatson errno = EINVAL; 14556055Srwatson goto error_label; 14656055Srwatson } 14756055Srwatson tag = string_skip_whitespace(tag); 14856055Srwatson if ((*tag == '\0') && (!entry)) { 14956055Srwatson /* 15066259Srwatson * Is an entirely comment line, skip to next 15166259Srwatson * comma. 15256055Srwatson */ 15356055Srwatson continue; 15456055Srwatson } 15556055Srwatson string_trim_trailing_whitespace(tag); 15656055Srwatson 15756055Srwatson qualifier = strsep(&entry, ":"); 15856055Srwatson if (!qualifier) { 15956055Srwatson errno = EINVAL; 16056055Srwatson goto error_label; 16156055Srwatson } 16256055Srwatson qualifier = string_skip_whitespace(qualifier); 16356055Srwatson string_trim_trailing_whitespace(qualifier); 16456055Srwatson 16556055Srwatson permission = strsep(&entry, ":"); 16656055Srwatson if ((!permission) || (entry)) { 16756055Srwatson errno = EINVAL; 16856055Srwatson goto error_label; 16956055Srwatson } 17056055Srwatson permission = string_skip_whitespace(permission); 17156055Srwatson string_trim_trailing_whitespace(permission); 17256055Srwatson 17356055Srwatson t = acl_string_to_tag(tag, qualifier); 17456055Srwatson if (t == -1) { 17556055Srwatson errno = EINVAL; 17656055Srwatson goto error_label; 17756055Srwatson } 17856055Srwatson 17956055Srwatson error = acl_string_to_perm(permission, &p); 18056055Srwatson if (error == -1) { 18156055Srwatson errno = EINVAL; 18256055Srwatson goto error_label; 18356055Srwatson } 18456055Srwatson 18556055Srwatson switch(t) { 18656055Srwatson case ACL_USER_OBJ: 18756055Srwatson case ACL_GROUP_OBJ: 18856055Srwatson case ACL_MASK: 18956055Srwatson case ACL_OTHER: 19056055Srwatson if (*qualifier != '\0') { 19156055Srwatson errno = EINVAL; 19256055Srwatson goto error_label; 19356055Srwatson } 19456055Srwatson id = 0; 19556055Srwatson break; 19656055Srwatson 19756055Srwatson case ACL_USER: 19856055Srwatson case ACL_GROUP: 19956055Srwatson error = acl_name_to_id(t, qualifier, &id); 20056055Srwatson if (error == -1) 20156055Srwatson goto error_label; 20256055Srwatson break; 20356055Srwatson 20456055Srwatson default: 20556055Srwatson errno = EINVAL; 20656055Srwatson goto error_label; 20756055Srwatson } 20856055Srwatson 20956055Srwatson error = acl_add_entry(acl, t, id, p); 21056055Srwatson if (error == -1) 21156055Srwatson goto error_label; 21256055Srwatson } 21356055Srwatson } 21456055Srwatson 21556055Srwatson#if 0 21666259Srwatson /* XXX Should we only return ACLs valid according to acl_valid? */ 21766259Srwatson /* Verify validity of the ACL we read in. */ 21856055Srwatson if (acl_valid(acl) == -1) { 21956055Srwatson errno = EINVAL; 22056055Srwatson goto error_label; 22156055Srwatson } 22256055Srwatson#endif 22356055Srwatson 22456055Srwatson return(acl); 22556055Srwatson 22656055Srwatsonerror_label: 22756055Srwatson acl_free(acl); 22856055Srwatson free(mybuf_p); 22956055Srwatson return(0); 23056055Srwatson} 23156055Srwatson 23256055Srwatson 23356055Srwatson 234