acl_from_text.c revision 92986
156055Srwatson/*- 274191Srwatson * Copyright (c) 1999, 2000, 2001 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 */ 2656055Srwatson/* 2766259Srwatson * acl_from_text: Convert a text-form ACL from a string to an acl_t. 2856055Srwatson */ 2956055Srwatson 3092986Sobrien#include <sys/cdefs.h> 3192986Sobrien__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_from_text.c 92986 2002-03-22 21:53:29Z obrien $"); 3292986Sobrien 3356055Srwatson#include <sys/types.h> 3475185Stmm#include "namespace.h" 3556055Srwatson#include <sys/acl.h> 3675185Stmm#include "un-namespace.h" 3756055Srwatson#include <sys/errno.h> 3856055Srwatson#include <stdio.h> 3956055Srwatson#include <stdlib.h> 4056055Srwatson#include <string.h> 4156055Srwatson 4256055Srwatson#include "acl_support.h" 4356055Srwatson 4491032Sjedgarstatic acl_tag_t acl_string_to_tag(char *tag, char *qualifier); 4591032Sjedgarstatic char *string_skip_whitespace(char *string); 4691032Sjedgarstatic void string_trim_trailing_whitespace(char *string); 4791032Sjedgar 4856055Srwatsonstatic char * 4956055Srwatsonstring_skip_whitespace(char *string) 5056055Srwatson{ 5156055Srwatson 5256055Srwatson while (*string && ((*string == ' ') || (*string == '\t'))) { 5356055Srwatson string++; 5456055Srwatson } 5556055Srwatson return (string); 5656055Srwatson} 5756055Srwatson 5856055Srwatsonstatic void 5956055Srwatsonstring_trim_trailing_whitespace(char *string) 6056055Srwatson{ 6156055Srwatson char *end; 6256055Srwatson 6356055Srwatson if (*string == '\0') 6456055Srwatson return; 6556055Srwatson 6656055Srwatson end = string + strlen(string) - 1; 6756055Srwatson 6856055Srwatson while (end != string) { 6956055Srwatson if ((*end == ' ') || (*end == '\t')) { 7056055Srwatson *end = '\0'; 7156055Srwatson end--; 7256055Srwatson } else { 7356055Srwatson return; 7456055Srwatson } 7556055Srwatson } 7656055Srwatson 7756055Srwatson return; 7856055Srwatson} 7956055Srwatson 8091032Sjedgarstatic acl_tag_t 8156055Srwatsonacl_string_to_tag(char *tag, char *qualifier) 8256055Srwatson{ 8356055Srwatson 8456055Srwatson if (*qualifier == '\0') { 8556055Srwatson if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 8656055Srwatson return (ACL_USER_OBJ); 8756055Srwatson } else 8856055Srwatson if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 8956055Srwatson return (ACL_GROUP_OBJ); 9056055Srwatson } else 9156055Srwatson if ((!strcmp(tag, "mask")) || (!strcmp(tag, "m"))) { 9256055Srwatson return (ACL_MASK); 9356055Srwatson } else 9456055Srwatson if ((!strcmp(tag, "other")) || (!strcmp(tag, "o"))) { 9556055Srwatson return (ACL_OTHER); 9656055Srwatson } else 9756055Srwatson return(-1); 9856055Srwatson } else { 9956055Srwatson if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) { 10056055Srwatson return(ACL_USER); 10156055Srwatson } else 10256055Srwatson if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) { 10356055Srwatson return(ACL_GROUP); 10456055Srwatson } else 10556055Srwatson return(-1); 10656055Srwatson } 10756055Srwatson} 10856055Srwatson 10956055Srwatson/* 11066259Srwatson * acl_from_text -- Convert a string into an ACL. 11166259Srwatson * Postpone most validity checking until the end and call acl_valid() to do 11256055Srwatson * that. 11356055Srwatson */ 11456055Srwatsonacl_t 11556055Srwatsonacl_from_text(const char *buf_p) 11656055Srwatson{ 11775928Sjedgar acl_tag_t t; 11875928Sjedgar acl_perm_t p; 11975928Sjedgar acl_t acl; 12075928Sjedgar char *mybuf_p, *line, *cur, *notcomment, *comment, *entry; 12175928Sjedgar char *tag, *qualifier, *permission; 12275928Sjedgar int error; 12375928Sjedgar uid_t id; 12456055Srwatson 12566259Srwatson /* Local copy we can mess up. */ 12656055Srwatson mybuf_p = strdup(buf_p); 12791034Sjedgar if (mybuf_p == NULL) 12871142Srwatson return(NULL); 12956055Srwatson 13056055Srwatson acl = acl_init(3); 13191034Sjedgar if (acl == NULL) { 13256055Srwatson free(mybuf_p); 13371142Srwatson return(NULL); 13456055Srwatson } 13556055Srwatson 13666259Srwatson /* Outer loop: delimit at \n boundaries. */ 13756055Srwatson cur = mybuf_p; 13856055Srwatson while ((line = strsep(&cur, "\n"))) { 13966259Srwatson /* Now split the line on the first # to strip out comments. */ 14056055Srwatson comment = line; 14156055Srwatson notcomment = strsep(&comment, "#"); 14256055Srwatson 14366259Srwatson /* Inner loop: delimit at ',' boundaries. */ 14456055Srwatson while ((entry = strsep(¬comment, ","))) { 14566259Srwatson /* Now split into three ':' delimited fields. */ 14656055Srwatson tag = strsep(&entry, ":"); 14791034Sjedgar if (tag == NULL) { 14856055Srwatson errno = EINVAL; 14956055Srwatson goto error_label; 15056055Srwatson } 15156055Srwatson tag = string_skip_whitespace(tag); 15256055Srwatson if ((*tag == '\0') && (!entry)) { 15356055Srwatson /* 15466259Srwatson * Is an entirely comment line, skip to next 15566259Srwatson * comma. 15656055Srwatson */ 15756055Srwatson continue; 15856055Srwatson } 15956055Srwatson string_trim_trailing_whitespace(tag); 16056055Srwatson 16156055Srwatson qualifier = strsep(&entry, ":"); 16291034Sjedgar if (qualifier == NULL) { 16356055Srwatson errno = EINVAL; 16456055Srwatson goto error_label; 16556055Srwatson } 16656055Srwatson qualifier = string_skip_whitespace(qualifier); 16756055Srwatson string_trim_trailing_whitespace(qualifier); 16856055Srwatson 16956055Srwatson permission = strsep(&entry, ":"); 17091034Sjedgar if (permission == NULL || entry) { 17156055Srwatson errno = EINVAL; 17256055Srwatson goto error_label; 17356055Srwatson } 17456055Srwatson permission = string_skip_whitespace(permission); 17556055Srwatson string_trim_trailing_whitespace(permission); 17656055Srwatson 17756055Srwatson t = acl_string_to_tag(tag, qualifier); 17856055Srwatson if (t == -1) { 17956055Srwatson errno = EINVAL; 18056055Srwatson goto error_label; 18156055Srwatson } 18256055Srwatson 18374191Srwatson error = _posix1e_acl_string_to_perm(permission, &p); 18456055Srwatson if (error == -1) { 18556055Srwatson errno = EINVAL; 18656055Srwatson goto error_label; 18756055Srwatson } 18856055Srwatson 18956055Srwatson switch(t) { 19056055Srwatson case ACL_USER_OBJ: 19156055Srwatson case ACL_GROUP_OBJ: 19256055Srwatson case ACL_MASK: 19356055Srwatson case ACL_OTHER: 19456055Srwatson if (*qualifier != '\0') { 19556055Srwatson errno = EINVAL; 19656055Srwatson goto error_label; 19756055Srwatson } 19856055Srwatson id = 0; 19956055Srwatson break; 20056055Srwatson 20156055Srwatson case ACL_USER: 20256055Srwatson case ACL_GROUP: 20374191Srwatson error = _posix1e_acl_name_to_id(t, qualifier, 20474191Srwatson &id); 20556055Srwatson if (error == -1) 20656055Srwatson goto error_label; 20756055Srwatson break; 20856055Srwatson 20956055Srwatson default: 21056055Srwatson errno = EINVAL; 21156055Srwatson goto error_label; 21256055Srwatson } 21356055Srwatson 21474191Srwatson error = _posix1e_acl_add_entry(acl, t, id, p); 21556055Srwatson if (error == -1) 21656055Srwatson goto error_label; 21756055Srwatson } 21856055Srwatson } 21956055Srwatson 22056055Srwatson#if 0 22166259Srwatson /* XXX Should we only return ACLs valid according to acl_valid? */ 22266259Srwatson /* Verify validity of the ACL we read in. */ 22356055Srwatson if (acl_valid(acl) == -1) { 22456055Srwatson errno = EINVAL; 22556055Srwatson goto error_label; 22656055Srwatson } 22756055Srwatson#endif 22856055Srwatson 22956055Srwatson return(acl); 23056055Srwatson 23156055Srwatsonerror_label: 23256055Srwatson acl_free(acl); 23356055Srwatson free(mybuf_p); 23471142Srwatson return(NULL); 23556055Srwatson} 23656055Srwatson 23756055Srwatson 23856055Srwatson 239