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

📄 pvfs_acl.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   POSIX NTVFS backend - ACL support   Copyright (C) Andrew Tridgell 2004   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 3 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, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "auth/auth.h"#include "vfs_posix.h"#include "librpc/gen_ndr/xattr.h"#include "libcli/security/security.h"/* the list of currently registered ACL backends */static struct pvfs_acl_backend {	const struct pvfs_acl_ops *ops;} *backends = NULL;static int num_backends;/*  register a pvfs acl backend.   The 'name' can be later used by other backends to find the operations  structure for this backend.  */NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops){	struct pvfs_acl_ops *new_ops;	if (pvfs_acl_backend_byname(ops->name) != NULL) {		DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));		return NT_STATUS_OBJECT_NAME_COLLISION;	}	backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);	NT_STATUS_HAVE_NO_MEMORY(backends);	new_ops = talloc_memdup(backends, ops, sizeof(*ops));	new_ops->name = talloc_strdup(new_ops, ops->name);	backends[num_backends].ops = new_ops;	num_backends++;	DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));	return NT_STATUS_OK;}/*  return the operations structure for a named backend*/const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name){	int i;	for (i=0;i<num_backends;i++) {		if (strcmp(backends[i].ops->name, name) == 0) {			return backends[i].ops;		}	}	return NULL;}/*  map a single access_mask from generic to specific bits for files/dirs*/static uint32_t pvfs_translate_mask(uint32_t access_mask){	if (access_mask & SEC_MASK_GENERIC) {		if (access_mask & SEC_GENERIC_READ)    access_mask |= SEC_RIGHTS_FILE_READ;		if (access_mask & SEC_GENERIC_WRITE)   access_mask |= SEC_RIGHTS_FILE_WRITE;		if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;		if (access_mask & SEC_GENERIC_ALL)     access_mask |= SEC_RIGHTS_FILE_ALL;		access_mask &= ~SEC_MASK_GENERIC;	}	return access_mask;}/*  map any generic access bits in the given acl  this relies on the fact that the mappings for files and directories  are the same*/static void pvfs_translate_generic_bits(struct security_acl *acl){	unsigned i;	if (!acl) return;	for (i=0;i<acl->num_aces;i++) {		struct security_ace *ace = &acl->aces[i];		ace->access_mask = pvfs_translate_mask(ace->access_mask);	}}/*  setup a default ACL for a file*/static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,				 struct ntvfs_request *req,				 struct pvfs_filename *name, int fd, 				 struct security_descriptor **psd){	struct security_descriptor *sd;	NTSTATUS status;	struct security_ace ace;	mode_t mode;	struct id_mapping *ids;	struct composite_context *ctx;	*psd = security_descriptor_initialise(req);	if (*psd == NULL) {		return NT_STATUS_NO_MEMORY;	}	sd = *psd;	ids = talloc_zero_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[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;	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);	talloc_free(ids);	sd->type |= SEC_DESC_DACL_PRESENT;	mode = name->st.st_mode;	/*	  we provide up to 4 ACEs	    - Owner	    - Group	    - Everyone	    - Administrator	 */	/* setup owner ACE */	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;	ace.flags = 0;	ace.trustee = *sd->owner_sid;	ace.access_mask = 0;	if (mode & S_IRUSR) {		if (mode & S_IWUSR) {			ace.access_mask |= SEC_RIGHTS_FILE_ALL;		} else {			ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;		}	}	if (mode & S_IWUSR) {		ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;	}	if (ace.access_mask) {		security_descriptor_dacl_add(sd, &ace);	}	/* setup group ACE */	ace.trustee = *sd->group_sid;	ace.access_mask = 0;	if (mode & S_IRGRP) {		ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;	}	if (mode & S_IWGRP) {		/* note that delete is not granted - this matches posix behaviour */		ace.access_mask |= SEC_RIGHTS_FILE_WRITE;	}	if (ace.access_mask) {		security_descriptor_dacl_add(sd, &ace);	}	/* setup other ACE */	ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);	ace.access_mask = 0;	if (mode & S_IROTH) {		ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;	}	if (mode & S_IWOTH) {		ace.access_mask |= SEC_RIGHTS_FILE_WRITE;	}	if (ace.access_mask) {		security_descriptor_dacl_add(sd, &ace);	}	/* setup system ACE */	ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);	ace.access_mask = SEC_RIGHTS_FILE_ALL;	security_descriptor_dacl_add(sd, &ace);		return NT_STATUS_OK;}				 /*  omit any security_descriptor elements not specified in the given  secinfo flags*/static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags){	if (!(secinfo_flags & SECINFO_OWNER)) {		sd->owner_sid = NULL;	}	if (!(secinfo_flags & SECINFO_GROUP)) {		sd->group_sid = NULL;	}	if (!(secinfo_flags & SECINFO_DACL)) {		sd->dacl = NULL;	}	if (!(secinfo_flags & SECINFO_SACL)) {		sd->sacl = NULL;	}}/*  answer a setfileinfo for an ACL*/NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 		      struct ntvfs_request *req,		      struct pvfs_filename *name, int fd, 		      uint32_t access_mask,		      union smb_setfileinfo *info){	uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;	struct security_descriptor *new_sd, *sd, orig_sd;	NTSTATUS status = NT_STATUS_NOT_FOUND;	uid_t old_uid = -1;	gid_t old_gid = -1;	uid_t new_uid = -1;	gid_t new_gid = -1;	struct id_mapping *ids;	struct composite_context *ctx;	if (pvfs->acl_ops != NULL) {		status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);	}	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		status = pvfs_default_acl(pvfs, req, name, fd, &sd);	}	if (!NT_STATUS_IS_OK(status)) {		return status;	}	ids = talloc(req, struct id_mapping);	NT_STATUS_HAVE_NO_MEMORY(ids);	ids->unixid = NULL;	ids->sid = NULL;	ids->status = NT_STATUS_NONE_MAPPED;	new_sd = info->set_secdesc.in.sd;	orig_sd = *sd;	old_uid = name->st.st_uid;	old_gid = name->st.st_gid;	/* only set the elements that have been specified */	if (secinfo_flags & SECINFO_OWNER) {		if (!(access_mask & SEC_STD_WRITE_OWNER)) {			return NT_STATUS_ACCESS_DENIED;		}		if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {			ids->sid = new_sd->owner_sid;			ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);			NT_STATUS_HAVE_NO_MEMORY(ctx);			status = wbc_sids_to_xids_recv(ctx, &ids);			NT_STATUS_NOT_OK_RETURN(status);			if (ids->unixid->type == ID_TYPE_BOTH ||			    ids->unixid->type == ID_TYPE_UID) {				new_uid = ids->unixid->id;			}		}		sd->owner_sid = new_sd->owner_sid;	}	if (secinfo_flags & SECINFO_GROUP) {		if (!(access_mask & SEC_STD_WRITE_OWNER)) {			return NT_STATUS_ACCESS_DENIED;		}		if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {			ids->sid = new_sd->group_sid;			ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);			NT_STATUS_HAVE_NO_MEMORY(ctx);			status = wbc_sids_to_xids_recv(ctx, &ids);			NT_STATUS_NOT_OK_RETURN(status);			if (ids->unixid->type == ID_TYPE_BOTH ||			    ids->unixid->type == ID_TYPE_GID) {				new_gid = ids->unixid->id;			}		}		sd->group_sid = new_sd->group_sid;	}	if (secinfo_flags & SECINFO_DACL) {		if (!(access_mask & SEC_STD_WRITE_DAC)) {			return NT_STATUS_ACCESS_DENIED;		}		sd->dacl = new_sd->dacl;		pvfs_translate_generic_bits(sd->dacl);	}	if (secinfo_flags & SECINFO_SACL) {		if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {			return NT_STATUS_ACCESS_DENIED;		}		sd->sacl = new_sd->sacl;		pvfs_translate_generic_bits(sd->sacl);	}	if (new_uid == old_uid) {		new_uid = -1;	}	if (new_gid == old_gid) {		new_gid = -1;	}	/* if there's something to change try it */	if (new_uid != -1 || new_gid != -1) {		int ret;		if (fd == -1) {			ret = chown(name->full_name, new_uid, new_gid);		} else {			ret = fchown(fd, new_uid, new_gid);		}		if (ret == -1) {			return pvfs_map_errno(pvfs, errno);		}	}	/* we avoid saving if the sd is the same. This means when clients	   copy files and end up copying the default sd that we don't	   needlessly use xattrs */	if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {		status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);	}	return status;}/*  answer a fileinfo query for the ACL*/NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 			struct ntvfs_request *req,			struct pvfs_filename *name, int fd, 			union smb_fileinfo *info){	NTSTATUS status = NT_STATUS_NOT_FOUND;	struct security_descriptor *sd;	if (pvfs->acl_ops) {		status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);	}	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		status = pvfs_default_acl(pvfs, req, name, fd, &sd);	}	if (!NT_STATUS_IS_OK(status)) {		return status;	}	normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);	info->query_secdesc.out.sd = sd;	return NT_STATUS_OK;}/*  check the read only bit against any of the write access bits*/

⌨️ 快捷键说明

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