From 3c4af39aa506a25fc6d6753dbe34e4e1c0dd0b43 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Dec 2011 13:40:49 +1100 Subject: s4-ntvfs: added allow_override check based on use of NT ACL This disables the posix permission override if the calculated permissions did not come from a NT ACL. Autobuild-User: Andrew Tridgell Autobuild-Date: Thu Dec 1 05:14:49 CET 2011 on sn-devel-104 --- source4/ntvfs/posix/pvfs_acl.c | 14 +++++++++++++- source4/ntvfs/posix/pvfs_mkdir.c | 12 ++++++------ source4/ntvfs/posix/pvfs_open.c | 16 ++++++++-------- source4/ntvfs/posix/pvfs_rename.c | 5 +++-- source4/ntvfs/posix/pvfs_resolve.c | 3 +++ source4/ntvfs/posix/pvfs_setfileinfo.c | 4 ++-- source4/ntvfs/posix/pvfs_sys.c | 28 ++++++++++++++-------------- source4/ntvfs/posix/pvfs_unlink.c | 2 +- source4/ntvfs/posix/pvfs_util.c | 15 ++++++++------- source4/ntvfs/posix/vfs_posix.h | 1 + 10 files changed, 59 insertions(+), 41 deletions(-) (limited to 'source4') diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c index 664196ab3e..810dcddbd3 100644 --- a/source4/ntvfs/posix/pvfs_acl.c +++ b/source4/ntvfs/posix/pvfs_acl.c @@ -643,6 +643,14 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, /* check the acl against the required access mask */ status = se_access_check(sd, token, *access_mask, access_mask); talloc_free(acl); + + /* if we used a NT acl, then allow access override if the + share allows for posix permission override + */ + if (NT_STATUS_IS_OK(status)) { + name->allow_override = (pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) != 0; + } + done: if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) { /* on SMB, this bit is always granted, even if not @@ -771,7 +779,11 @@ NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs, return status; } - return pvfs_access_check_simple(pvfs, req, parent, access_mask); + status = pvfs_access_check_simple(pvfs, req, parent, access_mask); + if (NT_STATUS_IS_OK(status) && parent->allow_override) { + name->allow_override = true; + } + return status; } diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c index 10de1d6d5c..2cf43ab1e1 100644 --- a/source4/ntvfs/posix/pvfs_mkdir.c +++ b/source4/ntvfs/posix/pvfs_mkdir.c @@ -51,7 +51,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs, mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY); - if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) { + if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) { return pvfs_map_errno(pvfs, errno); } @@ -69,7 +69,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs, /* setup an inherited acl from the parent */ status = pvfs_acl_inherit(pvfs, req, name, -1); if (!NT_STATUS_IS_OK(status)) { - pvfs_sys_rmdir(pvfs, name->full_name); + pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override); return status; } @@ -78,7 +78,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs, md->t2mkdir.in.num_eas, md->t2mkdir.in.eas); if (!NT_STATUS_IS_OK(status)) { - pvfs_sys_rmdir(pvfs, name->full_name); + pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override); return status; } @@ -127,7 +127,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs, mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY); - if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) { + if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) { return pvfs_map_errno(pvfs, errno); } @@ -136,7 +136,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs, /* setup an inherited acl from the parent */ status = pvfs_acl_inherit(pvfs, req, name, -1); if (!NT_STATUS_IS_OK(status)) { - pvfs_sys_rmdir(pvfs, name->full_name); + pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override); return status; } @@ -179,7 +179,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs, return status; } - if (pvfs_sys_rmdir(pvfs, name->full_name) == -1) { + if (pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override) == -1) { /* some olders systems don't return ENOTEMPTY to rmdir() */ if (errno == EEXIST) { return NT_STATUS_DIRECTORY_NOT_EMPTY; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c0f55e8e73..a095f74633 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -73,7 +73,7 @@ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h) DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", delete_path, nt_errstr(status))); } - if (pvfs_sys_rmdir(h->pvfs, delete_path) != 0) { + if (pvfs_sys_rmdir(h->pvfs, delete_path, h->name->allow_override) != 0) { DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n", delete_path, strerror(errno))); } @@ -344,7 +344,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; mode_t mode = pvfs_fileperms(pvfs, attrib); - if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) { + if (pvfs_sys_mkdir(pvfs, name->full_name, mode, name->allow_override) == -1) { return pvfs_map_errno(pvfs,errno); } @@ -432,7 +432,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - pvfs_sys_rmdir(pvfs, name->full_name); + pvfs_sys_rmdir(pvfs, name->full_name, name->allow_override); return status; } @@ -514,7 +514,7 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", delete_path, nt_errstr(status))); } - if (pvfs_sys_unlink(h->pvfs, delete_path) != 0) { + if (pvfs_sys_unlink(h->pvfs, delete_path, h->name->allow_override) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", delete_path, strerror(errno))); } else { @@ -677,7 +677,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, mode = pvfs_fileperms(pvfs, attrib); /* create the file */ - fd = pvfs_sys_open(pvfs, name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode); + fd = pvfs_sys_open(pvfs, name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode, name->allow_override); if (fd == -1) { return pvfs_map_errno(pvfs, errno); } @@ -856,7 +856,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, cleanup_delete: close(fd); - pvfs_sys_unlink(pvfs, name->full_name); + pvfs_sys_unlink(pvfs, name->full_name, name->allow_override); return status; } @@ -1549,7 +1549,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* do the actual open */ - fd = pvfs_sys_open(pvfs, f->handle->name->full_name, flags | O_NONBLOCK, 0); + fd = pvfs_sys_open(pvfs, f->handle->name->full_name, flags | O_NONBLOCK, 0, name->allow_override); if (fd == -1) { status = pvfs_map_errno(f->pvfs, errno); @@ -1635,7 +1635,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (f->handle->name->st.st_mode != mode && f->handle->name->dos.attrib != attrib && - pvfs_sys_fchmod(pvfs, fd, mode) == -1) { + pvfs_sys_fchmod(pvfs, fd, mode, name->allow_override) == -1) { talloc_free(lck); return pvfs_map_errno(pvfs, errno); } diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index 5296811f02..432716130c 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -37,7 +37,8 @@ NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs, uint32_t mask; NTSTATUS status; - if (pvfs_sys_rename(pvfs, name1->full_name, name2) == -1) { + if (pvfs_sys_rename(pvfs, name1->full_name, name2, + name1->allow_override) == -1) { return pvfs_map_errno(pvfs, errno); } @@ -624,7 +625,7 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, case RENAME_FLAG_COPY: status = pvfs_access_check_parent(pvfs, req, name2, SEC_DIR_ADD_FILE); NT_STATUS_NOT_OK_RETURN(status); - return pvfs_copy_file(pvfs, name1, name2); + return pvfs_copy_file(pvfs, name1, name2, name1->allow_override && name2->allow_override); case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: DEBUG(3,(__location__ ": Invalid rename cluster for %s\n", diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 255728382e..837ea174d6 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -518,6 +518,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, (*name)->exists = false; (*name)->stream_exists = false; + (*name)->allow_override = false; if (!(pvfs->fs_attribs & FS_ATTR_NAMED_STREAMS)) { flags &= ~PVFS_RESOLVE_STREAMS; @@ -630,6 +631,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->original_name = talloc_strdup(*name, fname); (*name)->stream_name = NULL; (*name)->stream_id = 0; + (*name)->allow_override = false; status = pvfs_fill_dos_info(pvfs, *name, flags, -1); @@ -815,6 +817,7 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, } (*name)->stream_name = NULL; (*name)->stream_id = 0; + (*name)->allow_override = false; status = pvfs_fill_dos_info(pvfs, *name, PVFS_RESOLVE_NO_OPENDB, -1); diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index cbb5c7853c..3c9b18d91c 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -534,7 +534,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, } mode = pvfs_fileperms(pvfs, newstats.dos.attrib); if (!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { - if (pvfs_sys_fchmod(pvfs, h->fd, mode) == -1) { + if (pvfs_sys_fchmod(pvfs, h->fd, mode, h->name->allow_override) == -1) { return pvfs_map_errno(pvfs, errno); } } @@ -859,7 +859,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, newstats.dos.attrib |= (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY); if (newstats.dos.attrib != name->dos.attrib) { mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib); - if (pvfs_sys_chmod(pvfs, name->full_name, mode) == -1) { + if (pvfs_sys_chmod(pvfs, name->full_name, mode, name->allow_override) == -1) { return pvfs_map_errno(pvfs, errno); } change_mask |= FILE_NOTIFY_CHANGE_ATTRIBUTES; diff --git a/source4/ntvfs/posix/pvfs_sys.c b/source4/ntvfs/posix/pvfs_sys.c index f110590153..9112848bfe 100644 --- a/source4/ntvfs/posix/pvfs_sys.c +++ b/source4/ntvfs/posix/pvfs_sys.c @@ -256,7 +256,7 @@ static int pvfs_sys_chown(struct pvfs_state *pvfs, struct pvfs_sys_ctx *ctx, con /* wrap open for system override */ -int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode_t mode) +int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode_t mode, bool allow_override) { int fd, ret; struct pvfs_sys_ctx *ctx; @@ -267,7 +267,7 @@ int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode fd = open(filename, flags, mode); if (fd != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return fd; } @@ -366,7 +366,7 @@ int pvfs_sys_open(struct pvfs_state *pvfs, const char *filename, int flags, mode /* wrap unlink for system override */ -int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename) +int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -376,7 +376,7 @@ int pvfs_sys_unlink(struct pvfs_state *pvfs, const char *filename) ret = unlink(filename); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } @@ -415,7 +415,7 @@ static bool contains_symlink(const char *path) /* wrap rename for system override */ -int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name2) +int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name2, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -425,7 +425,7 @@ int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name ret = rename(name1, name2); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } @@ -480,7 +480,7 @@ int pvfs_sys_rename(struct pvfs_state *pvfs, const char *name1, const char *name /* wrap mkdir for system override */ -int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode) +int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -490,7 +490,7 @@ int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode) ret = mkdir(dirname, mode); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } @@ -525,7 +525,7 @@ int pvfs_sys_mkdir(struct pvfs_state *pvfs, const char *dirname, mode_t mode) /* wrap rmdir for system override */ -int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname) +int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -535,7 +535,7 @@ int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname) ret = rmdir(dirname); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } @@ -563,7 +563,7 @@ int pvfs_sys_rmdir(struct pvfs_state *pvfs, const char *dirname) /* wrap fchmod for system override */ -int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode) +int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -573,7 +573,7 @@ int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode) ret = fchmod(fd, mode); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } @@ -602,7 +602,7 @@ int pvfs_sys_fchmod(struct pvfs_state *pvfs, int fd, mode_t mode) /* wrap chmod for system override */ -int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode) +int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode, bool allow_override) { int ret; struct pvfs_sys_ctx *ctx; @@ -612,7 +612,7 @@ int pvfs_sys_chmod(struct pvfs_state *pvfs, const char *filename, mode_t mode) ret = chmod(filename, mode); if (ret != -1 || - !(pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) || + !allow_override || errno != EACCES) { return ret; } diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index be2ba53148..a4b51d1d7d 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -123,7 +123,7 @@ static NTSTATUS pvfs_unlink_file(struct pvfs_state *pvfs, } /* finally try the actual unlink */ - if (pvfs_sys_unlink(pvfs, name->full_name) == -1) { + if (pvfs_sys_unlink(pvfs, name->full_name, name->allow_override) == -1) { status = pvfs_map_errno(pvfs, errno); } diff --git a/source4/ntvfs/posix/pvfs_util.c b/source4/ntvfs/posix/pvfs_util.c index c6c6eaa13c..6afb928d73 100644 --- a/source4/ntvfs/posix/pvfs_util.c +++ b/source4/ntvfs/posix/pvfs_util.c @@ -90,7 +90,8 @@ uint32_t pvfs_attrib_normalise(uint32_t attrib, mode_t mode) */ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, struct pvfs_filename *name1, - struct pvfs_filename *name2) + struct pvfs_filename *name2, + bool allow_override) { int fd1, fd2; mode_t mode; @@ -102,13 +103,13 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fd1 = pvfs_sys_open(pvfs, name1->full_name, O_RDONLY, 0); + fd1 = pvfs_sys_open(pvfs, name1->full_name, O_RDONLY, 0, allow_override); if (fd1 == -1) { talloc_free(buf); return pvfs_map_errno(pvfs, errno); } - fd2 = pvfs_sys_open(pvfs, name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0); + fd2 = pvfs_sys_open(pvfs, name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0, allow_override); if (fd2 == -1) { close(fd1); talloc_free(buf); @@ -133,7 +134,7 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, close(fd1); close(fd2); talloc_free(buf); - pvfs_sys_unlink(pvfs, name2->full_name); + pvfs_sys_unlink(pvfs, name2->full_name, allow_override); if (ret2 == -1) { return pvfs_map_errno(pvfs, errno); } @@ -145,10 +146,10 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, close(fd1); mode = pvfs_fileperms(pvfs, name1->dos.attrib); - if (pvfs_sys_fchmod(pvfs, fd2, mode) == -1) { + if (pvfs_sys_fchmod(pvfs, fd2, mode, allow_override) == -1) { status = pvfs_map_errno(pvfs, errno); close(fd2); - pvfs_sys_unlink(pvfs, name2->full_name); + pvfs_sys_unlink(pvfs, name2->full_name, allow_override); return status; } @@ -158,7 +159,7 @@ NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, status = pvfs_dosattrib_save(pvfs, name2, fd2); if (!NT_STATUS_IS_OK(status)) { close(fd2); - pvfs_sys_unlink(pvfs, name2->full_name); + pvfs_sys_unlink(pvfs, name2->full_name, allow_override); return status; } diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index e1593a38cf..9a03658040 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -131,6 +131,7 @@ struct pvfs_filename { bool has_wildcard; bool exists; /* true if the base filename exists */ bool stream_exists; /* true if the stream exists */ + bool allow_override; struct stat st; struct pvfs_dos_fileinfo dos; }; -- cgit