Path: blob/main/lib/libc/posix1e/acl_from_text_nfs4.c
39476 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2008, 2009 Edward Tomasz NapieraĆa <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <stdio.h>28#include <stdlib.h>29#include <unistd.h>30#include <errno.h>31#include <assert.h>32#include <string.h>33#include <pwd.h>34#include <grp.h>35#include <ctype.h>36#include <err.h>37#include <sys/syscall.h>38#include <sys/types.h>39#include <sys/acl.h>4041#include "acl_support.h"4243#define MAX_ENTRY_LENGTH 5124445/*46* Parse the tag field of ACL entry passed as "str". If qualifier47* needs to follow, then the variable referenced by "need_qualifier"48* is set to 1, otherwise it's set to 0.49*/50static int51parse_tag(const char *str, acl_entry_t entry, int *need_qualifier)52{5354assert(need_qualifier != NULL);55*need_qualifier = 0;5657if (strcmp(str, "owner@") == 0)58return (acl_set_tag_type(entry, ACL_USER_OBJ));59if (strcmp(str, "group@") == 0)60return (acl_set_tag_type(entry, ACL_GROUP_OBJ));61if (strcmp(str, "everyone@") == 0)62return (acl_set_tag_type(entry, ACL_EVERYONE));6364*need_qualifier = 1;6566if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0)67return (acl_set_tag_type(entry, ACL_USER));68if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0)69return (acl_set_tag_type(entry, ACL_GROUP));7071warnx("malformed ACL: invalid \"tag\" field");7273return (-1);74}7576/*77* Parse the qualifier field of ACL entry passed as "str".78* If user or group name cannot be resolved, then the variable79* referenced by "need_qualifier" is set to 1; it will be checked80* later to figure out whether the appended_id is required.81*/82static int83parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier)84{85int qualifier_length, error;86uid_t id;87acl_tag_t tag;8889assert(need_qualifier != NULL);90*need_qualifier = 0;9192qualifier_length = strlen(str);9394if (qualifier_length == 0) {95warnx("malformed ACL: empty \"qualifier\" field");96return (-1);97}9899error = acl_get_tag_type(entry, &tag);100if (error)101return (error);102103error = _acl_name_to_id(tag, str, &id);104if (error) {105*need_qualifier = 1;106return (0);107}108109return (acl_set_qualifier(entry, &id));110}111112static int113parse_access_mask(char *str, acl_entry_t entry)114{115int error;116acl_perm_t perm;117118error = _nfs4_parse_access_mask(str, &perm);119if (error)120return (error);121122error = acl_set_permset(entry, &perm);123124return (error);125}126127static int128parse_flags(char *str, acl_entry_t entry)129{130int error;131acl_flag_t flags;132133error = _nfs4_parse_flags(str, &flags);134if (error)135return (error);136137error = acl_set_flagset_np(entry, &flags);138139return (error);140}141142static int143parse_entry_type(const char *str, acl_entry_t entry)144{145146if (strcmp(str, "allow") == 0)147return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW));148if (strcmp(str, "deny") == 0)149return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY));150if (strcmp(str, "audit") == 0)151return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT));152if (strcmp(str, "alarm") == 0)153return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM));154155warnx("malformed ACL: invalid \"type\" field");156157return (-1);158}159160static int161parse_appended_id(char *str, acl_entry_t entry)162{163int qualifier_length;164char *end;165id_t id;166167qualifier_length = strlen(str);168if (qualifier_length == 0) {169warnx("malformed ACL: \"appended id\" field present, "170"but empty");171return (-1);172}173174id = strtod(str, &end);175if (end - str != qualifier_length) {176warnx("malformed ACL: appended id is not a number");177return (-1);178}179180return (acl_set_qualifier(entry, &id));181}182183static int184number_of_colons(const char *str)185{186int count = 0;187188while (*str != '\0') {189if (*str == ':')190count++;191192str++;193}194195return (count);196}197198int199_nfs4_acl_entry_from_text(acl_t aclp, char *str)200{201int error, need_qualifier;202acl_entry_t entry;203char *field, *qualifier_field;204205error = acl_create_entry(&aclp, &entry);206if (error)207return (error);208209assert(_entry_brand(entry) == ACL_BRAND_NFS4);210211if (str == NULL)212goto truncated_entry;213field = strsep(&str, ":");214215field = string_skip_whitespace(field);216if ((*field == '\0') && (!str)) {217/*218* Is an entirely comment line, skip to next219* comma.220*/221return (0);222}223224error = parse_tag(field, entry, &need_qualifier);225if (error)226goto malformed_field;227228if (need_qualifier) {229if (str == NULL)230goto truncated_entry;231qualifier_field = field = strsep(&str, ":");232error = parse_qualifier(field, entry, &need_qualifier);233if (error)234goto malformed_field;235}236237if (str == NULL)238goto truncated_entry;239field = strsep(&str, ":");240error = parse_access_mask(field, entry);241if (error)242goto malformed_field;243244if (str == NULL)245goto truncated_entry;246/* Do we have "flags" field? */247if (number_of_colons(str) > 0) {248field = strsep(&str, ":");249error = parse_flags(field, entry);250if (error)251goto malformed_field;252}253254if (str == NULL)255goto truncated_entry;256field = strsep(&str, ":");257error = parse_entry_type(field, entry);258if (error)259goto malformed_field;260261if (need_qualifier) {262if (str == NULL) {263warnx("malformed ACL: unknown user or group name "264"\"%s\"", qualifier_field);265goto truncated_entry;266}267268error = parse_appended_id(str, entry);269if (error)270goto malformed_field;271}272273return (0);274275truncated_entry:276malformed_field:277acl_delete_entry(aclp, entry);278errno = EINVAL;279return (-1);280}281282283