summaryrefslogtreecommitdiff
path: root/source4/ntvfs
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-12-30 05:50:23 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:07:44 -0500
commite913a48ded85e7baf91a355fff46fe270afed936 (patch)
tree9133ded6ec35d1855798cc2bb13a6c78e0e07633 /source4/ntvfs
parent447a346f0dea0b6099f047b406b55b7304bf2d46 (diff)
downloadsamba-e913a48ded85e7baf91a355fff46fe270afed936.tar.gz
samba-e913a48ded85e7baf91a355fff46fe270afed936.tar.bz2
samba-e913a48ded85e7baf91a355fff46fe270afed936.zip
r4408: added the remaining access check hooks into pvfs. All calls should now have acl checking,
and obey the various inheritance rules. (This used to be commit 5fe51807d6b97e68b65f152c0f405e5c5a025d21)
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