2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A *
2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A%{
2N/A#include <sys/acl.h>
2N/A#include <aclutils.h>
2N/A#include <idmap.h>
2N/A#include <errno.h>
2N/A#include "acl.tab.h"
2N/A
2N/A#ifdef input
2N/A#undef input
2N/A#endif
2N/A
2N/A#ifdef unput
2N/A#undef unput
2N/A#endif
2N/A
2N/Aint grab_string(char *terminators);
2N/Astatic int input();
2N/Astatic void unput(int);
2N/A
2N/Aint
2N/Ayyerror(const char *s)
2N/A{
2N/A return (0);
2N/A}
2N/A
2N/Aint
2N/Ayywrap(void)
2N/A{
2N/A return (1);
2N/A}
2N/A
2N/Aextern char *yybuf;
2N/Aint yybufpos;
2N/A
2N/A/*
2N/A * Used for tracking allocated strings while walking through an ACL.
2N/A */
2N/Astruct yystrings {
2N/A char *y_logname; /* user/group name from LOGNAME */
2N/A char *y_perms; /* permssions from PERM_TOK */
2N/A char *y_iflags; /* iflags from INHERIT_TOK */
2N/A char *y_idstr; /* string of appened id */
2N/A} yystrings;
2N/A
2N/A%}
2N/A
2N/A%e 1500
2N/A%s TS NS PS AIS AS US ES
2N/A%p 5000
2N/A
2N/A/*
2N/A * TS = type state
2N/A * NS = name state
2N/A * PS = Permission state
2N/A * AIS = Allow/deny/inheritance state
2N/A * AS = Allow state (only used when inheritance detected)
2N/A * US = UID/GID state
2N/A * ES = End state
2N/A */
2N/A
2N/AID [0-9]+
2N/ASID S-[^:,\n]+
2N/ALOGNAME [^:]+:
2N/APERM_STR [rRwWxpdDaAcCos-]+
2N/AINHERIT_STR [fdinFSI-]+
2N/A
2N/A%%
2N/A
2N/A<TS>user: {
2N/A BEGIN NS;
2N/A yylval.val = USER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>usersid: {
2N/A BEGIN NS;
2N/A yylval.val = USER_SID_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>owner@: {
2N/A BEGIN PS;
2N/A yylval.val = OWNERAT_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>group@: {
2N/A BEGIN PS;
2N/A yylval.val = GROUPAT_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>everyone@: {
2N/A BEGIN PS;
2N/A yylval.val = EVERYONEAT_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>group: {
2N/A BEGIN NS;
2N/A yylval.val = GROUP_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>groupsid: {
2N/A BEGIN NS;
2N/A yylval.val = GROUP_SID_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>sid: {
2N/A BEGIN NS;
2N/A yylval.val = GROUP_SID_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>mask: {
2N/A BEGIN PS;
2N/A yylval.val = MASK_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>mask:: {
2N/A BEGIN PS;
2N/A yylval.val = MASK_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>other: {
2N/A BEGIN PS;
2N/A yylval.val = OTHER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>other:: {
2N/A BEGIN PS;
2N/A yylval.val = OTHER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultuser: {
2N/A BEGIN NS;
2N/A yylval.val = DEFAULT_USER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>default:user: {
2N/A BEGIN NS;
2N/A yylval.val = DEFAULT_USER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultgroup: {
2N/A BEGIN NS;
2N/A yylval.val = DEFAULT_GROUP_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>default:group: {
2N/A BEGIN NS;
2N/A yylval.val = DEFAULT_GROUP_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultother: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_OTHER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultother:: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_OTHER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>default:other: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_OTHER_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultmask: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_MASK_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>defaultmask:: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_MASK_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>default:mask: {
2N/A BEGIN PS;
2N/A yylval.val = DEFAULT_MASK_TOK;
2N/A return (ENTRY_TYPE);
2N/A }
2N/A<TS>"\n" {
2N/A return (NL);
2N/A }
2N/A<TS>. {
2N/A if (grab_string(":,\n") != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Failed to retrieve"
2N/A " error string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Invalid ACL entry "
2N/A "type '%s' specified.\n"), yylval.str);
2N/A free(yylval.str);
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<NS>: {
2N/A BEGIN PS;
2N/A return (COLON);
2N/A }
2N/A<NS>{LOGNAME} {
2N/A yylval.str = strdup(yytext);
2N/A if (yylval.str == NULL) {
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A yylval.str[strlen(yylval.str) -1] = '\0';
2N/A yystrings.y_logname = yylval.str;
2N/A BEGIN PS;
2N/A return (IDNAME);
2N/A }
2N/A<NS>"\n" {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Missing user/group name"
2N/A " from ACL specification.\n"));
2N/A yylval.val = EACL_MISSING_FIELDS;
2N/A return (ERROR);
2N/A }
2N/A<NS>. {
2N/A int error;
2N/A
2N/A error = grab_string(":,\n");
2N/A if (error != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Invalid user/group "
2N/A "name specification.\n"));
2N/A yylval.val = EACL_INVALID_USER_GROUP;
2N/A } else {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "User/Group name "
2N/A "'%s' not specified correctly.\n"),
2N/A yylval.str);
2N/A free(yylval.str);
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A }
2N/A return (ERROR);
2N/A }
2N/A<PS>read_data/[:/,] {
2N/A yylval.val = ACE_READ_DATA;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>list_directory/[:/,] {
2N/A yylval.val = ACE_LIST_DIRECTORY;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_data/[:/,] {
2N/A yylval.val = ACE_WRITE_DATA;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>add_file/[:/,] {
2N/A yylval.val = ACE_ADD_FILE;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>append_data/[:/,] {
2N/A yylval.val = ACE_APPEND_DATA;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>add_subdirectory/[:/,] {
2N/A yylval.val = ACE_ADD_SUBDIRECTORY;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>read_xattr/[:/,] {
2N/A yylval.val = ACE_READ_NAMED_ATTRS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_xattr/[:/,] {
2N/A yylval.val = ACE_WRITE_NAMED_ATTRS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>execute/[:/,] {
2N/A yylval.val = ACE_EXECUTE;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>delete_child/[:/,] {
2N/A yylval.val = ACE_DELETE_CHILD;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>read_attributes/[:/,] {
2N/A yylval.val = ACE_READ_ATTRIBUTES;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_attributes/[:/,] {
2N/A yylval.val = ACE_WRITE_ATTRIBUTES;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>delete/[:/,] {
2N/A yylval.val = ACE_DELETE;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>read_acl/[:/,] {
2N/A yylval.val = ACE_READ_ACL;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_acl/[:/,] {
2N/A yylval.val = ACE_WRITE_ACL;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_owner/[:/,] {
2N/A yylval.val = ACE_WRITE_OWNER;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>synchronize/[:/,] {
2N/A yylval.val = ACE_SYNCHRONIZE;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>read_set/[:/,] {
2N/A yylval.val = ACE_READ_PERMS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>write_set/[:/,] {
2N/A yylval.val = ACE_WRITE_PERMS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>modify_set/[:/,] {
2N/A yylval.val = ACE_MODIFY_PERMS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>full_set/[:/,] {
2N/A yylval.val = ACE_ALL_PERMS;
2N/A return (ACE_PERM);
2N/A }
2N/A<PS>{PERM_STR}/[:,\n] {
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A yylval.str = strdup(yytext);
2N/A if (yylval.str == NULL) {
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A yystrings.y_perms = yylval.str;
2N/A
2N/A /*
2N/A * aclent are done after permissions.
2N/A */
2N/A if (isdigit(c))
2N/A BEGIN US;
2N/A else if (c != ':')
2N/A BEGIN ES;
2N/A
2N/A return (PERM_TOK);
2N/A }
2N/A<PS>"/:" {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Invalid permission /: specified.\n"));
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<PS>: {
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (isdigit(c))
2N/A BEGIN (US);
2N/A else
2N/A BEGIN AIS;
2N/A return (COLON);
2N/A }
2N/A<PS>"/" {
2N/A return (SLASH);
2N/A }
2N/A<PS>"\n" {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "ACL entry is missing "
2N/A "permission fields.\n"));
2N/A yylval.val = EACL_MISSING_FIELDS;
2N/A return (ERROR);
2N/A }
2N/A<PS>"," {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "The ',' is not a valid permission field "
2N/A "separator.\nThe comma is used to separate "
2N/A "access control entries.\nSee acl(5) for "
2N/A "examples of specifying ACL entries.\n"));
2N/A yylval.val = EACL_PERM_MASK_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<PS>. {
2N/A if (grab_string("/:,\n") != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Failed to retrieve"
2N/A " error string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Invalid permission(s) '%s' "
2N/A "specified.\n"), yylval.str);
2N/A free(yylval.str);
2N/A yylval.val = EACL_PERM_MASK_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<AS>allow/[:,\n] {
2N/A
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AS>deny/[:,\n] {
2N/A
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AS>audit/[:,\n] {
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AS>alarm/[:,\n] {
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AS>: {
2N/A
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Invalid Access type "
2N/A "specified.\nThe field is blank, when"
2N/A " it should be either allow or deny.\n"));
2N/A yylval.val = EACL_INVALID_ACCESS_TYPE;
2N/A return (ERROR);
2N/A }
2N/A<AS>"\n" {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "ACL access type must be specified.\n"));
2N/A yylval.val = EACL_INVALID_ACCESS_TYPE;
2N/A return (ERROR);
2N/A }
2N/A<AS>. {
2N/A if (yytext[0] != '\n' && yytext[0] != '\0') {
2N/A if (grab_string(":,\n") != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Failed to "
2N/A "retrieve error "
2N/A "string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Invalid access "
2N/A "type '%s' specified.\n"),
2N/A yylval.str);
2N/A } else {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "No access "
2N/A "type specified.\n"), yylval.str);
2N/A }
2N/A
2N/A free(yylval.str);
2N/A yylval.val = EACL_INVALID_ACCESS_TYPE;
2N/A return (ERROR);
2N/A }
2N/A<AIS>allow/[:,\n] {
2N/A
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AIS>deny/[:,\n] {
2N/A
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AIS>audit/[:,\n] {
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AIS>alarm/[:,\n] {
2N/A
2N/A int c;
2N/A
2N/A c = input();
2N/A unput(c);
2N/A if (c == ',' || c == '\n')
2N/A BEGIN ES;
2N/A else
2N/A BEGIN US;
2N/A
2N/A yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
2N/A return (ACCESS_TYPE);
2N/A }
2N/A<AIS>file_inherit/[:/,] {
2N/A yylval.val = ACE_FILE_INHERIT_ACE;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>dir_inherit/[:/,] {
2N/A yylval.val = ACE_DIRECTORY_INHERIT_ACE;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>no_propagate/[/:,] {
2N/A yylval.val = ACE_NO_PROPAGATE_INHERIT_ACE;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>inherit_only/[/:,] {
2N/A yylval.val = ACE_INHERIT_ONLY_ACE;
2N/A return (ACE_INHERIT);
2N/A }
2N/A
2N/A<AIS>successful_access/[/:,] {
2N/A yylval.val = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>failed_access/[/:,] {
2N/A yylval.val = ACE_FAILED_ACCESS_ACE_FLAG;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>inherited/[/:,] {
2N/A yylval.val = ACE_INHERITED_ACE;
2N/A return (ACE_INHERIT);
2N/A }
2N/A<AIS>{INHERIT_STR}/[:] {
2N/A yylval.str = strdup(yytext);
2N/A if (yylval.str == NULL) {
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A yystrings.y_iflags = yylval.str;
2N/A return (INHERIT_TOK);
2N/A }
2N/A<AIS>: {
2N/A /*
2N/A * Only inheritance fields should hit this.
2N/A * allow/deny fields match on ":" as part
2N/A * of the regexp.
2N/A */
2N/A BEGIN AS;
2N/A return (COLON);
2N/A }
2N/A<AIS>"/" {
2N/A return (SLASH);
2N/A }
2N/A<AIS>"\n" {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Invalid ACL specification."
2N/A "\nWas expecting to find"
2N/A " access type or inheritance flags.\n"),
2N/A yylval.str);
2N/A yylval.val = EACL_UNKNOWN_DATA;
2N/A return (ERROR);
2N/A }
2N/A<AIS>"," {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "The ',' is not a valid inheritance field "
2N/A "separator.\nThe comma is used to separate "
2N/A "access control entries.\nSee acl(5) for "
2N/A "examples of specifying ACL entries.\n"));
2N/A yylval.val = EACL_INVALID_ACCESS_TYPE;
2N/A return (ERROR);
2N/A }
2N/A<AIS>. {
2N/A if (yytext[0] != '\n' && yytext[0] != '\0') {
2N/A if (grab_string(":,\n") != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Failed to "
2N/A "retrieve error "
2N/A "string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Invalid inheritance or"
2N/A " access type '%s' specified.\n"),
2N/A yylval.str);
2N/A } else {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "No inheritance or "
2N/A "access type specified.\n"),
2N/A yylval.str);
2N/A }
2N/A
2N/A free(yylval.str);
2N/A yylval.val = EACL_INVALID_ACCESS_TYPE;
2N/A return (ERROR);
2N/A }
2N/A<US>{ID}/[,\n] {
2N/A BEGIN ES;
2N/A yylval.str = strdup(yytext);
2N/A if (yylval.str == NULL) {
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A yystrings.y_idstr = yylval.str;
2N/A return (ID);
2N/A }
2N/A<US>{SID}/[,\n] {
2N/A BEGIN ES;
2N/A yylval.str = strdup(yytext);
2N/A if (yylval.str == NULL) {
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A yystrings.y_idstr = yylval.str;
2N/A return (SID);
2N/A }
2N/A<US>: {
2N/A return (COLON);
2N/A }
2N/A<US>{INHERIT_STR} { /*
2N/A * Catch specific error to produce
2N/A * nice message for users who are trying
2N/A * to use old syntax format which had
2N/A * inheritance flags as the last field.
2N/A */
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Access type should be final"
2N/A " field in ACL specification.\n"));
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<US>. {
2N/A if (grab_string(",\n") != 0) {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Failed to retrieve"
2N/A " error string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Invalid data ':%s' specified"
2N/A " on end of ACL.\n"), yylval.str);
2N/A free(yylval.str);
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<US>"\n" {
2N/A acl_error(dgettext(TEXT_DOMAIN,
2N/A "Missing fields in ACL "
2N/A "specification.\nWas expecting to find "
2N/A "uid/gid.\n"));
2N/A yylval.val = EACL_ENTRY_ERROR;
2N/A return (ERROR);
2N/A }
2N/A<ES>"," {
2N/A BEGIN TS;
2N/A return (COMMA);
2N/A }
2N/A<ES>. {
2N/A if (grab_string("/:,\n") != 0) {
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Failed to retrieve error"
2N/A " string.\n"));
2N/A yylval.val = EACL_MEM_ERROR;
2N/A return (ERROR);
2N/A }
2N/A acl_error(
2N/A dgettext(TEXT_DOMAIN,
2N/A "Unrecognized data '%s' found"
2N/A " in ACL specification.\n"), yylval.str);
2N/A free(yylval.str);
2N/A yylval.val = EACL_UNKNOWN_DATA;
2N/A return (ERROR);
2N/A }
2N/A<ES>"\n" {
2N/A return (NL);
2N/A }
2N/A%%
2N/A
2N/A
2N/A/*
2N/A * Pull string up to terminator off of input string.
2N/A * used for retrieving illegal data in ACL specification.
2N/A *
2N/A * The first set of characters is retrieved from yytext.
2N/A * subsequent characters are pulled from the input stream,
2N/A * until either EOF or one of the requested terminators is scene.
2N/A * Result is returned in yylval.str which is malloced.
2N/A */
2N/Aint
2N/Agrab_string(char *terminators)
2N/A{
2N/A int c;
2N/A int done = 0;
2N/A int cnt;
2N/A int alloced;
2N/A int error = 0;
2N/A char *ptr;
2N/A
2N/A cnt = strlen(yytext);
2N/A yylval.str = calloc(cnt + 1, sizeof (char));
2N/A if (yylval.str == NULL) {
2N/A return (1);
2N/A }
2N/A alloced = cnt + 1;
2N/A strcpy(yylval.str, yytext);
2N/A
2N/A do {
2N/A c = input();
2N/A if (c == EOF)
2N/A break;
2N/A
2N/A for (ptr = terminators; *ptr; ptr++) {
2N/A if (c == *ptr) {
2N/A done = 1;
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (done)
2N/A break;
2N/A
2N/A if (cnt + 1 >= alloced) {
2N/A yylval.str = realloc(yylval.str,
2N/A alloced + 80);
2N/A alloced += 80;
2N/A if (yylval.str == NULL)
2N/A return (1);
2N/A
2N/A memset(yylval.str + cnt, 0,
2N/A alloced - strlen(yylval.str));
2N/A }
2N/A yylval.str[strlen(yylval.str)] = c;
2N/A cnt++;
2N/A } while (!done);
2N/A
2N/A return (error);
2N/A}
2N/A
2N/Astatic int
2N/Ainput(void)
2N/A{
2N/A int c;
2N/A
2N/A c = yybuf[yybufpos++];
2N/A if (c == '\0') {
2N/A return (EOF);
2N/A }
2N/A
2N/A return (c);
2N/A}
2N/A
2N/Astatic void
2N/Aunput(int c)
2N/A{
2N/A if (c == '\0') {
2N/A return;
2N/A }
2N/A
2N/A if (yybufpos > 0) {
2N/A --yybufpos;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * return ACE entry type
2N/A */
2N/Aint
2N/Aace_entry_type(int type)
2N/A{
2N/A int ret = -1;
2N/A switch (type) {
2N/A case USER_TOK:
2N/A case USER_SID_TOK:
2N/A ret = 0;
2N/A break;
2N/A case GROUP_TOK:
2N/A case GROUP_SID_TOK:
2N/A ret = ACE_IDENTIFIER_GROUP;
2N/A break;
2N/A case OWNERAT_TOK:
2N/A ret = ACE_OWNER;
2N/A break;
2N/A case GROUPAT_TOK:
2N/A ret = ACE_IDENTIFIER_GROUP | ACE_GROUP;
2N/A break;
2N/A case EVERYONEAT_TOK:
2N/A ret = ACE_EVERYONE;
2N/A break;
2N/A }
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * return aclent entry type
2N/A */
2N/Aint
2N/Aaclent_entry_type(int type, int owning, int *ret)
2N/A{
2N/A
2N/A *ret = 0;
2N/A
2N/A switch (type) {
2N/A case USER_TOK:
2N/A *ret = (owning == 0) ? USER : USER_OBJ;
2N/A break;
2N/A case GROUP_TOK:
2N/A *ret = (owning == 0) ? GROUP : GROUP_OBJ;
2N/A break;
2N/A case OTHER_TOK:
2N/A *ret = OTHER_OBJ;
2N/A break;
2N/A case MASK_TOK:
2N/A *ret = CLASS_OBJ;
2N/A break;
2N/A case DEFAULT_USER_TOK:
2N/A *ret = (owning == 0) ? DEF_USER : DEF_USER_OBJ;
2N/A break;
2N/A case DEFAULT_GROUP_TOK:
2N/A *ret = (owning == 0) ? DEF_GROUP : DEF_GROUP_OBJ;
2N/A break;
2N/A case DEFAULT_MASK_TOK:
2N/A *ret = DEF_CLASS_OBJ;
2N/A break;
2N/A case DEFAULT_OTHER_TOK:
2N/A *ret = DEF_OTHER_OBJ;
2N/A break;
2N/A default:
2N/A return (EACL_ENTRY_ERROR);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * convert string into numeric id.
2N/A */
2N/Astatic int
2N/Aacl_str_to_id(char *str, uid_t *id)
2N/A{
2N/A char *end;
2N/A uid_t value;
2N/A
2N/A errno = 0;
2N/A value = strtoul(str, &end, 10);
2N/A
2N/A if (errno != 0 || *end != '\0')
2N/A return (EACL_INVALID_USER_GROUP);
2N/A
2N/A *id = value;
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * determine either uid/gid for given entry type
2N/A */
2N/Aint
2N/Aget_id(int entry_type, char *name, uid_t *id)
2N/A{
2N/A struct passwd *pw;
2N/A struct group *gr;
2N/A int error = 0;
2N/A
2N/A switch (entry_type) {
2N/A case USER_TOK:
2N/A case DEFAULT_USER_TOK:
2N/A if ((error = acl_str_to_id(name, id)) == 0)
2N/A break;
2N/A pw = getpwnam(name);
2N/A if (pw) {
2N/A *id = pw->pw_uid;
2N/A error = 0;
2N/A }
2N/A break;
2N/A
2N/A case GROUP_TOK:
2N/A case DEFAULT_GROUP_TOK:
2N/A if ((error = acl_str_to_id(name, id)) == 0)
2N/A break;
2N/A gr = getgrnam(name);
2N/A if (gr) {
2N/A *id = gr->gr_gid;
2N/A error = 0;
2N/A }
2N/A break;
2N/A case USER_SID_TOK:
2N/A if (sid_to_id(name, B_TRUE, id))
2N/A error = EACL_INVALID_USER_GROUP;
2N/A break;
2N/A
2N/A case GROUP_SID_TOK:
2N/A if (sid_to_id(name, B_FALSE, id))
2N/A error = EACL_INVALID_USER_GROUP;
2N/A break;
2N/A }
2N/A
2N/A return (error);
2N/A}
2N/A
2N/Aint
2N/Aget_id_nofail(int entry_type, char *name)
2N/A{
2N/A uid_t id;
2N/A
2N/A if (get_id(entry_type, name, &id))
2N/A return (UID_NOBODY);
2N/A else
2N/A return (id);
2N/A}
2N/A
2N/A/*
2N/A * reset beginning state to TS and set character position
2N/A * back to zero.
2N/A */
2N/Avoid
2N/Ayyreset()
2N/A{
2N/A yybufpos = 0;
2N/A memset(&yystrings, 0, sizeof (yystrings));
2N/A BEGIN TS;
2N/A}
2N/A
2N/Avoid
2N/Ayycleanup()
2N/A{
2N/A if (yystrings.y_logname)
2N/A free(yystrings.y_logname);
2N/A if (yystrings.y_perms)
2N/A free(yystrings.y_perms);
2N/A if (yystrings.y_iflags)
2N/A free(yystrings.y_iflags);
2N/A if (yystrings.y_idstr)
2N/A free(yystrings.y_idstr);
2N/A yystrings.y_logname = NULL;
2N/A yystrings.y_perms = NULL;
2N/A yystrings.y_iflags = NULL;
2N/A yystrings.y_idstr = NULL;
2N/A}