acltext.c revision afe1f701befcc3fd850031b953345201d666ce0f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*LINTLIBRARY*/
#include <grp.h>
#include <pwd.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
#include <aclutils.h>
/*
* yyinteractive controls whether yyparse should print out
* error messages to stderr, and whether or not id's should be
* allowed from acl_fromtext().
*/
int yyinteractive;
char *yybuf;
struct dynaclstr {
char *aclexport;
};
static char *strappend(char *, char *);
static char *convert_perm(char *, o_mode_t);
static void
{
txt_perms[0] = 'r';
else
txt_perms[0] = '-';
else
else
}
static char *
{
if (noresolve == 0)
/* could not get passwd information: display uid instead */
} else {
}
return (uidp);
}
static char *
{
if (noresolve == 0)
/* could not get group information: display gid instead */
} else {
}
return (gidp);
}
static void
{
int aclcnt;
int mask;
int slot = 0;
char perm[4];
char uidp[ID_STR_MAX];
char gidp[ID_STR_MAX];
/* display ACL: assume it is sorted. */
}
case USER:
(void) printf("user:%s:%s\t\t",
break;
case USER_OBJ:
/* no need to display uid */
break;
case GROUP:
(void) printf("group:%s:%s\t\t",
break;
case GROUP_OBJ:
break;
case CLASS_OBJ:
break;
case OTHER_OBJ:
break;
case DEF_USER:
(void) printf("default:user:%s:%s\n",
break;
case DEF_USER_OBJ:
break;
case DEF_GROUP:
(void) printf("default:group:%s:%s\n",
break;
case DEF_GROUP_OBJ:
break;
case DEF_CLASS_OBJ:
break;
case DEF_OTHER_OBJ:
break;
default:
gettext("unrecognized entry\n"));
break;
}
}
}
static void
{
char *ptr;
int len;
int i;
int last_split;
char *pad = "";
int pad_len;
pad_len = 0;
last_split = 0;
for (i = 0; i != len; i++) {
i = 0;
pad_len = 4;
pad = " ";
} else {
last_split = i;
}
}
}
if (i == len) {
}
}
#define OWNERAT_TXT "owner@"
#define GROUPAT_TXT "group@"
#define EVERYONEAT_TXT "everyone@"
#define GROUP_TXT "group:"
#define USER_TXT "user:"
char *
{
char idp[ID_STR_MAX];
return (NULL);
case ACE_OWNER:
break;
break;
case ACE_IDENTIFIER_GROUP:
break;
case ACE_EVERYONE:
break;
case 0:
break;
}
return (buf);
}
#define READ_DATA_TXT "read_data/"
#define WRITE_DATA_TXT "write_data/"
#define EXECUTE_TXT "execute/"
#define READ_XATTR_TXT "read_xattr/"
#define WRITE_XATTR_TXT "write_xattr/"
#define READ_ATTRIBUTES_TXT "read_attributes/"
#define WRITE_ATTRIBUTES_TXT "write_attributes/"
#define DELETE_TXT "delete/"
#define DELETE_CHILD_TXT "delete_child/"
#define WRITE_OWNER_TXT "write_owner/"
#define READ_ACL_TXT "read_acl/"
#define WRITE_ACL_TXT "write_acl/"
#define APPEND_DATA_TXT "append_data/"
#define READ_DIR_TXT "list_directory/read_data/"
#define ADD_DIR_TXT "add_subdirectory/append_data/"
#define ADD_FILE_TXT "add_file/write_data/"
char *
{
return (NULL);
if (flags & ACL_COMPACT_FMT) {
if (mask & ACE_READ_DATA)
buf[0] = 'r';
else
buf[0] = '-';
if (mask & ACE_WRITE_DATA)
else
if (mask & ACE_EXECUTE)
else
if (mask & ACE_APPEND_DATA)
else
if (mask & ACE_DELETE)
else
if (mask & ACE_DELETE_CHILD)
else
if (mask & ACE_READ_ATTRIBUTES)
else
if (mask & ACE_WRITE_ATTRIBUTES)
else
if (mask & ACE_READ_NAMED_ATTRS)
else
if (mask & ACE_WRITE_NAMED_ATTRS)
else
if (mask & ACE_READ_ACL)
else
if (mask & ACE_WRITE_ACL)
else
if (mask & ACE_WRITE_OWNER)
else
if (mask & ACE_SYNCHRONIZE)
else
return (buf);
} else {
/*
* If ACE is a directory, but inheritance indicates its
* for a file then print permissions for file rather than
* dir.
*/
if (isdir) {
if (mask & ACE_LIST_DIRECTORY) {
if (iflags == ACE_FILE_INHERIT_ACE) {
} else {
}
}
if (mask & ACE_ADD_FILE) {
if (iflags == ACE_FILE_INHERIT_ACE) {
} else {
lend +=
sizeof (ADD_FILE_TXT) -1;
}
}
if (mask & ACE_ADD_SUBDIRECTORY) {
if (iflags == ACE_FILE_INHERIT_ACE) {
} else {
}
}
} else {
if (mask & ACE_READ_DATA) {
}
if (mask & ACE_WRITE_DATA) {
}
if (mask & ACE_APPEND_DATA) {
}
}
if (mask & ACE_READ_NAMED_ATTRS) {
}
if (mask & ACE_WRITE_NAMED_ATTRS) {
}
if (mask & ACE_EXECUTE) {
}
if (mask & ACE_DELETE_CHILD) {
}
if (mask & ACE_READ_ATTRIBUTES) {
}
if (mask & ACE_WRITE_ATTRIBUTES) {
}
if (mask & ACE_DELETE) {
}
if (mask & ACE_READ_ACL) {
}
if (mask & ACE_WRITE_ACL) {
}
if (mask & ACE_WRITE_OWNER) {
}
if (mask & ACE_SYNCHRONIZE) {
}
*--lend = '\0';
}
return (buf);
}
#define ALLOW_TXT "allow"
#define DENY_TXT "deny"
#define ALARM_TXT "alarm"
#define AUDIT_TXT "audit"
#define UNKNOWN_TXT "unknown"
char *
{
return (NULL);
if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
} else if (type == ACE_ACCESS_DENIED_ACE_TYPE) {
} else if (type == ACE_SYSTEM_AUDIT_ACE_TYPE) {
} else if (type == ACE_SYSTEM_ALARM_ACE_TYPE) {
} else {
}
return (buf);
}
static char *
{
return (NULL);
}
if (flags & ACL_COMPACT_FMT) {
if (iflags & ACE_FILE_INHERIT_ACE)
buf[0] = 'f';
else
buf[0] = '-';
if (iflags & ACE_DIRECTORY_INHERIT_ACE)
else
if (iflags & ACE_INHERIT_ONLY_ACE)
else
else
else
if (iflags & ACE_FAILED_ACCESS_ACE_FLAG)
else
} else {
if (iflags & ACE_FILE_INHERIT_ACE) {
}
if (iflags & ACE_DIRECTORY_INHERIT_ACE) {
}
if (iflags & ACE_NO_PROPAGATE_INHERIT_ACE) {
}
if (iflags & ACE_INHERIT_ONLY_ACE) {
}
*--lend = '\0';
}
return (buf);
}
/*
* Convert internal acl representation to external representation.
*
* The length of a non-owning user name or non-owning group name ie entries
* of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We
* thus check the length of these entries, and if greater than LOGNAME_MAX,
* we realloc() via increase_length().
*
* The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
* adhered to.
*/
/*
* acltotext() converts each ACL entry to look like this:
*
* entry_type:uid^gid^name:perms[:id]
*
* The maximum length of entry_type is 14 ("defaultgroup::" and
* "defaultother::") hence ENTRYTYPELEN is set to 14.
*
* The max length of a uid^gid^name entry (in theory) is 8, hence we use,
* however the ID could be a number so we therefore use ID_STR_MAX
*
* The length of a perms entry is 4 to allow for the comma appended to each
* to each acl entry. Hence PERMS is set to 4.
*/
#define ENTRYTYPELEN 14
#define PERMS 4
char *
{
char *aclexport;
char *where;
int i, rtn;
return (NULL);
return (NULL);
return (NULL);
}
case DEF_USER_OBJ:
case USER_OBJ:
else
break;
case DEF_USER:
case USER:
else
if ((flags & ACL_NORESOLVE) == 0)
/* put in uid instead */
} else {
if (excess > 0) {
if (rtn == 1) {
} else {
return (NULL);
}
}
}
break;
case DEF_GROUP_OBJ:
case GROUP_OBJ:
else
break;
case DEF_GROUP:
case GROUP:
else
if ((flags & ACL_NORESOLVE) == 0)
/* put in gid instead */
} else {
if (excess > 0) {
if (rtn == 1) {
} else {
return (NULL);
}
}
}
break;
case DEF_CLASS_OBJ:
case CLASS_OBJ:
else
break;
case DEF_OTHER_OBJ:
case OTHER_OBJ:
else
break;
default:
return (NULL);
}
}
if (i < aclcnt - 1)
}
return (aclexport);
}
char *
{
}
aclent_t *
{
int error;
if (error)
return (NULL);
return (aclentp);
}
static char *
{
}
static char *
{
else
else
else
/* perm is the last field */
return (where);
}
/*
* Callers should check the return code as this routine may change the string
* pointer in dynaclstr.
*/
static int
{
char *tptr;
return (1);
} else
return (0);
}
/*
* ace_acltotext() convert each ace formatted acl to look like this:
*
* entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
*
* The maximum length of entry_type is 5 ("group")
*
* The max length of a uid^gid^name entry (in theory) is 8,
* however id could be a number so we therefore use ID_STR_MAX
*
* The length of a perms entry is 144 i.e read_data/write_data...
* to each acl entry.
*
* iflags: file_inherit/dir_inherit/inherit_only/no_propagate
*
*/
#define ACE_ENTRYTYPLEN 6
#define IFLAGS_SIZE 51
#define COLON_CNT 3
#define PERMS_LEN 216
static char *
{
char *aclexport;
char *endp;
int i;
return (NULL);
return (NULL);
aclexport[0] = '\0';
*endp++ = ':';
*endp = '\0';
*endp++ = ':';
*endp = '\0';
*endp++ = ':';
*endp = '\0';
}
if ((flags & ACL_APPEND_ID) &&
ACE_IDENTIFIER_GROUP))) {
*endp++ = ':';
*endp = '\0';
}
if (i < aclcnt - 1) {
*endp++ = ',';
}
}
return (aclexport);
}
char *
{
char *txtp;
return (NULL);
case ACE_T:
break;
case ACLENT_T:
break;
}
return (txtp);
}
int
{
int error;
char *buf;
return (EACL_MEM_ERROR);
yyreset();
if (yyacl) {
if (error == 0)
else {
}
}
return (error);
}
int
{
int error;
yyinteractive = 1;
yyinteractive = 0;
return (error);
}
static void
{
int cnt;
char *endp;
char buf[ACE_ENTRY_SIZE];
buf[0] = '\0';
(void) printf("%s:",
}
}
static void
{
int slot = 0;
char *token;
char *acltext;
if (compact) {
return;
}
return;
return;
}
do {
}
/*
* pretty print an ACL.
* For aclent_t ACL's the format is
* similar to the old format used by getfacl,
* with the addition of adding a "slot" number
* before each entry.
*
* for ace_t ACL's the cols variable will break up
* the long lines into multiple lines and will also
* print a "slot" number.
*/
void
{
case ACLENT_T:
break;
case ACE_T:
break;
}
}
typedef struct value_table {
char p_letter; /* perm letter such as 'r' */
#define ACE_PERM_COUNT 14
/*
* The permission tables are layed out in positional order
* a '-' character will indicate a permission at a given
* position is not specified. The '-' is not part of the
* table, but will be checked for in the permission computation
* routine.
*/
{ 'r', ACE_READ_DATA},
{ 'w', ACE_WRITE_DATA},
{ 'x', ACE_EXECUTE},
{ 'p', ACE_APPEND_DATA},
{ 'd', ACE_DELETE},
{ 'D', ACE_DELETE_CHILD},
{ 'a', ACE_READ_ATTRIBUTES},
{ 'A', ACE_WRITE_ATTRIBUTES},
{ 'R', ACE_READ_NAMED_ATTRS},
{ 'W', ACE_WRITE_NAMED_ATTRS},
{ 'c', ACE_READ_ACL},
{ 'C', ACE_WRITE_ACL},
{ 'o', ACE_WRITE_OWNER},
{ 's', ACE_SYNCHRONIZE}
};
#define ACLENT_PERM_COUNT 3
{ 'r', S_IROTH},
{ 'w', S_IWOTH},
{ 'x', S_IXOTH}
};
#define IFLAG_COUNT 6
{'f', ACE_FILE_INHERIT_ACE},
{'d', ACE_DIRECTORY_INHERIT_ACE},
{'i', ACE_INHERIT_ONLY_ACE},
{'n', ACE_NO_PROPAGATE_INHERIT_ACE},
{'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
{'F', ACE_FAILED_ACCESS_ACE_FLAG}
};
/*
* compute value from a permission table or inheritance table
* based on string passed in. If positional is set then
* string must match order in permtab, otherwise any order
* is allowed.
*/
int
{
char *pstr;
int i, found;
if (count < 0)
return (1);
if (positional) {
} else if (*pstr != '-') {
return (1);
}
}
} else { /* random order single letters with no '-' */
found = 1;
break;
}
}
if (found == 0)
return (1);
}
}
return (0);
}
/*
* compute value for inheritance flags.
*/
int
{
int error;
int positional = 0;
positional = 1;
if (error)
return (EACL_INHERIT_ERROR);
return (error);
}
/*
* compute value for ACE permissions.
*/
int
{
int positional = 0;
int error;
positional = 1;
if (error && positional) {
/*
* If positional was set, then make sure permissions
* aren't actually valid in non positional case where
* all permissions are specified, just in random order.
*/
}
if (error)
return (error);
}
/*
* compute values for aclent permissions.
*/
int
{
int error;
return (EACL_PERM_MASK_ERROR);
*mask = 0;
if (error == 0) {
} else
return (error);
}
/*
* determine ACE permissions.
*/
int
{
int error;
*mask = 0;
return (0);
}
return (0);
}
if (error) {
return (EACL_PERM_MASK_ERROR);
}
return (0);
}