posix_acls.c

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

C
2,170
字号
	for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {		mode_t new_perms = (mode_t)0;		canon_ace *allow_ace_p;		canon_ace *tmp_ace;		curr_ace_next = curr_ace->next; /* So we can't lose the link. */		if (curr_ace->attr != DENY_ACE)			continue;		if (curr_ace->owner_type != UID_ACE)			continue;		if (curr_ace->perms == ALL_ACE_PERMS) {			/*			 * Optimisation - this is a deny everything to this user.			 * Convert to an allow nothing and push to the end of the list.			 */			curr_ace->attr = ALLOW_ACE;			curr_ace->perms = (mode_t)0;			DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);			continue;		}		for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {			if (allow_ace_p->attr != ALLOW_ACE)				continue;			/* We process GID_ACE and WORLD_ACE entries only. */			if (allow_ace_p->owner_type == UID_ACE)				continue;			if (uid_entry_in_group( curr_ace, allow_ace_p))				new_perms |= allow_ace_p->perms;		}		/*		 * Convert to a allow entry, modify the perms and push to the end		 * of the list.		 */		curr_ace->attr = ALLOW_ACE;		curr_ace->perms = (new_perms & ~curr_ace->perms);		DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);	}	/* Pass 3 above - deal with deny group entries. */	for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {		canon_ace *tmp_ace;		canon_ace *allow_ace_p;		canon_ace *allow_everyone_p = NULL;		curr_ace_next = curr_ace->next; /* So we can't lose the link. */		if (curr_ace->attr != DENY_ACE)			continue;		if (curr_ace->owner_type != GID_ACE)			continue;		for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {			if (allow_ace_p->attr != ALLOW_ACE)				continue;			/* Store a pointer to the Everyone allow, if it exists. */			if (allow_ace_p->owner_type == WORLD_ACE)				allow_everyone_p = allow_ace_p;			/* We process UID_ACE entries only. */			if (allow_ace_p->owner_type != UID_ACE)				continue;			/* Mask off the deny group perms. */			if (uid_entry_in_group( allow_ace_p, curr_ace))				allow_ace_p->perms &= ~curr_ace->perms;		}		/*		 * Convert the deny to an allow with the correct perms and		 * push to the end of the list.		 */		curr_ace->attr = ALLOW_ACE;		if (allow_everyone_p)			curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;		else			curr_ace->perms = (mode_t)0;		DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);	}	/* Doing this fourth pass allows Windows semantics to be layered	 * on top of POSIX semantics. I'm not sure if this is desirable.	 * For example, in W2K ACLs there is no way to say, "Group X no	 * access, user Y full access" if user Y is a member of group X.	 * This seems completely broken semantics to me.... JRA.	 */#if 0	/* Pass 4 above - deal with allow entries. */	for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {		canon_ace *allow_ace_p;		curr_ace_next = curr_ace->next; /* So we can't lose the link. */		if (curr_ace->attr != ALLOW_ACE)			continue;		if (curr_ace->owner_type != UID_ACE)			continue;		for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {			if (allow_ace_p->attr != ALLOW_ACE)				continue;			/* We process GID_ACE entries only. */			if (allow_ace_p->owner_type != GID_ACE)				continue;			/* OR in the group perms. */			if (uid_entry_in_group( curr_ace, allow_ace_p))				curr_ace->perms |= allow_ace_p->perms;		}	}#endif	*pp_ace_list = ace_list;}/**************************************************************************** Create a default mode that will be used if a security descriptor entry has no user/group/world entries.****************************************************************************/static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode){	int snum = SNUM(fsp->conn);	mode_t and_bits = (mode_t)0;	mode_t or_bits = (mode_t)0;	mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR;	if (fsp->is_directory)		mode |= (S_IWUSR|S_IXUSR);	/*	 * Now AND with the create mode/directory mode bits then OR with the	 * force create mode/force directory mode bits.	 */	if (fsp->is_directory) {		and_bits = lp_dir_security_mask(snum);		or_bits = lp_force_dir_security_mode(snum);	} else {		and_bits = lp_security_mask(snum);		or_bits = lp_force_security_mode(snum);	}	return ((mode & and_bits)|or_bits);}/**************************************************************************** Unpack a SEC_DESC into two canonical ace lists. We don't depend on this succeeding.****************************************************************************/static BOOL unpack_canon_ace(files_struct *fsp, 							SMB_STRUCT_STAT *pst,							DOM_SID *pfile_owner_sid,							DOM_SID *pfile_grp_sid,							canon_ace **ppfile_ace, canon_ace **ppdir_ace,							uint32 security_info_sent, SEC_DESC *psd){	canon_ace *file_ace = NULL;	canon_ace *dir_ace = NULL;	*ppfile_ace = NULL;	*ppdir_ace = NULL;	if(security_info_sent == 0) {		DEBUG(0,("unpack_canon_ace: no security info sent !\n"));		return False;	}	/*	 * If no DACL then this is a chown only security descriptor.	 */	if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl)		return True;	/*	 * Now go through the DACL and create the canon_ace lists.	 */	if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,								&file_ace, &dir_ace, psd->dacl))		return False;	if ((file_ace == NULL) && (dir_ace == NULL)) {		/* W2K traverse DACL set - ignore. */		return True;	}	/*	 * Go through the canon_ace list and merge entries	 * belonging to identical users of identical allow or deny type.	 * We can do this as all deny entries come first, followed by	 * all allow entries (we have mandated this before accepting this acl).	 */	print_canon_ace_list( "file ace - before merge", file_ace);	merge_aces( &file_ace );	print_canon_ace_list( "dir ace - before merge", dir_ace);	merge_aces( &dir_ace );	/*	 * NT ACLs are order dependent. Go through the acl lists and	 * process DENY entries by masking the allow entries.	 */	print_canon_ace_list( "file ace - before deny", file_ace);	process_deny_list( &file_ace);	print_canon_ace_list( "dir ace - before deny", dir_ace);	process_deny_list( &dir_ace);	/*	 * A well formed POSIX file or default ACL has at least 3 entries, a 	 * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ	 * and optionally a mask entry. Ensure this is the case.	 */	print_canon_ace_list( "file ace - before valid", file_ace);	/*	 * A default 3 element mode entry for a file should be r-- --- ---.	 * A default 3 element mode entry for a directory should be rwx --- ---.	 */	pst->st_mode = create_default_mode(fsp, False);	if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {		free_canon_ace_list(file_ace);		free_canon_ace_list(dir_ace);		return False;	}	print_canon_ace_list( "dir ace - before valid", dir_ace);	/*	 * A default inheritable 3 element mode entry for a directory should be the	 * mode Samba will use to create a file within. Ensure user rwx bits are set if	 * it's a directory.	 */	pst->st_mode = create_default_mode(fsp, True);	if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {		free_canon_ace_list(file_ace);		free_canon_ace_list(dir_ace);		return False;	}	print_canon_ace_list( "file ace - return", file_ace);	print_canon_ace_list( "dir ace - return", dir_ace);	*ppfile_ace = file_ace;	*ppdir_ace = dir_ace;	return True;}/****************************************************************************** When returning permissions, try and fit NT display semantics if possible. Note the the canon_entries here must have been malloced. The list format should be - first entry = owner, followed by group and other user entries, last entry = other. Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries are not ordered, and match on the most specific entry rather than walking a list, then a simple POSIX permission of rw-r--r-- should really map to 5 entries, Entry 0: owner : deny all except read and write. Entry 1: owner : allow read and write. Entry 2: group : deny all except read. Entry 3: group : allow read. Entry 4: Everyone : allow read. But NT cannot display this in their ACL editor !********************************************************************************/static void arrange_posix_perms( char *filename, canon_ace **pp_list_head){	canon_ace *list_head = *pp_list_head;	canon_ace *owner_ace = NULL;	canon_ace *other_ace = NULL;	canon_ace *ace = NULL;	for (ace = list_head; ace; ace = ace->next) {		if (ace->type == SMB_ACL_USER_OBJ)			owner_ace = ace;		else if (ace->type == SMB_ACL_OTHER) {			/* Last ace - this is "other" */			other_ace = ace;		}	}			if (!owner_ace || !other_ace) {		DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",			filename ));		return;	}	/*	 * The POSIX algorithm applies to owner first, and other last,	 * so ensure they are arranged in this order.	 */	if (owner_ace) {		DLIST_PROMOTE(list_head, owner_ace);	}	if (other_ace) {		DLIST_DEMOTE(list_head, other_ace, ace);	}	/* We have probably changed the head of the list. */	*pp_list_head = list_head;}		/**************************************************************************** Create a linked list of canonical ACE entries.****************************************************************************/static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,					const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type){	connection_struct *conn = fsp->conn;	mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);	canon_ace *list_head = NULL;	canon_ace *ace = NULL;	canon_ace *next_ace = NULL;	int entry_id = SMB_ACL_FIRST_ENTRY;	SMB_ACL_ENTRY_T entry;	size_t ace_count;	while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {		SMB_ACL_TAG_T tagtype;		SMB_ACL_PERMSET_T permset;		DOM_SID sid;		posix_id unix_ug;		enum ace_owner owner_type;		/* get_next... */		if (entry_id == SMB_ACL_FIRST_ENTRY)			entry_id = SMB_ACL_NEXT_ENTRY;		/* Is this a MASK entry ? */		if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)			continue;		if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)			continue;		/* Decide which SID to use based on the ACL type. */		switch(tagtype) {			case SMB_ACL_USER_OBJ:				/* Get the SID from the owner. */				sid_copy(&sid, powner);				unix_ug.uid = psbuf->st_uid;				owner_type = UID_ACE;				break;			case SMB_ACL_USER:				{					uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);					if (puid == NULL) {						DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));						continue;					}					/*					 * A SMB_ACL_USER entry for the owner is shadowed by the					 * SMB_ACL_USER_OBJ entry and Windows also cannot represent					 * that entry, so we ignore it. We also don't create such					 * entries out of the blue when setting ACLs, so a get/set					 * cycle will drop them.					 */					if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) {						SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);						continue;					}					uid_to_sid( &sid, *puid);					unix_ug.uid = *puid;					owner_type = UID_ACE;					SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);					break;				}			case SMB_ACL_GROUP_OBJ:				/* Get the SID from the owning group. */				sid_copy(&sid, pgroup);				unix_ug.gid = psbuf->st_gid;				owner_type = GID_ACE;				break;			case SMB_ACL_GROUP:				{					gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);					if (pgid == NULL) {						DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));						continue;					}					gid_to_sid( &sid, *pgid);					unix_ug.gid = *pgid;					owner_type = GID_ACE;					SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);					break;				}			case SMB_ACL_MASK:				acl_mask = convert_permset_to_mode_t(conn, permset);				continue; /* Don't count the mask as an entry. */			case SMB_ACL_OTHER:

⌨️ 快捷键说明

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