posix_acls.c

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

C
2,170
字号
			mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;		}		break;	case S_IRGRP:		if(sec_access.mask & GENERIC_ALL_ACCESS)			mode = S_IRGRP|S_IWGRP|S_IXGRP;		else {			mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;			mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;			mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;		}		break;	case S_IROTH:		if(sec_access.mask & GENERIC_ALL_ACCESS)			mode = S_IROTH|S_IWOTH|S_IXOTH;		else {			mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;			mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;			mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;		}		break;	}	return mode;}/**************************************************************************** Unpack a SEC_DESC into a UNIX owner and group.****************************************************************************/static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd){	DOM_SID owner_sid;	DOM_SID grp_sid;	*puser = (uid_t)-1;	*pgrp = (gid_t)-1;	if(security_info_sent == 0) {		DEBUG(0,("unpack_nt_owners: no security info sent !\n"));		return True;	}	/*	 * Validate the owner and group SID's.	 */	memset(&owner_sid, '\0', sizeof(owner_sid));	memset(&grp_sid, '\0', sizeof(grp_sid));	DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));	/*	 * Don't immediately fail if the owner sid cannot be validated.	 * This may be a group chown only set.	 */	if (security_info_sent & OWNER_SECURITY_INFORMATION) {		sid_copy(&owner_sid, psd->owner_sid);		if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) {			if (lp_force_unknown_acl_user(snum)) {				/* this allows take ownership to work				 * reasonably */				*puser = current_user.uid;			} else {				DEBUG(3,("unpack_nt_owners: unable to validate"					 " owner sid for %s\n",					 sid_string_static(&owner_sid)));				return False;			}		} 	}	/*	 * Don't immediately fail if the group sid cannot be validated.	 * This may be an owner chown only set.	 */	if (security_info_sent & GROUP_SECURITY_INFORMATION) {		sid_copy(&grp_sid, psd->grp_sid);		if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) {			if (lp_force_unknown_acl_user(snum)) {				/* this allows take group ownership to work				 * reasonably */				*pgrp = current_user.gid;			} else {				DEBUG(3,("unpack_nt_owners: unable to validate"					 " group sid.\n"));				return False;			}		}	}	DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));	return True;}/**************************************************************************** Ensure the enforced permissions for this share apply.****************************************************************************/static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type){	int snum = SNUM(fsp->conn);	mode_t and_bits = (mode_t)0;	mode_t or_bits = (mode_t)0;	/* Get the initial bits to apply. */	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);	}	/* Now bounce them into the S_USR space. */		switch(type) {	case S_IRUSR:		/* Ensure owner has read access. */		pace->perms |= S_IRUSR;		if (fsp->is_directory)			pace->perms |= (S_IWUSR|S_IXUSR);		and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);		or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);		break;	case S_IRGRP:		and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);		or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);		break;	case S_IROTH:		and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);		or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);		break;	}	pace->perms = ((pace->perms & and_bits)|or_bits);}/**************************************************************************** Check if a given uid/SID is in a group gid/SID. This is probably very expensive and will need optimisation. A *lot* of optimisation :-). JRA.****************************************************************************/static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ){	fstring u_name;	fstring g_name;	/* "Everyone" always matches every uid. */	if (sid_equal(&group_ace->trustee, &global_sid_World))		return True;	/* Assume that the current user is in the current group (force group) */	if (uid_ace->unix_ug.uid == current_user.uid && group_ace->unix_ug.gid == current_user.gid)		return True;	fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));	fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));	/*	 * Due to the winbind interfaces we need to do this via names,	 * not uids/gids.	 */	return user_in_group_list(u_name, g_name, NULL, 0);}/**************************************************************************** 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. In addition, the owner must always have at least read access. When using this call on get_acl, the pst struct is valid and contains the mode of the file. When using this call on set_acl, the pst struct has been modified to have a mode containing the default for this file or directory type.****************************************************************************/static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,							files_struct *fsp,							const DOM_SID *pfile_owner_sid,							const DOM_SID *pfile_grp_sid,							SMB_STRUCT_STAT *pst,							BOOL setting_acl){	canon_ace *pace;	BOOL got_user = False;	BOOL got_grp = False;	BOOL got_other = False;	canon_ace *pace_other = NULL;	for (pace = *pp_ace; pace; pace = pace->next) {		if (pace->type == SMB_ACL_USER_OBJ) {			if (setting_acl)				apply_default_perms(fsp, pace, S_IRUSR);			got_user = True;		} else if (pace->type == SMB_ACL_GROUP_OBJ) {			/*			 * Ensure create mask/force create mode is respected on set.			 */			if (setting_acl)				apply_default_perms(fsp, pace, S_IRGRP);			got_grp = True;		} else if (pace->type == SMB_ACL_OTHER) {			/*			 * Ensure create mask/force create mode is respected on set.			 */			if (setting_acl)				apply_default_perms(fsp, pace, S_IROTH);			got_other = True;			pace_other = pace;		}	}	if (!got_user) {		if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {			DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));			return False;		}		ZERO_STRUCTP(pace);		pace->type = SMB_ACL_USER_OBJ;		pace->owner_type = UID_ACE;		pace->unix_ug.uid = pst->st_uid;		pace->trustee = *pfile_owner_sid;		pace->attr = ALLOW_ACE;		if (setting_acl) {			/* See if the owning user is in any of the other groups in			   the ACE. If so, OR in the permissions from that group. */			BOOL group_matched = False;			canon_ace *pace_iter;			for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {				if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {					if (uid_entry_in_group(pace, pace_iter)) {						pace->perms |= pace_iter->perms;						group_matched = True;					}				}			}			/* If we only got an "everyone" perm, just use that. */			if (!group_matched) {				if (got_other)					pace->perms = pace_other->perms;				else					pace->perms = 0;			}			apply_default_perms(fsp, pace, S_IRUSR);		} else {			pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);		}		DLIST_ADD(*pp_ace, pace);	}	if (!got_grp) {		if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {			DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));			return False;		}		ZERO_STRUCTP(pace);		pace->type = SMB_ACL_GROUP_OBJ;		pace->owner_type = GID_ACE;		pace->unix_ug.uid = pst->st_gid;		pace->trustee = *pfile_grp_sid;		pace->attr = ALLOW_ACE;		if (setting_acl) {			/* If we only got an "everyone" perm, just use that. */			if (got_other)				pace->perms = pace_other->perms;			else				pace->perms = 0;			apply_default_perms(fsp, pace, S_IRGRP);		} else {			pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);		}		DLIST_ADD(*pp_ace, pace);	}	if (!got_other) {		if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {			DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));			return False;		}		ZERO_STRUCTP(pace);		pace->type = SMB_ACL_OTHER;		pace->owner_type = WORLD_ACE;		pace->unix_ug.world = -1;		pace->trustee = global_sid_World;		pace->attr = ALLOW_ACE;		if (setting_acl) {			pace->perms = 0;			apply_default_perms(fsp, pace, S_IROTH);		} else			pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);		DLIST_ADD(*pp_ace, pace);	}	return True;}/**************************************************************************** Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries. If it does not have them, check if there are any entries where the trustee is the file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.****************************************************************************/static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid){	BOOL got_user_obj, got_group_obj;	canon_ace *current_ace;	int i, entries;	entries = count_canon_ace_list(ace);	got_user_obj = False;	got_group_obj = False;	for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {		if (current_ace->type == SMB_ACL_USER_OBJ)			got_user_obj = True;		else if (current_ace->type == SMB_ACL_GROUP_OBJ)			got_group_obj = True;	}	if (got_user_obj && got_group_obj) {		DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));		return;	}	for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {		if (!got_user_obj && current_ace->owner_type == UID_ACE &&				sid_equal(&current_ace->trustee, pfile_owner_sid)) {			current_ace->type = SMB_ACL_USER_OBJ;			got_user_obj = True;		}		if (!got_group_obj && current_ace->owner_type == GID_ACE &&				sid_equal(&current_ace->trustee, pfile_grp_sid)) {			current_ace->type = SMB_ACL_GROUP_OBJ;			got_group_obj = True;		}	}	if (!got_user_obj)		DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));	if (!got_group_obj)		DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));}/**************************************************************************** Unpack a SEC_DESC into two canonical ace lists.****************************************************************************/static BOOL create_canon_ace_lists(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,							SEC_ACL *dacl){	BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);	canon_ace *file_ace = NULL;	canon_ace *dir_ace = NULL;	canon_ace *tmp_ace = NULL;	canon_ace *current_ace = NULL;	BOOL got_dir_allow = False;	BOOL got_file_allow = False;	int i, j;	*ppfile_ace = NULL;	*ppdir_ace = NULL;	/*	 * Convert the incoming ACL into a more regular form.	 */	for(i = 0; i < dacl->num_aces; i++) {		SEC_ACE *psa = &dacl->ace[i];		if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {			DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));			return False;		}		if (nt4_compatible_acls()) {			/*			 * The security mask may be UNIX_ACCESS_NONE which should map into			 * no permissions (we overload the WRITE_OWNER bit for this) or it			 * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this			 * to be so. Any other bits override the UNIX_ACCESS_NONE bit.			 */			/*			 * Convert GENERIC bits to specific bits.			 */ 			se_map_generic(&psa->info.mask, &file_generic_mapping);			psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);			if(psa->info.mask != UNIX_ACCESS_NONE)				psa->info.mask &= ~UNIX_ACCESS_NONE;		}	}	/*	 * Deal with the fact that NT 4.x re-writes the canonical format	 * that we return for default ACLs. If a directory ACE is identical	 * to a inherited directory ACE then NT changes the bits so that the	 * first ACE is set to OI|IO and the second ACE for this SID is set	 * to CI. We need to repair this. JRA.	 */	for(i = 0; i < dacl->num_aces; i++) {		SEC_ACE *psa1 = &dacl->ace[i];		for (j = i + 1; j < dacl->num_aces; j++) {			SEC_ACE *psa2 = &dacl->ace[j];

⌨️ 快捷键说明

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