posix_acls.c

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

C
2,170
字号
{	char *pai_buf;	size_t pai_buf_size = 1024;	struct pai_val *paiv = NULL;	ssize_t ret;	if (!lp_map_acl_inherit(SNUM(fsp->conn)))		return NULL;	if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)		return NULL;	do {		if (fsp->fh->fd != -1)			ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,					pai_buf, pai_buf_size);		else			ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,					pai_buf, pai_buf_size);		if (ret == -1) {			if (errno != ERANGE) {				break;			}			/* Buffer too small - enlarge it. */			pai_buf_size *= 2;			SAFE_FREE(pai_buf);			if (pai_buf_size > 1024*1024) {				return NULL; /* Limit malloc to 1mb. */			}			if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)				return NULL;		}	} while (ret == -1);	DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name));	if (ret == -1) {		/* No attribute or not supported. */#if defined(ENOATTR)		if (errno != ENOATTR)			DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));#else		if (errno != ENOSYS)			DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));#endif		SAFE_FREE(pai_buf);		return NULL;	}	paiv = create_pai_val(pai_buf, ret);	if (paiv && paiv->pai_protected)		DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name));	SAFE_FREE(pai_buf);	return paiv;}/**************************************************************************** Functions to manipulate the internal ACE format.****************************************************************************//**************************************************************************** Count a linked list of canonical ACE entries.****************************************************************************/static size_t count_canon_ace_list( canon_ace *list_head ){	size_t count = 0;	canon_ace *ace;	for (ace = list_head; ace; ace = ace->next)		count++;	return count;}/**************************************************************************** Free a linked list of canonical ACE entries.****************************************************************************/static void free_canon_ace_list( canon_ace *list_head ){	while (list_head) {		canon_ace *old_head = list_head;		DLIST_REMOVE(list_head, list_head);		SAFE_FREE(old_head);	}}/**************************************************************************** Function to duplicate a canon_ace entry.****************************************************************************/static canon_ace *dup_canon_ace( canon_ace *src_ace){	canon_ace *dst_ace = SMB_MALLOC_P(canon_ace);	if (dst_ace == NULL)		return NULL;	*dst_ace = *src_ace;	dst_ace->prev = dst_ace->next = NULL;	return dst_ace;}/**************************************************************************** Print out a canon ace.****************************************************************************/static void print_canon_ace(canon_ace *pace, int num){	fstring str;	dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );	dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));	if (pace->owner_type == UID_ACE) {		const char *u_name = uidtoname(pace->unix_ug.uid);		dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name );	} else if (pace->owner_type == GID_ACE) {		char *g_name = gidtoname(pace->unix_ug.gid);		dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name );	} else		dbgtext( "other ");	switch (pace->type) {		case SMB_ACL_USER:			dbgtext( "SMB_ACL_USER ");			break;		case SMB_ACL_USER_OBJ:			dbgtext( "SMB_ACL_USER_OBJ ");			break;		case SMB_ACL_GROUP:			dbgtext( "SMB_ACL_GROUP ");			break;		case SMB_ACL_GROUP_OBJ:			dbgtext( "SMB_ACL_GROUP_OBJ ");			break;		case SMB_ACL_OTHER:			dbgtext( "SMB_ACL_OTHER ");			break;	}	if (pace->inherited)		dbgtext( "(inherited) ");	dbgtext( "perms ");	dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');	dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');	dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');}/**************************************************************************** Print out a canon ace list.****************************************************************************/static void print_canon_ace_list(const char *name, canon_ace *ace_list){	int count = 0;	if( DEBUGLVL( 10 )) {		dbgtext( "print_canon_ace_list: %s\n", name );		for (;ace_list; ace_list = ace_list->next, count++)			print_canon_ace(ace_list, count );	}}/**************************************************************************** Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).****************************************************************************/static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset){	mode_t ret = 0;	ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);	ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);	ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);	return ret;}/**************************************************************************** Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).****************************************************************************/static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask){	mode_t ret = 0;	if (mode & r_mask)		ret |= S_IRUSR;	if (mode & w_mask)		ret |= S_IWUSR;	if (mode & x_mask)		ret |= S_IXUSR;	return ret;}/**************************************************************************** Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to an SMB_ACL_PERMSET_T.****************************************************************************/static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset){	if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1)		return -1;	if (mode & S_IRUSR) {		if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)			return -1;	}	if (mode & S_IWUSR) {		if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)			return -1;	}	if (mode & S_IXUSR) {		if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)			return -1;	}	return 0;}/**************************************************************************** Function to create owner and group SIDs from a SMB_STRUCT_STAT.****************************************************************************/static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid){	uid_to_sid( powner_sid, psbuf->st_uid );	gid_to_sid( pgroup_sid, psbuf->st_gid );}/**************************************************************************** Merge aces with a common sid - if both are allow or deny, OR the permissions together and delete the second one. If the first is deny, mask the permissions off and delete the allow if the permissions become zero, delete the deny if the permissions are non zero.****************************************************************************/static void merge_aces( canon_ace **pp_list_head ){	canon_ace *list_head = *pp_list_head;	canon_ace *curr_ace_outer;	canon_ace *curr_ace_outer_next;	/*	 * First, merge allow entries with identical SIDs, and deny entries	 * with identical SIDs.	 */	for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {		canon_ace *curr_ace;		canon_ace *curr_ace_next;		curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */		for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {			curr_ace_next = curr_ace->next; /* Save the link in case of delete. */			if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&				(curr_ace->attr == curr_ace_outer->attr)) {				if( DEBUGLVL( 10 )) {					dbgtext("merge_aces: Merging ACE's\n");					print_canon_ace( curr_ace_outer, 0);					print_canon_ace( curr_ace, 0);				}				/* Merge two allow or two deny ACE's. */				curr_ace_outer->perms |= curr_ace->perms;				DLIST_REMOVE(list_head, curr_ace);				SAFE_FREE(curr_ace);				curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */			}		}	}	/*	 * Now go through and mask off allow permissions with deny permissions.	 * We can delete either the allow or deny here as we know that each SID	 * appears only once in the list.	 */	for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {		canon_ace *curr_ace;		canon_ace *curr_ace_next;		curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */		for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {			curr_ace_next = curr_ace->next; /* Save the link in case of delete. */			/*			 * Subtract ACE's with different entries. Due to the ordering constraints			 * we've put on the ACL, we know the deny must be the first one.			 */			if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&				(curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {				if( DEBUGLVL( 10 )) {					dbgtext("merge_aces: Masking ACE's\n");					print_canon_ace( curr_ace_outer, 0);					print_canon_ace( curr_ace, 0);				}				curr_ace->perms &= ~curr_ace_outer->perms;				if (curr_ace->perms == 0) {					/*					 * The deny overrides the allow. Remove the allow.					 */					DLIST_REMOVE(list_head, curr_ace);					SAFE_FREE(curr_ace);					curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */				} else {					/*					 * Even after removing permissions, there					 * are still allow permissions - delete the deny.					 * It is safe to delete the deny here,					 * as we are guarenteed by the deny first					 * ordering that all the deny entries for					 * this SID have already been merged into one					 * before we can get to an allow ace.					 */					DLIST_REMOVE(list_head, curr_ace_outer);					SAFE_FREE(curr_ace_outer);					break;				}			}		} /* end for curr_ace */	} /* end for curr_ace_outer */	/* We may have modified the list. */	*pp_list_head = list_head;}/**************************************************************************** Check if we need to return NT4.x compatible ACL entries.****************************************************************************/static BOOL nt4_compatible_acls(void){	const char *compat = lp_acl_compatibility();	if (*compat == '\0') {		enum remote_arch_types ra_type = get_remote_arch();		/* Automatically adapt to client */		return (ra_type <= RA_WINNT);	} else		return (strequal(compat, "winnt"));}/**************************************************************************** Map canon_ace perms to permission bits NT. The attr element is not used here - we only process deny entries on set, not get. Deny entries are implicit on get with ace->perms = 0.****************************************************************************/static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace){	SEC_ACCESS sa;	uint32 nt_mask = 0;	*pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;	if (lp_acl_map_full_control(snum) && ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {		if (directory_ace) {			nt_mask = UNIX_DIRECTORY_ACCESS_RWX;		} else {			nt_mask = UNIX_ACCESS_RWX;		}	} else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) {		/*		 * Windows NT refuses to display ACEs with no permissions in them (but		 * they are perfectly legal with Windows 2000). If the ACE has empty		 * permissions we cannot use 0, so we use the otherwise unused		 * WRITE_OWNER permission, which we ignore when we set an ACL.		 * We abstract this into a #define of UNIX_ACCESS_NONE to allow this		 * to be changed in the future.		 */		if (nt4_compatible_acls())			nt_mask = UNIX_ACCESS_NONE;		else			nt_mask = 0;	} else {		if (directory_ace) {			nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );			nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );			nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );		} else {			nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );			nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );			nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );		}	}	DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",			(unsigned int)ace->perms, (unsigned int)nt_mask ));	init_sec_access(&sa,nt_mask);	return sa;}/**************************************************************************** Map NT perms to a UNIX mode_t.****************************************************************************/#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)static mode_t map_nt_perms( SEC_ACCESS sec_access, int type){	mode_t mode = 0;	switch(type) {	case S_IRUSR:		if(sec_access.mask & GENERIC_ALL_ACCESS)			mode = S_IRUSR|S_IWUSR|S_IXUSR;		else {			mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;			mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;

⌨️ 快捷键说明

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