s3:smbd: convert '\\' into '/' in SMB2 Create
[ira/wip.git] / source3 / smbd / smb2_create.c
index 0e3cd164cd9216cf3caf6335e097def32c579e1e..1517ab8b3515290ed5b3b17d5ed726f35da37ae3 100644 (file)
@@ -88,7 +88,9 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req)
        in_name_offset          = SVAL(inbody, 0x2C);
        in_name_length          = SVAL(inbody, 0x2E);
 
-       if (in_name_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
+       if (in_name_offset == 0 && in_name_length == 0) {
+               /* This is ok */
+       } else if (in_name_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
                return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
        }
 
@@ -109,7 +111,7 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req)
        }
 
        subreq = smbd_smb2_create_send(req,
-                                      req->conn->smb2.event_ctx,
+                                      req->sconn->smb2.event_ctx,
                                       req,
                                       in_oplock_level,
                                       in_impersonation_level,
@@ -123,6 +125,11 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req)
                return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
        }
        tevent_req_set_callback(subreq, smbd_smb2_request_create_done, req);
+
+       if (tevent_req_is_in_progress(subreq)) {
+               return smbd_smb2_request_pending_queue(req);
+       }
+
        return NT_STATUS_OK;
 }
 
@@ -134,16 +141,16 @@ static void smbd_smb2_request_create_done(struct tevent_req *subreq)
        uint8_t *outhdr;
        DATA_BLOB outbody;
        DATA_BLOB outdyn;
-       uint8_t out_oplock_level;
-       uint32_t out_create_action;
-       NTTIME out_creation_time;
-       NTTIME out_last_access_time;
-       NTTIME out_last_write_time;
-       NTTIME out_change_time;
-       uint64_t out_allocation_size;
-       uint64_t out_end_of_file;
-       uint32_t out_file_attributes;
-       uint64_t out_file_id_volatile;
+       uint8_t out_oplock_level = 0;
+       uint32_t out_create_action = 0;
+       NTTIME out_creation_time = 0;
+       NTTIME out_last_access_time = 0;
+       NTTIME out_last_write_time = 0;
+       NTTIME out_change_time = 0;
+       uint64_t out_allocation_size = 0;
+       uint64_t out_end_of_file = 0;
+       uint32_t out_file_attributes = 0;
+       uint64_t out_file_id_volatile = 0;
        NTSTATUS status;
        NTSTATUS error; /* transport error */
 
@@ -162,7 +169,7 @@ static void smbd_smb2_request_create_done(struct tevent_req *subreq)
        if (!NT_STATUS_IS_OK(status)) {
                error = smbd_smb2_request_error(req, status);
                if (!NT_STATUS_IS_OK(error)) {
-                       smbd_server_connection_terminate(req->conn,
+                       smbd_server_connection_terminate(req->sconn,
                                                         nt_errstr(error));
                        return;
                }
@@ -175,7 +182,7 @@ static void smbd_smb2_request_create_done(struct tevent_req *subreq)
        if (outbody.data == NULL) {
                error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
                if (!NT_STATUS_IS_OK(error)) {
-                       smbd_server_connection_terminate(req->conn,
+                       smbd_server_connection_terminate(req->sconn,
                                                         nt_errstr(error));
                        return;
                }
@@ -213,7 +220,7 @@ static void smbd_smb2_request_create_done(struct tevent_req *subreq)
 
        error = smbd_smb2_request_done(req, outbody, &outdyn);
        if (!NT_STATUS_IS_OK(error)) {
-               smbd_server_connection_terminate(req->conn,
+               smbd_server_connection_terminate(req->sconn,
                                                 nt_errstr(error));
                return;
        }
@@ -252,7 +259,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
        files_struct *result;
        int info;
        SMB_STRUCT_STAT sbuf;
-       struct smb_filename *smb_fname = NULL;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct smbd_smb2_create_state);
@@ -309,20 +315,30 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                }
                info = FILE_WAS_CREATED;
        } else {
-               char *fname = NULL;
+               struct smb_filename *smb_fname = NULL;
 
                /* these are ignored for SMB2 */
                in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
                in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
 
+               /* convert '\\' into '/' */
+               status = check_path_syntax(in_name);
+               if (!NT_STATUS_IS_OK(status)) {
+                       tevent_req_nterror(req, status);
+                       TALLOC_FREE(smb_fname);
+                       goto out;
+               }
+
                status = filename_convert(talloc_tos(),
                                        smbreq->conn,
                                        smbreq->flags2 & FLAGS2_DFS_PATHNAMES,
                                        in_name,
-                                       &smb_fname,
-                                       &fname);
+                                       0,
+                                       NULL,
+                                       &smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
+                       TALLOC_FREE(smb_fname);
                        goto out;
                }
 
@@ -343,9 +359,11 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                                             &info);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
+                       TALLOC_FREE(smb_fname);
                        goto out;
                }
                sbuf = smb_fname->st;
+               TALLOC_FREE(smb_fname);
        }
 
        smb2req->compat_chain_fsp = smbreq->chain_fsp;
@@ -364,8 +382,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
        state->out_allocation_size      = sbuf.st_ex_blksize * sbuf.st_ex_blocks;
        state->out_end_of_file          = sbuf.st_ex_size;
        state->out_file_attributes      = dos_mode(result->conn,
-                                                  result->fsp_name,
-                                                  &sbuf);
+                                                  result->fsp_name);
        if (state->out_file_attributes == 0) {
                state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
        }
@@ -373,7 +390,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
        tevent_req_done(req);
  out:
-       TALLOC_FREE(smb_fname);
        return tevent_req_post(req, ev);
 }