smbd: Fix a profile problem
authorVolker Lendecke <Volker.Lendecke@SerNet.DE>
Tue, 9 Jul 2013 18:02:39 +0000 (11:02 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 9 Jul 2013 19:22:00 +0000 (12:22 -0700)
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/smbd/filename.c
source3/smbd/nttrans.c
source3/smbd/reply.c
source3/smbd/smb2_create.c
source3/smbd/smbd.h

index 03e1d2dfa1e62e75a05ebb30327a8df113f4ce6a..4384f5a5c030c8046dbe1c12b38a090f67ebc830 100644 (file)
@@ -723,7 +723,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 f5e5877d0937d45829b5bd59413cb78c0944a789..516b8267960e7d24c03eeaec6433e836cdf8a8b6 100644 (file)
@@ -538,7 +538,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);
 
@@ -1163,7 +1164,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 07b144e68b38ad7bdc216e0168b2ca7cc7910a6e..2ae3ff4b1e68193fad3ceb8707c7df7fcb495847 100644 (file)
@@ -1906,11 +1906,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)) {
@@ -1924,14 +1933,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 */
@@ -2081,11 +2082,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)) {
@@ -2099,16 +2111,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 */
@@ -2328,7 +2330,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)) {
@@ -2469,7 +2471,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)) {
@@ -5828,7 +5830,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 6a43d274ff8b5c7cba9fd450b548cb7ed10e0535..ba743e76fa7ebc70205f5fa00cd846ce3fc25cab 100644 (file)
@@ -841,7 +841,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                                                  smb1req->conn,
                                                  smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
                                                  fname,
-                                                 0,    /* unix_convert flags */
+                                                 (in_create_disposition == FILE_CREATE) ?
+                                                 UCF_CREATING_FILE : 0,
                                                  NULL, /* ppath_contains_wcards */
                                                  &smb_fname);
                        if (!NT_STATUS_IS_OK(status)) {
index a5b211a678d93f3f95ff1bf634a3d378dafc7505..e76915730d4018f90afbf0b7c90743e8d7af82cd 100644 (file)
@@ -73,5 +73,6 @@ struct trans_state {
 #define UCF_COND_ALLOW_WCARD_LCOMP     0x00000004
 #define UCF_POSIX_PATHNAMES            0x00000008
 #define UCF_UNIX_NAME_LOOKUP           0x00000010
+#define UCF_CREATING_FILE              0x00000020
 
 #endif /* _SMBD_SMBD_H */