Blame libacl/acl_from_text.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
  File: acl_from_text.c
rpm-build 0a0c83
rpm-build 0a0c83
  Copyright (C) 1999, 2000, 2001
rpm-build 0a0c83
  Andreas Gruenbacher, <a.gruenbacher@bestbits.at>
rpm-build 0a0c83
rpm-build 0a0c83
  This program is free software; you can redistribute it and/or
rpm-build 0a0c83
  modify it under the terms of the GNU Lesser General Public
rpm-build 0a0c83
  License as published by the Free Software Foundation; either
rpm-build 0a0c83
  version 2.1 of the License, or (at your option) any later version.
rpm-build 0a0c83
rpm-build 0a0c83
  This program is distributed in the hope that it will be useful,
rpm-build 0a0c83
  but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build 0a0c83
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rpm-build 0a0c83
  Lesser General Public License for more details.
rpm-build 0a0c83
rpm-build 0a0c83
  You should have received a copy of the GNU Lesser General Public
rpm-build 0a0c83
  License along with this library; if not, write to the Free Software
rpm-build 0a0c83
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
rpm-build 0a0c83
*/
rpm-build 0a0c83
rpm-build 0a0c83
#include "config.h"
rpm-build 0a0c83
#include <string.h>
rpm-build 0a0c83
#include <pwd.h>
rpm-build 0a0c83
#include <grp.h>
rpm-build 0a0c83
#include "libacl.h"
rpm-build 0a0c83
#include "misc.h"
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
#define SKIP_WS(x) do { \
rpm-build 0a0c83
	while (*(x)==' ' || *(x)=='\t' || *(x)=='\n' || *(x)=='\r') \
rpm-build 0a0c83
		(x)++; \
rpm-build 0a0c83
	if (*(x)=='#') { \
rpm-build 0a0c83
		while (*(x)!='\n' && *(x)!='\0') \
rpm-build 0a0c83
			(x)++; \
rpm-build 0a0c83
	} \
rpm-build 0a0c83
	} while (0)
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int parse_acl_entry(const char **text_p, acl_t *acl_p);
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
/* 23.4.13 */
rpm-build 0a0c83
acl_t
rpm-build 0a0c83
acl_from_text(const char *buf_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_t acl;
rpm-build 0a0c83
	acl = acl_init(0);
rpm-build 0a0c83
	if (!acl)
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
	if (!buf_p) {
rpm-build 0a0c83
		errno = EINVAL;
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	while (*buf_p != '\0') {
rpm-build 0a0c83
		if (parse_acl_entry(&buf_p, &acl) != 0)
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		SKIP_WS(buf_p);
rpm-build 0a0c83
		if (*buf_p == ',') {
rpm-build 0a0c83
			buf_p++;
rpm-build 0a0c83
			SKIP_WS(buf_p);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (*buf_p != '\0') {
rpm-build 0a0c83
		errno = EINVAL;
rpm-build 0a0c83
		goto fail;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	return acl;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	acl_free(acl);
rpm-build 0a0c83
	return NULL;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
skip_tag_name(const char **text_p, const char *token)
rpm-build 0a0c83
{
rpm-build 0a0c83
	size_t len = strlen(token);
rpm-build 0a0c83
	const char *text = *text_p;
rpm-build 0a0c83
rpm-build 0a0c83
	SKIP_WS(text);
rpm-build 0a0c83
	if (strncmp(text, token, len) == 0) {
rpm-build 0a0c83
		text += len;
rpm-build 0a0c83
		goto delimiter;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (*text == *token) {
rpm-build 0a0c83
		text++;
rpm-build 0a0c83
		goto delimiter;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
rpm-build 0a0c83
delimiter:
rpm-build 0a0c83
	SKIP_WS(text);
rpm-build 0a0c83
	if (*text == ':')
rpm-build 0a0c83
		text++;
rpm-build 0a0c83
	*text_p = text;
rpm-build 0a0c83
	return 1;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static char *
rpm-build 0a0c83
get_token(const char **text_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *token = NULL;
rpm-build 0a0c83
	const char *ep;
rpm-build 0a0c83
rpm-build 0a0c83
	ep = *text_p;
rpm-build 0a0c83
	SKIP_WS(ep);
rpm-build 0a0c83
rpm-build 0a0c83
	while (*ep!='\0' && *ep!='\r' && *ep!='\n' && *ep!=':' && *ep!=',')
rpm-build 0a0c83
		ep++;
rpm-build 0a0c83
	if (ep == *text_p)
rpm-build 0a0c83
		goto after_token;
rpm-build 0a0c83
	token = (char*)malloc(ep - *text_p + 1);
rpm-build 0a0c83
	if (token == 0)
rpm-build 0a0c83
		goto after_token;
rpm-build 0a0c83
	memcpy(token, *text_p, (ep - *text_p));
rpm-build 0a0c83
	token[ep - *text_p] = '\0';
rpm-build 0a0c83
after_token:
rpm-build 0a0c83
	if (*ep == ':')
rpm-build 0a0c83
		ep++;
rpm-build 0a0c83
	*text_p = ep;
rpm-build 0a0c83
	return token;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_id(const char *token, id_t *id_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *ep;
rpm-build 0a0c83
	long l;
rpm-build 0a0c83
	l = strtol(token, &ep, 0);
rpm-build 0a0c83
	if (*ep != '\0')
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	if (l < 0) {
rpm-build 0a0c83
		/*
rpm-build 0a0c83
		  Negative values are interpreted as 16-bit numbers,
rpm-build 0a0c83
		  so that id -2 maps to 65534 (nobody/nogroup), etc.
rpm-build 0a0c83
		*/
rpm-build 0a0c83
		l &= 0xFFFF;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	*id_p = l;
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_uid(const char *token, uid_t *uid_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct passwd *passwd;
rpm-build 0a0c83
rpm-build 0a0c83
	if (get_id(token, uid_p) == 0)
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	errno = 0;
rpm-build 0a0c83
	passwd = getpwnam(token);
rpm-build 0a0c83
	if (passwd) {
rpm-build 0a0c83
		*uid_p = passwd->pw_uid;
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (errno == 0)
rpm-build 0a0c83
		errno = EINVAL;
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_gid(const char *token, gid_t *gid_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct group *group;
rpm-build 0a0c83
rpm-build 0a0c83
	if (get_id(token, (uid_t *)gid_p) == 0)
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	errno = 0;
rpm-build 0a0c83
	group = getgrnam(token);
rpm-build 0a0c83
	if (group) {
rpm-build 0a0c83
		*gid_p = group->gr_gid;
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (errno == 0)
rpm-build 0a0c83
		errno = EINVAL;
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
/*
rpm-build 0a0c83
	Parses the next acl entry in text_p.
rpm-build 0a0c83
rpm-build 0a0c83
	Returns:
rpm-build 0a0c83
		-1 on error, 0 on success.
rpm-build 0a0c83
*/
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
parse_acl_entry(const char **text_p, acl_t *acl_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_obj entry_obj;
rpm-build 0a0c83
	acl_entry_t entry_d;
rpm-build 0a0c83
	char *str;
rpm-build 0a0c83
	const char *backup;
rpm-build 0a0c83
	int error, perm_chars;
rpm-build 0a0c83
rpm-build 0a0c83
	new_obj_p_here(acl_entry, &entry_obj);
rpm-build 0a0c83
	init_acl_entry_obj(entry_obj);
rpm-build 0a0c83
rpm-build 0a0c83
	/* parse acl entry type */
rpm-build 0a0c83
	SKIP_WS(*text_p);
rpm-build 0a0c83
	switch (**text_p) {
rpm-build 0a0c83
		case 'u':  /* user */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "user"))
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			backup = *text_p;
rpm-build 0a0c83
			str = get_token(text_p);
rpm-build 0a0c83
			if (str) {
rpm-build 0a0c83
				entry_obj.etag = ACL_USER;
rpm-build 0a0c83
				error = get_uid(__acl_unquote(str),
rpm-build 0a0c83
						&entry_obj.eid.qid);
rpm-build 0a0c83
				free(str);
rpm-build 0a0c83
				if (error) {
rpm-build 0a0c83
					*text_p = backup;
rpm-build 0a0c83
					return -1;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				entry_obj.etag = ACL_USER_OBJ;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'g':  /* group */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "group"))
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			backup = *text_p;
rpm-build 0a0c83
			str = get_token(text_p);
rpm-build 0a0c83
			if (str) {
rpm-build 0a0c83
				entry_obj.etag = ACL_GROUP;
rpm-build 0a0c83
				error = get_gid(__acl_unquote(str),
rpm-build 0a0c83
						&entry_obj.eid.qid);
rpm-build 0a0c83
				free(str);
rpm-build 0a0c83
				if (error) {
rpm-build 0a0c83
					*text_p = backup;
rpm-build 0a0c83
					return -1;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				entry_obj.etag = ACL_GROUP_OBJ;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'm':  /* mask */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "mask"))
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			/* skip empty entry qualifier field (this field may
rpm-build 0a0c83
			   be missing for compatibility with Solaris.) */
rpm-build 0a0c83
			SKIP_WS(*text_p);
rpm-build 0a0c83
			if (**text_p == ':')
rpm-build 0a0c83
				(*text_p)++;
rpm-build 0a0c83
			entry_obj.etag = ACL_MASK;
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'o':  /* other */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "other"))
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			/* skip empty entry qualifier field (this field may
rpm-build 0a0c83
			   be missing for compatibility with Solaris.) */
rpm-build 0a0c83
			SKIP_WS(*text_p);
rpm-build 0a0c83
			if (**text_p == ':')
rpm-build 0a0c83
				(*text_p)++;
rpm-build 0a0c83
			entry_obj.etag = ACL_OTHER;
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		default:
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	for (perm_chars=0; perm_chars<3; perm_chars++, (*text_p)++) {
rpm-build 0a0c83
		switch(**text_p) {
rpm-build 0a0c83
			case 'r':
rpm-build 0a0c83
				if (entry_obj.eperm.sperm & ACL_READ)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				entry_obj.eperm.sperm |= ACL_READ;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'w':
rpm-build 0a0c83
				if (entry_obj.eperm.sperm  & ACL_WRITE)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				entry_obj.eperm.sperm  |= ACL_WRITE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'x':
rpm-build 0a0c83
				if (entry_obj.eperm.sperm  & ACL_EXECUTE)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				entry_obj.eperm.sperm  |= ACL_EXECUTE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case '-':
rpm-build 0a0c83
				/* ignore */
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				if (perm_chars == 0)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				goto create_entry;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
create_entry:
rpm-build 0a0c83
	if (acl_create_entry(acl_p, &entry_d) != 0)
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
#pragma GCC diagnostic push
rpm-build 0a0c83
#pragma GCC diagnostic ignored "-Waddress"
rpm-build 0a0c83
	if (acl_copy_entry(entry_d, int2ext(&entry_obj)) != 0)
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
#pragma GCC diagnostic pop
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	errno = EINVAL;
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
}
rpm-build 0a0c83