summaryrefslogtreecommitdiff
path: root/source4/ntvfs
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs')
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c21
-rw-r--r--source4/ntvfs/posix/pvfs_mkdir.c16
-rw-r--r--source4/ntvfs/posix/pvfs_open.c18
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c37
-rw-r--r--source4/ntvfs/posix/pvfs_rename.c22
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c52
6 files changed, 159 insertions, 7 deletions
diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c
index c2309b92ea..a5cd9ebd79 100644
--- a/source4/ntvfs/posix/pvfs_acl.c
+++ b/source4/ntvfs/posix/pvfs_acl.c
@@ -371,9 +371,30 @@ NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
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 smbsrv_request *req,
+ struct pvfs_filename *name)
+{
+ 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, name, SEC_DIR_ADD_FILE);
+}
+
/*
determine if an ACE is inheritable
diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c
index 14fffb6a2e..d2d431ae79 100644
--- a/source4/ntvfs/posix/pvfs_mkdir.c
+++ b/source4/ntvfs/posix/pvfs_mkdir.c
@@ -22,6 +22,7 @@
#include "includes.h"
#include "vfs_posix.h"
+#include "librpc/gen_ndr/ndr_security.h"
/*
create a directory with EAs
@@ -43,6 +44,11 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ status = pvfs_access_check_create(pvfs, req, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
if (mkdir(name->full_name, mode) == -1) {
@@ -108,6 +114,11 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ status = pvfs_access_check_create(pvfs, req, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
if (mkdir(name->full_name, mode) == -1) {
@@ -146,6 +157,11 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = pvfs_xattr_unlink_hook(pvfs, name->full_name);
if (!NT_STATUS_IS_OK(status)) {
return status;
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 1695d8e1d9..3941414cd8 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -198,10 +198,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
if (name->exists) {
/* check the security descriptor */
status = pvfs_access_check(pvfs, req, name, &access_mask);
- if (!NT_STATUS_IS_OK(status)) {
- idr_remove(pvfs->idtree_fnum, fnum);
- return status;
- }
+ } else {
+ status = pvfs_access_check_create(pvfs, req, name);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ idr_remove(pvfs->idtree_fnum, fnum);
+ return status;
}
f->fnum = fnum;
@@ -450,6 +452,11 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
mode_t mode;
uint32_t attrib;
+ status = pvfs_access_check_create(pvfs, req, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
(create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
return NT_STATUS_CANNOT_DELETE;
@@ -1065,6 +1072,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
/* if this was a stream create then create the stream as well */
if (!name->stream_exists) {
+ if (!(access_mask & SEC_FILE_WRITE_ATTRIBUTE)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
status = pvfs_stream_create(pvfs, f->handle->name, fd);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(lck);
diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c
index 75a9909492..dae9ca649c 100644
--- a/source4/ntvfs/posix/pvfs_qfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_qfileinfo.c
@@ -24,6 +24,31 @@
#include "vfs_posix.h"
#include "librpc/gen_ndr/ndr_xattr.h"
+
+/*
+ determine what access bits are needed for a call
+*/
+static uint32_t pvfs_fileinfo_access(enum smb_fileinfo_level level)
+{
+ uint32_t needed;
+
+ switch (level) {
+ case RAW_FILEINFO_EA_LIST:
+ case RAW_FILEINFO_ALL_EAS:
+ needed = SEC_FILE_READ_EA;
+ break;
+
+ case RAW_FILEINFO_IS_NAME_VALID:
+ needed = 0;
+ break;
+
+ default:
+ needed = SEC_FILE_READ_ATTRIBUTE;
+ break;
+ }
+ return needed;
+}
+
/*
reply to a RAW_FILEINFO_EA_LIST call
*/
@@ -269,6 +294,12 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ status = pvfs_access_check_simple(pvfs, req, name,
+ pvfs_fileinfo_access(info->generic.level));
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = pvfs_map_fileinfo(pvfs, req, name, info, -1);
return status;
@@ -284,6 +315,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
struct pvfs_file *f;
struct pvfs_file_handle *h;
NTSTATUS status;
+ uint32_t access_needed;
f = pvfs_find_fd(pvfs, req, info->generic.in.fnum);
if (!f) {
@@ -291,6 +323,11 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
}
h = f->handle;
+ access_needed = pvfs_fileinfo_access(info->generic.level);
+ if (!(f->access_mask & access_needed)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
/* update the file information */
status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c
index 0ca05bbc17..9fe92c9173 100644
--- a/source4/ntvfs/posix/pvfs_rename.c
+++ b/source4/ntvfs/posix/pvfs_rename.c
@@ -169,6 +169,11 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs,
}
}
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
fname2 = talloc_asprintf(mem_ctx, "%s/%s", dir_path, fname2);
if (fname2 == NULL) {
return NT_STATUS_NO_MEMORY;
@@ -283,6 +288,11 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs,
return status;
}
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = pvfs_can_rename(pvfs, name1);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -357,18 +367,30 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs,
switch (ren->ntrename.in.flags) {
case RENAME_FLAG_RENAME:
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (rename(name1->full_name, name2->full_name) == -1) {
return pvfs_map_errno(pvfs, errno);
}
break;
case RENAME_FLAG_HARD_LINK:
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (link(name1->full_name, name2->full_name) == -1) {
return pvfs_map_errno(pvfs, errno);
}
break;
case RENAME_FLAG_COPY:
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
return pvfs_copy_file(pvfs, name1, name2);
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index 31db6ce630..10eb082183 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -27,6 +27,38 @@
/*
+ determine what access bits are needed for a call
+*/
+static uint32_t pvfs_setfileinfo_access(enum smb_setfileinfo_level level)
+{
+ uint32_t needed;
+
+ switch (level) {
+ case RAW_SFILEINFO_EA_SET:
+ needed = SEC_FILE_WRITE_EA;
+ break;
+
+ case RAW_SFILEINFO_DISPOSITION_INFO:
+ case RAW_SFILEINFO_DISPOSITION_INFORMATION:
+ needed = SEC_STD_DELETE;
+ break;
+
+ case RAW_SFILEINFO_END_OF_FILE_INFO:
+ needed = SEC_FILE_WRITE_DATA;
+ break;
+
+ case RAW_SFILEINFO_POSITION_INFORMATION:
+ needed = 0;
+ break;
+
+ default:
+ needed = SEC_FILE_WRITE_ATTRIBUTE;
+ break;
+ }
+ return needed;
+}
+
+/*
rename_information level
*/
static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
@@ -100,6 +132,11 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
}
}
+ status = pvfs_access_check_create(pvfs, req, name2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if (rename(name->full_name, name2->full_name) == -1) {
return pvfs_map_errno(pvfs, errno);
}
@@ -202,6 +239,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
uint32_t create_options;
struct pvfs_filename newstats;
NTSTATUS status;
+ uint32_t access_needed;
f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
if (!f) {
@@ -210,6 +248,11 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
h = f->handle;
+ access_needed = pvfs_setfileinfo_access(info->generic.level);
+ if (!(f->access_mask & access_needed)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
/* update the file information */
status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
if (!NT_STATUS_IS_OK(status)) {
@@ -272,9 +315,6 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
case RAW_SFILEINFO_DISPOSITION_INFO:
case RAW_SFILEINFO_DISPOSITION_INFORMATION:
- if (!(f->access_mask & SEC_STD_DELETE)) {
- return NT_STATUS_ACCESS_DENIED;
- }
create_options = h->create_options;
if (info->disposition_info.in.delete_on_close) {
create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
@@ -389,6 +429,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
struct pvfs_filename newstats;
NTSTATUS status;
struct utimbuf unix_times;
+ uint32_t access_needed;
/* resolve the cifs name to a posix name */
status = pvfs_resolve_name(pvfs, req, info->generic.file.fname,
@@ -401,6 +442,11 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ access_needed = pvfs_setfileinfo_access(info->generic.level);
+ status = pvfs_access_check_simple(pvfs, req, name, access_needed);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
/* we take a copy of the current file stats, then update
newstats in each of the elements below. At the end we