⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pvfs_acl.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask){	if ((pvfs->flags & PVFS_FLAG_READONLY) &&	    (access_mask & (SEC_FILE_WRITE_DATA |			    SEC_FILE_APPEND_DATA | 			    SEC_FILE_WRITE_EA | 			    SEC_FILE_WRITE_ATTRIBUTE | 			    SEC_STD_DELETE | 			    SEC_STD_WRITE_DAC | 			    SEC_STD_WRITE_OWNER | 			    SEC_DIR_DELETE_CHILD))) {		return true;	}	return false;}/*  default access check function based on unix permissions  doing this saves on building a full security descriptor  for the common case of access check on files with no   specific NT ACL*/NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 				struct ntvfs_request *req,				struct pvfs_filename *name,				uint32_t *access_mask){	uid_t uid = geteuid();	uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;	if (pvfs_read_only(pvfs, *access_mask)) {		return NT_STATUS_ACCESS_DENIED;	}	/* owner and root get extra permissions */	if (uid == 0) {		max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;	} else if (uid == name->st.st_uid) {		max_bits |= SEC_STD_ALL;	}	if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {		*access_mask = max_bits;		return NT_STATUS_OK;	}	if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {		return NT_STATUS_ACCESS_DENIED;	}	if (*access_mask & ~max_bits) {		return NT_STATUS_ACCESS_DENIED;	}	if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {		/* on SMB, this bit is always granted, even if not		   asked for */		*access_mask |= SEC_FILE_READ_ATTRIBUTE;	}	return NT_STATUS_OK;}/*  check the security descriptor on a file, if any    *access_mask is modified with the access actually granted*/NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 			   struct ntvfs_request *req,			   struct pvfs_filename *name,			   uint32_t *access_mask){	struct security_token *token = req->session_info->security_token;	struct xattr_NTACL *acl;	NTSTATUS status;	struct security_descriptor *sd;	if (pvfs_read_only(pvfs, *access_mask)) {		return NT_STATUS_ACCESS_DENIED;	}	acl = talloc(req, struct xattr_NTACL);	if (acl == NULL) {		return NT_STATUS_NO_MEMORY;	}	/* expand the generic access bits to file specific bits */	*access_mask = pvfs_translate_mask(*access_mask);	if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {		*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;	}	status = pvfs_acl_load(pvfs, name, -1, acl);	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		talloc_free(acl);		return pvfs_access_check_unix(pvfs, req, name, access_mask);	}	if (!NT_STATUS_IS_OK(status)) {		return status;	}	switch (acl->version) {	case 1:		sd = acl->info.sd;		break;	default:		return NT_STATUS_INVALID_ACL;	}	/* check the acl against the required access mask */	status = sec_access_check(sd, token, *access_mask, access_mask);	if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {		/* on SMB, this bit is always granted, even if not		   asked for */		*access_mask |= SEC_FILE_READ_ATTRIBUTE;	}	talloc_free(acl);		return status;}/*  a simplified interface to access check, designed for calls that  do not take or return an access check mask*/NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 				  struct ntvfs_request *req,				  struct pvfs_filename *name,				  uint32_t access_needed){	if (access_needed == 0) {		return NT_STATUS_OK;	}	return pvfs_access_check(pvfs, req, name, &access_needed);}/*  access check for creating a new file/directory*/NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 				  struct ntvfs_request *req,				  struct pvfs_filename *name,				  uint32_t *access_mask){	struct pvfs_filename *parent;	NTSTATUS status;	status = pvfs_resolve_parent(pvfs, req, name, &parent);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	status = pvfs_access_check(pvfs, req, parent, access_mask);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {		return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);	}	return status;}/*  access check for creating a new file/directory - no access mask supplied*/NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, 				  struct ntvfs_request *req,				  struct pvfs_filename *name,				  uint32_t access_mask){	struct pvfs_filename *parent;	NTSTATUS status;	status = pvfs_resolve_parent(pvfs, req, name, &parent);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	return pvfs_access_check_simple(pvfs, req, parent, access_mask);}/*  determine if an ACE is inheritable*/static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,				 const struct security_ace *ace,				 bool container){	if (!container) {		return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;	}	if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {		return true;	}	if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&	    !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {		return true;	}	return false;}/*  this is the core of ACL inheritance. It copies any inheritable  aces from the parent SD to the child SD. Note that the algorithm   depends on whether the child is a container or not*/static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 				      struct security_descriptor *parent_sd,				      struct security_descriptor *sd,				      bool container){	int i;		for (i=0;i<parent_sd->dacl->num_aces;i++) {		struct security_ace ace = parent_sd->dacl->aces[i];		NTSTATUS status;		const struct dom_sid *creator = NULL, *new_id = NULL;		uint32_t orig_flags;		if (!pvfs_inheritable_ace(pvfs, &ace, container)) {			continue;		}		orig_flags = ace.flags;		/* see the RAW-ACLS inheritance test for details on these rules */		if (!container) {			ace.flags = 0;		} else {			ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;			if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {				ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;			}			if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {				ace.flags = 0;			}		}		/* the CREATOR sids are special when inherited */		if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {			creator = pvfs->sid_cache.creator_owner;			new_id = sd->owner_sid;		} else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {			creator = pvfs->sid_cache.creator_group;			new_id = sd->group_sid;		} else {			new_id = &ace.trustee;		}		if (creator && container && 		    (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {			uint32_t flags = ace.flags;			ace.trustee = *new_id;			ace.flags = 0;			status = security_descriptor_dacl_add(sd, &ace);			if (!NT_STATUS_IS_OK(status)) {				return status;			}			ace.trustee = *creator;			ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;			status = security_descriptor_dacl_add(sd, &ace);		} else if (container && 			   !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {			status = security_descriptor_dacl_add(sd, &ace);		} else {			ace.trustee = *new_id;			status = security_descriptor_dacl_add(sd, &ace);		}		if (!NT_STATUS_IS_OK(status)) {			return status;		}	}	return NT_STATUS_OK;}/*  setup an ACL on a new file/directory based on the inherited ACL from  the parent. If there is no inherited ACL then we don't set anything,  as the default ACL applies anyway*/NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 			  struct ntvfs_request *req,			  struct pvfs_filename *name,			  int fd){	struct xattr_NTACL *acl;	NTSTATUS status;	struct pvfs_filename *parent;	struct security_descriptor *parent_sd, *sd;	bool container;	struct id_mapping *ids;	struct composite_context *ctx;	/* form the parents path */	status = pvfs_resolve_parent(pvfs, req, name, &parent);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	acl = talloc(req, struct xattr_NTACL);	if (acl == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = pvfs_acl_load(pvfs, parent, -1, acl);	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		return NT_STATUS_OK;	}	if (!NT_STATUS_IS_OK(status)) {		return status;	}	switch (acl->version) {	case 1:		parent_sd = acl->info.sd;		break;	default:		return NT_STATUS_INVALID_ACL;	}	if (parent_sd == NULL ||	    parent_sd->dacl == NULL ||	    parent_sd->dacl->num_aces == 0) {		/* go with the default ACL */		return NT_STATUS_OK;	}	/* create the new sd */	sd = security_descriptor_initialise(req);	if (sd == NULL) {		return NT_STATUS_NO_MEMORY;	}	ids = talloc_array(sd, struct id_mapping, 2);	NT_STATUS_HAVE_NO_MEMORY(ids);	ids[0].unixid = talloc(ids, struct unixid);	NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);	ids[0].unixid->id = name->st.st_uid;	ids[0].unixid->type = ID_TYPE_UID;	ids[0].sid = NULL;	ids[0].status = NT_STATUS_NONE_MAPPED;	ids[1].unixid = talloc(ids, struct unixid);	NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);	ids[1].unixid->id = name->st.st_gid;	ids[1].unixid->type = ID_TYPE_GID;	ids[1].sid = NULL;	ids[1].status = NT_STATUS_NONE_MAPPED;	ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);	NT_STATUS_HAVE_NO_MEMORY(ctx);	status = wbc_xids_to_sids_recv(ctx, &ids);	NT_STATUS_NOT_OK_RETURN(status);	sd->owner_sid = talloc_steal(sd, ids[0].sid);	sd->group_sid = talloc_steal(sd, ids[1].sid);	sd->type |= SEC_DESC_DACL_PRESENT;	container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;	/* fill in the aces from the parent */	status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	/* if there is nothing to inherit then we fallback to the	   default acl */	if (sd->dacl == NULL || sd->dacl->num_aces == 0) {		return NT_STATUS_OK;	}	acl->info.sd = sd;	status = pvfs_acl_save(pvfs, name, fd, acl);		return status;}/*  return the maximum allowed access mask*/NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs, 				     struct ntvfs_request *req,				     struct pvfs_filename *name,				     uint32_t *maximal_access){	*maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;	return pvfs_access_check(pvfs, req, name, maximal_access);}

⌨️ 快捷键说明

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