summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <Volker.Lendecke@SerNet.DE>2013-08-28 15:39:41 -0700
committerKarolin Seeger <kseeger@samba.org>2013-08-30 10:07:19 +0200
commitb55072ccf8d801726aec49a925f5a69277a10494 (patch)
treed303a0f41560425b8478dc89f7d32200ee05b567
parent87adc2118677b7cabc3f3b476313b254856f5f9d (diff)
downloadsamba-b55072ccf8d801726aec49a925f5a69277a10494.tar.gz
smbd: Fix a profile problem
When trying to read a profile, under certain circumstances Windows tries to read with its machine account first. The profile previously written was stored with an ACL that only allows access for the user and not the machine. Windows should get an NT_STATUS_ACCESS_DENIED when using the machine account, making it retry with the user account (which would then succeed). Samba under these circumstances erroneously gives NT_STATUS_OBJECT_PATH_NOT_FOUND, which makes Windows give up and not retry. The reasons is the "dropbox" patch in unix_convert, turning EACCESS on the last path component to OBJECT_PATH_NOT_FOUND. This patch makes the dropbox behaviour only kick in when we are creating a file. I think this is an abstraction violation. unix_convert() should not have to know about the create_disposition, but given that we have pathname resolution separated from the core open code right now this is the best we can do. Signed-off-by: Volker Lendecke <Volker.Lendecke@SerNet.DE> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/smbd/filename.c3
-rw-r--r--source3/smbd/nttrans.c6
-rw-r--r--source3/smbd/reply.c48
-rw-r--r--source3/smbd/smb2_create.c3
5 files changed, 34 insertions, 27 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 873657a892f..2d04373d7b6 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1716,6 +1716,7 @@ struct smb_file_time {
#define UCF_COND_ALLOW_WCARD_LCOMP 0x00000004
#define UCF_POSIX_PATHNAMES 0x00000008
#define UCF_UNIX_NAME_LOOKUP 0x00000010
+#define UCF_CREATING_FILE 0x00000020
/*
* smb_filename
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 207b56ce772..934634a5b6c 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -718,7 +718,8 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* can only put stuff with permission -wx.
*/
if ((errno != 0) && (errno != ENOENT)
- && (errno != EACCES)) {
+ && ((ucf_flags & UCF_CREATING_FILE) &&
+ (errno != EACCES))) {
/*
* ENOTDIR and ELOOP both map to
* NT_STATUS_OBJECT_PATH_NOT_FOUND
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index a884b2f38f4..4c145e01dcc 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -536,7 +536,8 @@ void reply_ntcreate_and_X(struct smb_request *req)
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ (create_disposition == FILE_CREATE)
+ ? UCF_CREATING_FILE : 0,
NULL,
&smb_fname);
@@ -1165,7 +1166,8 @@ static void call_nt_transact_create(connection_struct *conn,
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ (create_disposition == FILE_CREATE)
+ ? UCF_CREATING_FILE : 0,
NULL,
&smb_fname);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index ca3a08f8723..0585a6edc96 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1748,11 +1748,20 @@ void reply_open(struct smb_request *req)
goto out;
}
+ if (!map_open_params_to_ntcreate(fname, deny_mode,
+ OPENX_FILE_EXISTS_OPEN, &access_mask,
+ &share_mode, &create_disposition,
+ &create_options, &private_flags)) {
+ reply_force_doserror(req, ERRDOS, ERRbadaccess);
+ goto out;
+ }
+
status = filename_convert(ctx,
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ (create_disposition == FILE_CREATE)
+ ? UCF_CREATING_FILE : 0,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
@@ -1766,14 +1775,6 @@ void reply_open(struct smb_request *req)
goto out;
}
- if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
- OPENX_FILE_EXISTS_OPEN, &access_mask,
- &share_mode, &create_disposition,
- &create_options, &private_flags)) {
- reply_force_doserror(req, ERRDOS, ERRbadaccess);
- goto out;
- }
-
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
@@ -1923,11 +1924,22 @@ void reply_open_and_X(struct smb_request *req)
goto out;
}
+ if (!map_open_params_to_ntcreate(fname, deny_mode,
+ smb_ofun,
+ &access_mask, &share_mode,
+ &create_disposition,
+ &create_options,
+ &private_flags)) {
+ reply_force_doserror(req, ERRDOS, ERRbadaccess);
+ goto out;
+ }
+
status = filename_convert(ctx,
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ (create_disposition == FILE_CREATE)
+ ? UCF_CREATING_FILE : 0,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
@@ -1941,16 +1953,6 @@ void reply_open_and_X(struct smb_request *req)
goto out;
}
- if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
- smb_ofun,
- &access_mask, &share_mode,
- &create_disposition,
- &create_options,
- &private_flags)) {
- reply_force_doserror(req, ERRDOS, ERRbadaccess);
- goto out;
- }
-
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
@@ -2145,7 +2147,7 @@ void reply_mknew(struct smb_request *req)
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ UCF_CREATING_FILE,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
@@ -2286,7 +2288,7 @@ void reply_ctemp(struct smb_request *req)
status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ UCF_CREATING_FILE,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
@@ -5539,7 +5541,7 @@ void reply_mkdir(struct smb_request *req)
status = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- 0,
+ UCF_CREATING_FILE,
NULL,
&smb_dname);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 5b81099928f..08629901427 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -694,7 +694,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
smb1req->conn,
smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ (in_create_disposition == FILE_CREATE) ?
+ UCF_CREATING_FILE : 0,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {