Vector correctly through reply_openerror() (which uses the same logic).
[ira/wip.git] / source3 / smbd / nttrans.c
index 5c6d78089d71077f2cea4d44c32130f7500e3138..be50090192df017f67d972d9e971ebd131ecffb9 100644 (file)
@@ -374,6 +374,53 @@ static void do_ntcreate_pipe_open(connection_struct *conn,
        chain_reply(req);
 }
 
+struct case_semantics_state {
+       connection_struct *conn;
+       bool case_sensitive;
+       bool case_preserve;
+       bool short_case_preserve;
+};
+
+/****************************************************************************
+ Restore case semantics.
+****************************************************************************/
+
+static int restore_case_semantics(struct case_semantics_state *state)
+{
+       state->conn->case_sensitive = state->case_sensitive;
+       state->conn->case_preserve = state->case_preserve;
+       state->conn->short_case_preserve = state->short_case_preserve;
+       return 0;
+}
+
+/****************************************************************************
+ Save case semantics.
+****************************************************************************/
+
+static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
+                                               connection_struct *conn)
+{
+       struct case_semantics_state *result;
+
+       if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
+               return NULL;
+       }
+
+       result->conn = conn;
+       result->case_sensitive = conn->case_sensitive;
+       result->case_preserve = conn->case_preserve;
+       result->short_case_preserve = conn->short_case_preserve;
+
+       /* Set to POSIX. */
+       conn->case_sensitive = True;
+       conn->case_preserve = True;
+       conn->short_case_preserve = True;
+
+       talloc_set_destructor(result, restore_case_semantics);
+
+       return result;
+}
+
 /****************************************************************************
  Reply to an NT create and X call.
 ****************************************************************************/
@@ -406,23 +453,19 @@ void reply_ntcreate_and_X(struct smb_request *req)
        NTSTATUS status;
        int oplock_request;
        uint8_t oplock_granted = NO_OPLOCK_RETURN;
+       struct case_semantics_state *case_state = NULL;
        TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBntcreateX);
 
        if (req->wct < 24) {
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return;
+               goto out;
        }
 
        flags = IVAL(req->vwv+3, 1);
        access_mask = IVAL(req->vwv+7, 1);
        file_attributes = IVAL(req->vwv+13, 1);
-       /*
-        * Bug #6898 - clients using Windows opens should
-        * never be able to set this attribute.
-        */
-       file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
        share_access = IVAL(req->vwv+15, 1);
        create_disposition = IVAL(req->vwv+17, 1);
        create_options = IVAL(req->vwv+19, 1);
@@ -479,6 +522,14 @@ void reply_ntcreate_and_X(struct smb_request *req)
                        ? BATCH_OPLOCK : 0;
        }
 
+       if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+               case_state = set_posix_case_semantics(ctx, conn);
+               if (!case_state) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+       }
+
        status = filename_convert(ctx,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
@@ -487,6 +538,8 @@ void reply_ntcreate_and_X(struct smb_request *req)
                                NULL,
                                &smb_fname);
 
+       TALLOC_FREE(case_state);
+
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -498,6 +551,13 @@ void reply_ntcreate_and_X(struct smb_request *req)
                goto out;
        }
 
+       /*
+        * Bug #6898 - clients using Windows opens should
+        * never be able to set this attribute into the
+        * VFS.
+        */
+       file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */
@@ -520,12 +580,7 @@ void reply_ntcreate_and_X(struct smb_request *req)
                        /* We have re-scheduled this call, no error. */
                        goto out;
                }
-               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-                       reply_botherror(req, status, ERRDOS, ERRfilexists);
-               }
-               else {
-                       reply_nterror(req, status);
-               }
+               reply_openerror(req, status);
                goto out;
        }
 
@@ -884,6 +939,7 @@ static void call_nt_transact_create(connection_struct *conn,
        uint64_t allocation_size;
        int oplock_request;
        uint8_t oplock_granted;
+       struct case_semantics_state *case_state = NULL;
        TALLOC_CTX *ctx = talloc_tos();
 
        DEBUG(5,("call_nt_transact_create\n"));
@@ -918,11 +974,6 @@ static void call_nt_transact_create(connection_struct *conn,
        flags = IVAL(params,0);
        access_mask = IVAL(params,8);
        file_attributes = IVAL(params,20);
-       /*
-        * Bug #6898 - clients using Windows opens should
-        * never be able to set this attribute.
-        */
-       file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
        share_access = IVAL(params,24);
        create_disposition = IVAL(params,28);
        create_options = IVAL(params,32);
@@ -1000,6 +1051,14 @@ static void call_nt_transact_create(connection_struct *conn,
                goto out;
        }
 
+       if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+               case_state = set_posix_case_semantics(ctx, conn);
+               if (!case_state) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       goto out;
+               }
+       }
+
        status = filename_convert(ctx,
                                conn,
                                req->flags2 & FLAGS2_DFS_PATHNAMES,
@@ -1008,6 +1067,8 @@ static void call_nt_transact_create(connection_struct *conn,
                                NULL,
                                &smb_fname);
 
+       TALLOC_FREE(case_state);
+
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req,
@@ -1025,6 +1086,13 @@ static void call_nt_transact_create(connection_struct *conn,
                        ? BATCH_OPLOCK : 0;
        }
 
+       /*
+        * Bug #6898 - clients using Windows opens should
+        * never be able to set this attribute into the
+        * VFS.
+        */
+       file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+
        status = SMB_VFS_CREATE_FILE(
                conn,                                   /* conn */
                req,                                    /* req */