#include "vfs_posix.h"
#include "librpc/gen_ndr/xattr.h"
#include "libcli/security/security.h"
+#include "param/param.h"
/* the list of currently registered ACL backends */
The 'name' can be later used by other backends to find the operations
structure for this backend.
*/
-_PUBLIC_ NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
+NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
{
struct pvfs_acl_ops *new_ops;
/*
return the operations structure for a named backend
*/
-_PUBLIC_ const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
+const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
{
int i;
return NULL;
}
+NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
+{
+ static bool initialized = false;
+ extern NTSTATUS pvfs_acl_nfs4_init(void);
+ extern NTSTATUS pvfs_acl_xattr_init(void);
+ init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
+ init_module_fn *shared_init;
+
+ if (initialized) return NT_STATUS_OK;
+ initialized = true;
+
+ shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
+
+ run_init_functions(static_init);
+ run_init_functions(shared_init);
+
+ talloc_free(shared_init);
+
+ return NT_STATUS_OK;
+}
+
/*
map a single access_mask from generic to specific bits for files/dirs
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) {
}
sd = *psd;
- status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ 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;
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);
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;
return NT_STATUS_ACCESS_DENIED;
}
if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
- status = sidmap_sid_to_unixuid(pvfs->sidmap, new_sd->owner_sid, &new_uid);
+ 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;
}
return NT_STATUS_ACCESS_DENIED;
}
if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
- status = sidmap_sid_to_unixgid(pvfs->sidmap, new_sd->group_sid, &new_gid);
+ 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;
}
/*
check the read only bit against any of the write access bits
*/
-static BOOL pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
+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_STD_WRITE_DAC |
SEC_STD_WRITE_OWNER |
SEC_DIR_DELETE_CHILD))) {
- return True;
+ return true;
}
- return False;
+ return false;
}
/*
}
if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
- return NT_STATUS_PRIVILEGE_NOT_HELD;
+ return NT_STATUS_ACCESS_DENIED;
}
if (*access_mask & ~max_bits) {
return NT_STATUS_ACCESS_DENIED;
}
- *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+ 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;
}
NTSTATUS status;
struct security_descriptor *sd;
+ /* on SMB2 a blank access mask is always denied */
+ if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
+ *access_mask == 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (pvfs_read_only(pvfs, *access_mask)) {
return NT_STATUS_ACCESS_DENIED;
}
/* expand the generic access bits to file specific bits */
*access_mask = pvfs_translate_mask(*access_mask);
- *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
+ 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)) {
/* check the acl against the required access mask */
status = sec_access_check(sd, token, *access_mask, access_mask);
- /* this bit is always granted, even if not asked for */
- *access_mask |= SEC_FILE_READ_ATTRIBUTE;
+ 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);
/*
determine if an ACE is inheritable
*/
-static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
+static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
const struct security_ace *ace,
- BOOL container)
+ bool container)
{
if (!container) {
return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
}
if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
- return True;
+ return true;
}
if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
!(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
- return True;
+ return true;
}
- return False;
+ return false;
}
/*
static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
struct security_descriptor *parent_sd,
struct security_descriptor *sd,
- BOOL container)
+ bool container)
{
int i;
NTSTATUS status;
struct pvfs_filename *parent;
struct security_descriptor *parent_sd, *sd;
- BOOL container;
+ bool container;
+ struct id_mapping *ids;
+ struct composite_context *ctx;
/* form the parents path */
status = pvfs_resolve_parent(pvfs, req, name, &parent);
return NT_STATUS_NO_MEMORY;
}
- status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ 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;
+ 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);
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);
+}