#include "vfs_posix.h"
#include "system/dir.h"
#include "system/time.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "messaging/messaging.h"
#include "librpc/gen_ndr/xattr.h"
struct ntvfs_request *req,
struct pvfs_filename *name,
int fd, struct pvfs_file *f,
- union smb_open *io)
+ union smb_open *io,
+ struct security_descriptor *sd)
{
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_OK;
/* setup any EAs that were asked for */
if (io->ntcreatex.in.ea_list) {
}
/* setup an initial sec_desc if requested */
- if (io->ntcreatex.in.sec_desc) {
+ if (sd && (sd->type & SEC_DESC_DACL_PRESENT)) {
union smb_setfileinfo set;
/*
* TODO: set the full ACL!
*/
set.set_secdesc.in.file.ntvfs = f->ntvfs;
set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
- set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc;
+ set.set_secdesc.in.sd = sd;
status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set);
- } else {
- /* otherwise setup an inherited acl from the parent */
- status = pvfs_acl_inherit(pvfs, req, name, fd);
}
return status;
uint32_t create_options;
uint32_t share_access;
bool forced;
+ struct security_descriptor *sd = NULL;
create_options = io->generic.in.create_options;
share_access = io->generic.in.share_access;
if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED &&
(io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) &&
(io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
+ DEBUG(3,(__location__ ": Invalid access_mask/create_options 0x%08x 0x%08x for %s\n",
+ io->ntcreatex.in.access_mask, io->ntcreatex.in.create_options, name->original_name));
return NT_STATUS_INVALID_PARAMETER;
}
case NTCREATEX_DISP_OVERWRITE:
case NTCREATEX_DISP_SUPERSEDE:
default:
+ DEBUG(3,(__location__ ": Invalid open disposition 0x%08x for %s\n",
+ io->generic.in.open_disposition, name->original_name));
return NT_STATUS_INVALID_PARAMETER;
}
if (name->exists) {
/* check the security descriptor */
status = pvfs_access_check(pvfs, req, name, &access_mask);
- } else {
- status = pvfs_access_check_create(pvfs, req, name, &access_mask);
+ } else {
+ sd = io->ntcreatex.in.sec_desc;
+ status = pvfs_access_check_create(pvfs, req, name, &access_mask, true, &sd);
}
NT_STATUS_NOT_OK_RETURN(status);
f->handle->fd = -1;
f->handle->odb_locking_key = data_blob(NULL, 0);
f->handle->create_options = io->generic.in.create_options;
+ f->handle->private_flags = io->generic.in.private_flags;
f->handle->seek_offset = 0;
f->handle->position = 0;
f->handle->mode = 0;
goto cleanup_delete;
}
- status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io);
+ status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io, sd);
if (!NT_STATUS_IS_OK(status)) {
goto cleanup_delete;
}
if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) {
if (utimes(h->name->full_name, tv) == -1) {
- DEBUG(0,("pvfs_handle_destructor: utimes() failed '%s' - %s\n",
+ DEBUG(3,("pvfs_handle_destructor: utimes() failed '%s' - %s\n",
h->name->full_name, strerror(errno)));
}
}
struct pvfs_filename *parent;
uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
bool allow_level_II_oplock = false;
+ struct security_descriptor *sd = NULL;
if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) {
+ DEBUG(3,(__location__ ": Invalid file_attr 0x%08x for %s\n",
+ io->ntcreatex.in.file_attr, name->original_name));
return NT_STATUS_INVALID_PARAMETER;
}
if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_ENCRYPTED) {
+ DEBUG(3,(__location__ ": Invalid encryption request for %s\n",
+ name->original_name));
return NT_STATUS_ACCESS_DENIED;
}
if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
(create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
+ DEBUG(4,(__location__ ": Invalid delete on close for readonly file %s\n",
+ name->original_name));
return NT_STATUS_CANNOT_DELETE;
}
- status = pvfs_access_check_create(pvfs, req, name, &access_mask);
+ sd = io->ntcreatex.in.sec_desc;
+ status = pvfs_access_check_create(pvfs, req, name, &access_mask, false, &sd);
NT_STATUS_NOT_OK_RETURN(status);
/* check that the parent isn't opened with delete on close set */
}
- status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io);
+ status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io, sd);
if (!NT_STATUS_IS_OK(status)) {
goto cleanup_delete;
}
f->handle->name = talloc_steal(f->handle, name);
f->handle->fd = fd;
f->handle->create_options = io->generic.in.create_options;
+ f->handle->private_flags = io->generic.in.private_flags;
f->handle->seek_offset = 0;
f->handle->position = 0;
f->handle->mode = 0;
/* destroy a pending request */
static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r)
{
- struct pvfs_state *pvfs = r->ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(r->ntvfs->private_data,
+ struct pvfs_state);
if (r->odb_locking_key.data) {
struct odb_lock *lck;
lck = odb_lock(r->req, pvfs->odb_context, &r->odb_locking_key);
void *private_data,
enum pvfs_wait_notice reason))
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct pvfs_odb_retry *r;
struct pvfs_wait *wait_handle;
NTSTATUS status;
struct ntvfs_request *req, union smb_open *io,
struct pvfs_file *f, struct odb_lock *lck)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct pvfs_file *f2;
struct pvfs_filename *name;
NTSTATUS status;
if (f2 != f &&
f2->ntvfs->session_info == req->session_info &&
f2->ntvfs->smbpid == req->smbpid &&
- (f2->handle->create_options &
+ (f2->handle->private_flags &
(NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
(f2->access_mask & SEC_FILE_WRITE_DATA) &&
/* quite an insane set of semantics ... */
if (is_exe_filename(io->generic.in.fname) &&
- (f2->handle->create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
+ (f2->handle->private_flags & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
return NT_STATUS_SHARING_VIOLATION;
}
struct odb_lock *lck,
NTSTATUS parent_status)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
NTSTATUS status;
struct timeval end_time;
struct timeval *final_timeout = NULL;
- if (io->generic.in.create_options &
+ if (io->generic.in.private_flags &
(NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
/* see if we can satisfy the request using the special DENY_DOS
code */
NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_open *io)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
int flags = 0;
struct pvfs_filename *name;
struct pvfs_file *f;
access_mask = io->generic.in.access_mask;
if (share_access & ~NTCREATEX_SHARE_ACCESS_MASK) {
+ DEBUG(3,(__location__ ": Invalid share_access 0x%08x for %s\n",
+ share_access, io->ntcreatex.in.fname));
return NT_STATUS_INVALID_PARAMETER;
}
* but we reuse some of them as private values for the generic mapping
*/
create_options_must_ignore_mask = NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
- create_options_must_ignore_mask &= ~NTCREATEX_OPTIONS_PRIVATE_MASK;
create_options &= ~create_options_must_ignore_mask;
if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) {
+ DEBUG(2,(__location__ " create_options 0x%x not supported\n",
+ create_options));
return NT_STATUS_NOT_SUPPORTED;
}
if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) {
+ DEBUG(3,(__location__ ": Invalid create_options 0x%08x for %s\n",
+ create_options, io->ntcreatex.in.fname));
return NT_STATUS_INVALID_PARAMETER;
}
/* other create options are not allowed */
if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
!(access_mask & SEC_STD_DELETE)) {
+ DEBUG(3,(__location__ ": Invalid delete_on_close option 0x%08x with access_mask 0x%08x for %s\n",
+ create_options, access_mask, io->ntcreatex.in.fname));
return NT_STATUS_INVALID_PARAMETER;
}
return NT_STATUS_ACCESS_DENIED;
}
+ /* cope with non-zero root_fid */
+ if (io->ntcreatex.in.root_fid.ntvfs != NULL) {
+ f = pvfs_find_fd(pvfs, req, io->ntcreatex.in.root_fid.ntvfs);
+ if (f == NULL) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ if (f->handle->fd != -1) {
+ return NT_STATUS_INVALID_DEVICE_REQUEST;
+ }
+ io->ntcreatex.in.fname = talloc_asprintf(req, "%s\\%s",
+ f->handle->name->original_name,
+ io->ntcreatex.in.fname);
+ NT_STATUS_HAVE_NO_MEMORY(io->ntcreatex.in.fname);
+ }
+
if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE|
FILE_ATTRIBUTE_VOLUME|
(~FILE_ATTRIBUTE_ALL_MASK))) {
+ DEBUG(3,(__location__ ": Invalid file_attr 0x%08x for %s\n",
+ io->ntcreatex.in.file_attr, io->ntcreatex.in.fname));
return NT_STATUS_INVALID_PARAMETER;
}
break;
default:
+ DEBUG(3,(__location__ ": Invalid open disposition 0x%08x for %s\n",
+ io->generic.in.open_disposition, name->original_name));
return NT_STATUS_INVALID_PARAMETER;
}
f->handle->fd = -1;
f->handle->name = talloc_steal(f->handle, name);
f->handle->create_options = io->generic.in.create_options;
+ f->handle->private_flags = io->generic.in.private_flags;
f->handle->seek_offset = 0;
f->handle->position = 0;
f->handle->mode = 0;
if (fd == -1) {
status = pvfs_map_errno(f->pvfs, errno);
+ DEBUG(0,(__location__ " mapped errno %s for %s (was %d)\n",
+ nt_errstr(status), f->handle->name->full_name, errno));
/*
* STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
*/
if (f->handle->name->stream_id == 0 &&
(io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
- /* for overwrite we need to replace file permissions */
+ /* for overwrite we may need to replace file permissions */
uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
mode_t mode = pvfs_fileperms(pvfs, attrib);
- if (fchmod(fd, mode) == -1) {
+ if (f->handle->name->st.st_mode != mode &&
+ f->handle->name->dos.attrib != attrib &&
+ fchmod(fd, mode) == -1) {
talloc_free(lck);
return pvfs_map_errno(pvfs, errno);
}
NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_close *io)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct pvfs_file *f;
if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct pvfs_file *f, *next;
+ /* If pvfs is NULL, we never logged on, and no files are open. */
+ if(pvfs == NULL) {
+ return NT_STATUS_OK;
+ }
+
for (f=pvfs->files.list;f;f=next) {
next = f->next;
if (f->ntvfs->session_info == req->session_info) {
NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req)
{
- struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
+ struct pvfs_state);
struct pvfs_file *f, *next;
for (f=pvfs->files.list;f;f=next) {
NTCREATEX_SHARE_ACCESS_WRITE |
NTCREATEX_SHARE_ACCESS_DELETE;
/*
- * I would have thought that we would need to pass
- * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too
- *
- * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions
- * to set the filesize.
- *
- * --metze
+ * this code previous set only SEC_FILE_WRITE_ATTRIBUTE, with
+ * a comment that this seemed to be wrong, but matched windows
+ * behaviour. It now appears that this windows behaviour is
+ * just a bug.
*/
- access_mask = SEC_FILE_WRITE_ATTRIBUTE;
+ access_mask = SEC_FILE_WRITE_ATTRIBUTE | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
delete_on_close = false;
break_to_none = true;