acl_from_text.c revision 56055
156055Srwatson/*- 256055Srwatson * Copyright (c) 1999 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 * $FreeBSD: head/lib/libc/posix1e/acl_from_text.c 56055 2000-01-15 19:44:27Z rwatson $ 2756055Srwatson */ 2856055Srwatson/* 2956055Srwatson * 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 4156055Srwatsonenum PARSE_MODE { 4256055Srwatson PM_BASE, /* initial, begin line, or after , */ 4356055Srwatson PM_QUALIFIER, /* in qualifier field */ 4456055Srwatson PM_PERM, /* in permission field */ 4556055Srwatson PM_COMMENT, /* in comment */ 4656055Srwatson}; 4756055Srwatson 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 8056055Srwatsonacl_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/* 11056055Srwatson * acl_from_text -- convert a string into an ACL 11156055Srwatson * postpone most validity checking until the end and cal acl_valid to do 11256055Srwatson * that. 11356055Srwatson */ 11456055Srwatsonacl_t 11556055Srwatsonacl_from_text(const char *buf_p) 11656055Srwatson{ 11756055Srwatson acl_tag_t t; 11856055Srwatson acl_perm_t p; 11956055Srwatson acl_t acl; 12056055Srwatson uid_t id; 12156055Srwatson char *mybuf_p, *line, *cur, *notcomment, *comment, *entry; 12256055Srwatson char *tag, *qualifier, *permission; 12356055Srwatson int error; 12456055Srwatson 12556055Srwatson /* local copy we can mess up */ 12656055Srwatson mybuf_p = strdup(buf_p); 12756055Srwatson if (!mybuf_p) { 12856055Srwatson errno = ENOMEM; 12956055Srwatson return(0); 13056055Srwatson } 13156055Srwatson 13256055Srwatson acl = acl_init(3); 13356055Srwatson if (!acl) { 13456055Srwatson free(mybuf_p); 13556055Srwatson errno = ENOMEM; 13656055Srwatson return(0); 13756055Srwatson } 13856055Srwatson 13956055Srwatson /* outer loop: delimit at \n boundaries */ 14056055Srwatson cur = mybuf_p; 14156055Srwatson while ((line = strsep(&cur, "\n"))) { 14256055Srwatson /* now split the line on the first # to strip out comments */ 14356055Srwatson comment = line; 14456055Srwatson notcomment = strsep(&comment, "#"); 14556055Srwatson 14656055Srwatson /* inner loop: delimit at , boundaries */ 14756055Srwatson while ((entry = strsep(¬comment, ","))) { 14856055Srwatson /* now split into three :-delimited fields */ 14956055Srwatson tag = strsep(&entry, ":"); 15056055Srwatson if (!tag) { 15156055Srwatson /* printf("no tag\n"); */ 15256055Srwatson errno = EINVAL; 15356055Srwatson goto error_label; 15456055Srwatson } 15556055Srwatson tag = string_skip_whitespace(tag); 15656055Srwatson if ((*tag == '\0') && (!entry)) { 15756055Srwatson /* 15856055Srwatson * is an entirely comment line, skip to next 15956055Srwatson * comma 16056055Srwatson */ 16156055Srwatson continue; 16256055Srwatson } 16356055Srwatson string_trim_trailing_whitespace(tag); 16456055Srwatson 16556055Srwatson qualifier = strsep(&entry, ":"); 16656055Srwatson if (!qualifier) { 16756055Srwatson /* printf("no qualifier\n"); */ 16856055Srwatson errno = EINVAL; 16956055Srwatson goto error_label; 17056055Srwatson } 17156055Srwatson qualifier = string_skip_whitespace(qualifier); 17256055Srwatson string_trim_trailing_whitespace(qualifier); 17356055Srwatson 17456055Srwatson permission = strsep(&entry, ":"); 17556055Srwatson if ((!permission) || (entry)) { 17656055Srwatson /* printf("no permission, or more stuff\n"); */ 17756055Srwatson errno = EINVAL; 17856055Srwatson goto error_label; 17956055Srwatson } 18056055Srwatson permission = string_skip_whitespace(permission); 18156055Srwatson string_trim_trailing_whitespace(permission); 18256055Srwatson 18356055Srwatson /* printf("[%s/%s/%s]\n", tag, qualifier, 18456055Srwatson permission); */ 18556055Srwatson 18656055Srwatson t = acl_string_to_tag(tag, qualifier); 18756055Srwatson if (t == -1) { 18856055Srwatson errno = EINVAL; 18956055Srwatson goto error_label; 19056055Srwatson } 19156055Srwatson 19256055Srwatson error = acl_string_to_perm(permission, &p); 19356055Srwatson if (error == -1) { 19456055Srwatson errno = EINVAL; 19556055Srwatson goto error_label; 19656055Srwatson } 19756055Srwatson 19856055Srwatson switch(t) { 19956055Srwatson case ACL_USER_OBJ: 20056055Srwatson case ACL_GROUP_OBJ: 20156055Srwatson case ACL_MASK: 20256055Srwatson case ACL_OTHER: 20356055Srwatson if (*qualifier != '\0') { 20456055Srwatson errno = EINVAL; 20556055Srwatson goto error_label; 20656055Srwatson } 20756055Srwatson id = 0; 20856055Srwatson break; 20956055Srwatson 21056055Srwatson case ACL_USER: 21156055Srwatson case ACL_GROUP: 21256055Srwatson error = acl_name_to_id(t, qualifier, &id); 21356055Srwatson if (error == -1) 21456055Srwatson goto error_label; 21556055Srwatson break; 21656055Srwatson 21756055Srwatson default: 21856055Srwatson errno = EINVAL; 21956055Srwatson goto error_label; 22056055Srwatson } 22156055Srwatson 22256055Srwatson error = acl_add_entry(acl, t, id, p); 22356055Srwatson if (error == -1) 22456055Srwatson goto error_label; 22556055Srwatson } 22656055Srwatson } 22756055Srwatson 22856055Srwatson#if 0 22956055Srwatson /* XXX should we only return ACLs valid according to acl_valid? */ 23056055Srwatson /* verify validity of the ACL we read in */ 23156055Srwatson if (acl_valid(acl) == -1) { 23256055Srwatson errno = EINVAL; 23356055Srwatson goto error_label; 23456055Srwatson } 23556055Srwatson#endif 23656055Srwatson 23756055Srwatson return(acl); 23856055Srwatson 23956055Srwatsonerror_label: 24056055Srwatson acl_free(acl); 24156055Srwatson free(mybuf_p); 24256055Srwatson return(0); 24356055Srwatson} 24456055Srwatson 24556055Srwatson 24656055Srwatson 247