smbd: Fix a profile problem
authorVolker Lendecke <Volker.Lendecke@SerNet.DE>
Wed, 28 Aug 2013 22:39:41 +0000 (15:39 -0700)
committerKarolin Seeger <kseeger@samba.org>
Fri, 30 Aug 2013 08:07:19 +0000 (10:07 +0200)
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>
source3/include/smb.h
source3/smbd/filename.c
source3/smbd/nttrans.c
source3/smbd/reply.c
source3/smbd/smb2_create.c

index 873657a892fee37adee3457f4ff735ec04493ebb..2d04373d7b65f01a3e77eae3ff01fb664642b5e1 100644 (file)
@@ -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
index 207b56ce7722ca186f6f4d3715e06dde15650923..934634a5b6c6420d31b2da869c85cd2a1c1ffdeb 100644 (file)
@@ -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
index a884b2f38f424b070c4c7aaf5e2763ea7f8be275..4c145e01dcc806a6ccd3204667168be73254abf9 100644 (file)
@@ -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);
 
index ca3a08f87236749e69d0d8632383d85f8e1e5a16..0585a6edc96a706bffa5e7d730ec6758277fd57d 100644 (file)
@@ -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)) {
index 5b81099928f764c73fadde23d63f7bf463591c0a..08629901427c263b23d8b5ea0073e70320c0e220 100644 (file)
@@ -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)) {