posix_acls.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,170 行 · 第 1/5 页

C
2,170
字号
/*   Unix SMB/CIFS implementation.   SMB NT Security Descriptor / Unix permission conversion.   Copyright (C) Jeremy Allison 1994-2000.   Copyright (C) Andreas Gruenbacher 2002.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"extern struct current_user current_user;extern struct generic_mapping file_generic_mapping;#undef  DBGC_CLASS#define DBGC_CLASS DBGC_ACLS/**************************************************************************** Data structures representing the internal ACE format.****************************************************************************/enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */typedef union posix_id {		uid_t uid;		gid_t gid;		int world;} posix_id;typedef struct canon_ace {	struct canon_ace *next, *prev;	SMB_ACL_TAG_T type;	mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */	DOM_SID trustee;	enum ace_owner owner_type;	enum ace_attribute attr;	posix_id unix_ug; 	BOOL inherited;} canon_ace;#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)/* * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance) * attribute on disk. * * |  1   |  1   |   2         |         2           |  ....  * +------+------+-------------+---------------------+-------------+--------------------+ * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... | * +------+------+-------------+---------------------+-------------+--------------------+ */#define PAI_VERSION_OFFSET	0#define PAI_FLAG_OFFSET		1#define PAI_NUM_ENTRIES_OFFSET	2#define PAI_NUM_DEFAULT_ENTRIES_OFFSET	4#define PAI_ENTRIES_BASE	6#define PAI_VERSION		1#define PAI_ACL_FLAG_PROTECTED	0x1#define PAI_ENTRY_LENGTH	5/* * In memory format of user.SAMBA_PAI attribute. */struct pai_entry {	struct pai_entry *next, *prev;	enum ace_owner owner_type;	posix_id unix_ug; };	struct pai_val {	BOOL pai_protected;	unsigned int num_entries;	struct pai_entry *entry_list;	unsigned int num_def_entries;	struct pai_entry *def_entry_list;};/************************************************************************ Return a uint32 of the pai_entry principal.************************************************************************/static uint32 get_pai_entry_val(struct pai_entry *paie){	switch (paie->owner_type) {		case UID_ACE:			DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));			return (uint32)paie->unix_ug.uid;		case GID_ACE:			DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));			return (uint32)paie->unix_ug.gid;		case WORLD_ACE:		default:			DEBUG(10,("get_pai_entry_val: world ace\n"));			return (uint32)-1;	}}/************************************************************************ Return a uint32 of the entry principal.************************************************************************/static uint32 get_entry_val(canon_ace *ace_entry){	switch (ace_entry->owner_type) {		case UID_ACE:			DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid ));			return (uint32)ace_entry->unix_ug.uid;		case GID_ACE:			DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid ));			return (uint32)ace_entry->unix_ug.gid;		case WORLD_ACE:		default:			DEBUG(10,("get_entry_val: world ace\n"));			return (uint32)-1;	}}/************************************************************************ Count the inherited entries.************************************************************************/static unsigned int num_inherited_entries(canon_ace *ace_list){	unsigned int num_entries = 0;	for (; ace_list; ace_list = ace_list->next)		if (ace_list->inherited)			num_entries++;	return num_entries;}/************************************************************************ Create the on-disk format. Caller must free.************************************************************************/static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size){	char *pai_buf = NULL;	canon_ace *ace_list = NULL;	char *entry_offset = NULL;	unsigned int num_entries = 0;	unsigned int num_def_entries = 0;	for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next)		if (ace_list->inherited)			num_entries++;	for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next)		if (ace_list->inherited)			num_def_entries++;	DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));	*store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH);	pai_buf = SMB_MALLOC(*store_size);	if (!pai_buf) {		return NULL;	}	/* Set up the header. */	memset(pai_buf, '\0', PAI_ENTRIES_BASE);	SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION);	SCVAL(pai_buf,PAI_FLAG_OFFSET,(pai_protected ? PAI_ACL_FLAG_PROTECTED : 0));	SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries);	SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);	entry_offset = pai_buf + PAI_ENTRIES_BASE;	for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {		if (ace_list->inherited) {			uint8 type_val = (unsigned char)ace_list->owner_type;			uint32 entry_val = get_entry_val(ace_list);			SCVAL(entry_offset,0,type_val);			SIVAL(entry_offset,1,entry_val);			entry_offset += PAI_ENTRY_LENGTH;		}	}	for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {		if (ace_list->inherited) {			uint8 type_val = (unsigned char)ace_list->owner_type;			uint32 entry_val = get_entry_val(ace_list);			SCVAL(entry_offset,0,type_val);			SIVAL(entry_offset,1,entry_val);			entry_offset += PAI_ENTRY_LENGTH;		}	}	return pai_buf;}/************************************************************************ Store the user.SAMBA_PAI attribute on disk.************************************************************************/static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list,					canon_ace *dir_ace_list, BOOL pai_protected){	int ret;	size_t store_size;	char *pai_buf;	if (!lp_map_acl_inherit(SNUM(fsp->conn)))		return;	/*	 * Don't store if this ACL isn't protected and	 * none of the entries in it are marked as inherited.	 */	if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) {		/* Instead just remove the attribute if it exists. */		if (fsp->fh->fd != -1)			SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME);		else			SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME);		return;	}	pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size);	if (fsp->fh->fd != -1)		ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,				pai_buf, store_size, 0);	else		ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,				pai_buf, store_size, 0);	SAFE_FREE(pai_buf);	DEBUG(10,("store_inheritance_attribute:%s for file %s\n", pai_protected ? " (protected)" : "", fsp->fsp_name));	if (ret == -1 && !no_acl_syscall_error(errno))		DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));}/************************************************************************ Delete the in memory inheritance info.************************************************************************/static void free_inherited_info(struct pai_val *pal){	if (pal) {		struct pai_entry *paie, *paie_next;		for (paie = pal->entry_list; paie; paie = paie_next) {			paie_next = paie->next;			SAFE_FREE(paie);		}		for (paie = pal->def_entry_list; paie; paie = paie_next) {			paie_next = paie->next;			SAFE_FREE(paie);		}		SAFE_FREE(pal);	}}/************************************************************************ Was this ACL protected ?************************************************************************/static BOOL get_protected_flag(struct pai_val *pal){	if (!pal)		return False;	return pal->pai_protected;}/************************************************************************ Was this ACE inherited ?************************************************************************/static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace){	struct pai_entry *paie;	if (!pal)		return False;	/* If the entry exists it is inherited. */	for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {		if (ace_entry->owner_type == paie->owner_type &&				get_entry_val(ace_entry) == get_pai_entry_val(paie))			return True;	}	return False;}/************************************************************************ Ensure an attribute just read is valid.************************************************************************/static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size){	uint16 num_entries;	uint16 num_def_entries;	if (pai_buf_data_size < PAI_ENTRIES_BASE) {		/* Corrupted - too small. */		return False;	}	if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION)		return False;	num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET);	num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);	/* Check the entry lists match. */	/* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */	if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size)		return False;	return True;}/************************************************************************ Convert to in-memory format.************************************************************************/static struct pai_val *create_pai_val(char *buf, size_t size){	char *entry_offset;	struct pai_val *paiv = NULL;	int i;	if (!check_pai_ok(buf, size))		return NULL;	paiv = SMB_MALLOC_P(struct pai_val);	if (!paiv)		return NULL;	memset(paiv, '\0', sizeof(struct pai_val));	paiv->pai_protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED);	paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET);	paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);	entry_offset = buf + PAI_ENTRIES_BASE;	DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n",			paiv->pai_protected ? " (pai_protected)" : "", paiv->num_entries, paiv->num_def_entries ));	for (i = 0; i < paiv->num_entries; i++) {		struct pai_entry *paie;		paie = SMB_MALLOC_P(struct pai_entry);		if (!paie) {			free_inherited_info(paiv);			return NULL;		}		paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);		switch( paie->owner_type) {			case UID_ACE:				paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);				DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));				break;			case GID_ACE:				paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);				DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));				break;			case WORLD_ACE:				paie->unix_ug.world = -1;				DEBUG(10,("create_pai_val: world ace\n"));				break;			default:				free_inherited_info(paiv);				return NULL;		}		entry_offset += PAI_ENTRY_LENGTH;		DLIST_ADD(paiv->entry_list, paie);	}	for (i = 0; i < paiv->num_def_entries; i++) {		struct pai_entry *paie;		paie = SMB_MALLOC_P(struct pai_entry);		if (!paie) {			free_inherited_info(paiv);			return NULL;		}		paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);		switch( paie->owner_type) {			case UID_ACE:				paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);				DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid ));				break;			case GID_ACE:				paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);				DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid ));				break;			case WORLD_ACE:				paie->unix_ug.world = -1;				DEBUG(10,("create_pai_val: (def) world ace\n"));				break;			default:				free_inherited_info(paiv);				return NULL;		}		entry_offset += PAI_ENTRY_LENGTH;		DLIST_ADD(paiv->def_entry_list, paie);	}	return paiv;}/************************************************************************ Load the user.SAMBA_PAI attribute.************************************************************************/static struct pai_val *load_inherited_info(files_struct *fsp)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?