LCOV - code coverage report
Current view: top level - source3/smbd - smb2_create.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 686 848 80.9 %
Date: 2021-09-23 10:06:22 Functions: 25 28 89.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             :    Copyright (C) Jeremy Allison 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "printing.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "../libcli/smb/smb_common.h"
      27             : #include "../librpc/gen_ndr/ndr_security.h"
      28             : #include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
      29             : #include "../lib/util/tevent_ntstatus.h"
      30             : #include "messages.h"
      31             : 
      32             : #undef DBGC_CLASS
      33             : #define DBGC_CLASS DBGC_SMB2
      34             : 
      35      450695 : int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
      36             : {
      37      450695 :         switch(in_oplock_level) {
      38      447929 :         case SMB2_OPLOCK_LEVEL_NONE:
      39      447929 :                 return NO_OPLOCK;
      40         236 :         case SMB2_OPLOCK_LEVEL_II:
      41         236 :                 return LEVEL_II_OPLOCK;
      42         192 :         case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
      43         192 :                 return EXCLUSIVE_OPLOCK;
      44        1272 :         case SMB2_OPLOCK_LEVEL_BATCH:
      45        1272 :                 return BATCH_OPLOCK;
      46        1066 :         case SMB2_OPLOCK_LEVEL_LEASE:
      47        1066 :                 return LEASE_OPLOCK;
      48           0 :         default:
      49           0 :                 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
      50             :                         "unknown level %u\n",
      51             :                         (unsigned int)in_oplock_level));
      52           0 :                 return NO_OPLOCK;
      53             :         }
      54             : }
      55             : 
      56      364246 : static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
      57             : {
      58      364872 :         if (BATCH_OPLOCK_TYPE(oplock_type)) {
      59        1124 :                 return SMB2_OPLOCK_LEVEL_BATCH;
      60      363748 :         } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
      61         139 :                 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
      62      363609 :         } else if (oplock_type == LEVEL_II_OPLOCK) {
      63         208 :                 return SMB2_OPLOCK_LEVEL_II;
      64      363401 :         } else if (oplock_type == LEASE_OPLOCK) {
      65         994 :                 return SMB2_OPLOCK_LEVEL_LEASE;
      66             :         } else {
      67      361781 :                 return SMB2_OPLOCK_LEVEL_NONE;
      68             :         }
      69             : }
      70             : 
      71             : /*
      72             :  MS-FSA 2.1.5.1 Server Requests an Open of a File
      73             :  Trailing '/' or '\\' checker.
      74             :  Must be done before the filename parser removes any
      75             :  trailing characters. If we decide to add this to SMB1
      76             :  NTCreate processing we can make this public.
      77             : 
      78             :  Note this is Windows pathname processing only. When
      79             :  POSIX pathnames are added to SMB2 this will not apply.
      80             : */
      81             : 
      82      452936 : static NTSTATUS windows_name_trailing_check(const char *name,
      83             :                         uint32_t create_options)
      84             : {
      85      452936 :         size_t name_len = strlen(name);
      86             :         char trail_c;
      87             : 
      88      452936 :         if (name_len <= 1) {
      89        4305 :                 return NT_STATUS_OK;
      90             :         }
      91             : 
      92      448631 :         trail_c = name[name_len-1];
      93             : 
      94             :         /*
      95             :          * Trailing '/' is always invalid.
      96             :          */
      97      448631 :         if (trail_c == '/') {
      98           8 :                 return NT_STATUS_OBJECT_NAME_INVALID;
      99             :         }
     100             : 
     101      448623 :         if (create_options & FILE_NON_DIRECTORY_FILE) {
     102      246589 :                 if (trail_c == '\\') {
     103           4 :                         return NT_STATUS_OBJECT_NAME_INVALID;
     104             :                 }
     105             :         }
     106      448619 :         return NT_STATUS_OK;
     107             : }
     108             : 
     109             : static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
     110             :                         struct tevent_context *ev,
     111             :                         struct smbd_smb2_request *smb2req,
     112             :                         uint8_t in_oplock_level,
     113             :                         uint32_t in_impersonation_level,
     114             :                         uint32_t in_desired_access,
     115             :                         uint32_t in_file_attributes,
     116             :                         uint32_t in_share_access,
     117             :                         uint32_t in_create_disposition,
     118             :                         uint32_t in_create_options,
     119             :                         const char *in_name,
     120             :                         struct smb2_create_blobs in_context_blobs);
     121             : static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
     122             :                         TALLOC_CTX *mem_ctx,
     123             :                         uint8_t *out_oplock_level,
     124             :                         uint32_t *out_create_action,
     125             :                         struct timespec *out_creation_ts,
     126             :                         struct timespec *out_last_access_ts,
     127             :                         struct timespec *out_last_write_ts,
     128             :                         struct timespec *out_change_ts,
     129             :                         uint64_t *out_allocation_size,
     130             :                         uint64_t *out_end_of_file,
     131             :                         uint32_t *out_file_attributes,
     132             :                         uint64_t *out_file_id_persistent,
     133             :                         uint64_t *out_file_id_volatile,
     134             :                         struct smb2_create_blobs *out_context_blobs);
     135             : 
     136             : static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
     137      468863 : NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
     138             : {
     139             :         const uint8_t *inbody;
     140             :         const struct iovec *indyniov;
     141             :         uint8_t in_oplock_level;
     142             :         uint32_t in_impersonation_level;
     143             :         uint32_t in_desired_access;
     144             :         uint32_t in_file_attributes;
     145             :         uint32_t in_share_access;
     146             :         uint32_t in_create_disposition;
     147             :         uint32_t in_create_options;
     148             :         uint16_t in_name_offset;
     149             :         uint16_t in_name_length;
     150             :         DATA_BLOB in_name_buffer;
     151             :         char *in_name_string;
     152             :         size_t in_name_string_size;
     153      468863 :         uint32_t name_offset = 0;
     154      468863 :         uint32_t name_available_length = 0;
     155             :         uint32_t in_context_offset;
     156             :         uint32_t in_context_length;
     157             :         DATA_BLOB in_context_buffer;
     158             :         struct smb2_create_blobs in_context_blobs;
     159      468863 :         uint32_t context_offset = 0;
     160      468863 :         uint32_t context_available_length = 0;
     161             :         uint32_t dyn_offset;
     162             :         NTSTATUS status;
     163             :         bool ok;
     164             :         struct tevent_req *tsubreq;
     165             : 
     166      468863 :         status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
     167      468863 :         if (!NT_STATUS_IS_OK(status)) {
     168           0 :                 return smbd_smb2_request_error(smb2req, status);
     169             :         }
     170      468863 :         inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
     171             : 
     172      468863 :         in_oplock_level         = CVAL(inbody, 0x03);
     173      468863 :         in_impersonation_level  = IVAL(inbody, 0x04);
     174      468863 :         in_desired_access       = IVAL(inbody, 0x18);
     175      468863 :         in_file_attributes      = IVAL(inbody, 0x1C);
     176      468863 :         in_share_access         = IVAL(inbody, 0x20);
     177      468863 :         in_create_disposition   = IVAL(inbody, 0x24);
     178      468863 :         in_create_options       = IVAL(inbody, 0x28);
     179      468863 :         in_name_offset          = SVAL(inbody, 0x2C);
     180      468863 :         in_name_length          = SVAL(inbody, 0x2E);
     181      468863 :         in_context_offset       = IVAL(inbody, 0x30);
     182      468863 :         in_context_length       = IVAL(inbody, 0x34);
     183             : 
     184             :         /*
     185             :          * First check if the dynamic name and context buffers
     186             :          * are correctly specified.
     187             :          *
     188             :          * Note: That we don't check if the name and context buffers
     189             :          *       overlap
     190             :          */
     191             : 
     192      468863 :         dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
     193             : 
     194      468863 :         if (in_name_offset == 0 && in_name_length == 0) {
     195             :                 /* This is ok */
     196           0 :                 name_offset = 0;
     197      468863 :         } else if (in_name_offset < dyn_offset) {
     198           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     199             :         } else {
     200      468863 :                 name_offset = in_name_offset - dyn_offset;
     201             :         }
     202             : 
     203      468863 :         indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
     204             : 
     205      468863 :         if (name_offset > indyniov->iov_len) {
     206           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     207             :         }
     208             : 
     209      468863 :         name_available_length = indyniov->iov_len - name_offset;
     210             : 
     211      468863 :         if (in_name_length > name_available_length) {
     212           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     213             :         }
     214             : 
     215      468863 :         in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
     216      468863 :         in_name_buffer.length = in_name_length;
     217             : 
     218      468863 :         if (in_context_offset == 0 && in_context_length == 0) {
     219             :                 /* This is ok */
     220      462926 :                 context_offset = 0;
     221        5311 :         } else if (in_context_offset < dyn_offset) {
     222           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     223             :         } else {
     224        5311 :                 context_offset = in_context_offset - dyn_offset;
     225             :         }
     226             : 
     227      468863 :         if (context_offset > indyniov->iov_len) {
     228           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     229             :         }
     230             : 
     231      468863 :         context_available_length = indyniov->iov_len - context_offset;
     232             : 
     233      468863 :         if (in_context_length > context_available_length) {
     234           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     235             :         }
     236             : 
     237      468863 :         in_context_buffer.data = (uint8_t *)indyniov->iov_base +
     238             :                 context_offset;
     239      468863 :         in_context_buffer.length = in_context_length;
     240             : 
     241             :         /*
     242             :          * Now interpret the name and context buffers
     243             :          */
     244             : 
     245      866214 :         ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
     246      468237 :                                    in_name_buffer.data,
     247             :                                    in_name_buffer.length,
     248             :                                    &in_name_string,
     249             :                                    &in_name_string_size);
     250      468863 :         if (!ok) {
     251           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
     252             :         }
     253             : 
     254      468863 :         if (in_name_buffer.length == 0) {
     255        4281 :                 in_name_string_size = 0;
     256             :         }
     257             : 
     258      468863 :         if (strlen(in_name_string) != in_name_string_size) {
     259           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
     260             :         }
     261             : 
     262      468863 :         ZERO_STRUCT(in_context_blobs);
     263      468863 :         status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
     264      468863 :         if (!NT_STATUS_IS_OK(status)) {
     265           0 :                 return smbd_smb2_request_error(smb2req, status);
     266             :         }
     267             : 
     268      866840 :         tsubreq = smbd_smb2_create_send(smb2req,
     269      468863 :                                        smb2req->sconn->ev_ctx,
     270             :                                        smb2req,
     271             :                                        in_oplock_level,
     272             :                                        in_impersonation_level,
     273             :                                        in_desired_access,
     274             :                                        in_file_attributes,
     275             :                                        in_share_access,
     276             :                                        in_create_disposition,
     277             :                                        in_create_options,
     278             :                                        in_name_string,
     279             :                                        in_context_blobs);
     280      468863 :         if (tsubreq == NULL) {
     281           0 :                 smb2req->subreq = NULL;
     282           0 :                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
     283             :         }
     284      468863 :         tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
     285             : 
     286      468863 :         return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
     287             : }
     288             : 
     289      102965 : static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
     290             : {
     291      102965 :         uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
     292      102965 :         return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
     293             : }
     294             : 
     295      468417 : static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
     296             : {
     297      468417 :         struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
     298             :                                         struct smbd_smb2_request);
     299             :         DATA_BLOB outbody;
     300             :         DATA_BLOB outdyn;
     301      468417 :         uint8_t out_oplock_level = 0;
     302      468417 :         uint32_t out_create_action = 0;
     303      468417 :         connection_struct *conn = smb2req->tcon->compat;
     304      468417 :         struct timespec out_creation_ts = { 0, };
     305      468417 :         struct timespec out_last_access_ts = { 0, };
     306      468417 :         struct timespec out_last_write_ts = { 0, };
     307      468417 :         struct timespec out_change_ts = { 0, };
     308      468417 :         uint64_t out_allocation_size = 0;
     309      468417 :         uint64_t out_end_of_file = 0;
     310      468417 :         uint32_t out_file_attributes = 0;
     311      468417 :         uint64_t out_file_id_persistent = 0;
     312      468417 :         uint64_t out_file_id_volatile = 0;
     313             :         struct smb2_create_blobs out_context_blobs;
     314             :         DATA_BLOB out_context_buffer;
     315      468417 :         uint16_t out_context_buffer_offset = 0;
     316             :         NTSTATUS status;
     317             :         NTSTATUS error; /* transport error */
     318             : 
     319      468417 :         status = smbd_smb2_create_recv(tsubreq,
     320             :                                        smb2req,
     321             :                                        &out_oplock_level,
     322             :                                        &out_create_action,
     323             :                                        &out_creation_ts,
     324             :                                        &out_last_access_ts,
     325             :                                        &out_last_write_ts,
     326             :                                        &out_change_ts,
     327             :                                        &out_allocation_size,
     328             :                                        &out_end_of_file,
     329             :                                        &out_file_attributes,
     330             :                                        &out_file_id_persistent,
     331             :                                        &out_file_id_volatile,
     332             :                                        &out_context_blobs);
     333      468417 :         if (!NT_STATUS_IS_OK(status)) {
     334      103497 :                 if (smbd_smb2_is_compound(smb2req)) {
     335          18 :                         smb2req->compound_create_err = status;
     336             :                 }
     337      103497 :                 error = smbd_smb2_request_error(smb2req, status);
     338      103497 :                 if (!NT_STATUS_IS_OK(error)) {
     339           0 :                         smbd_server_connection_terminate(smb2req->xconn,
     340             :                                                          nt_errstr(error));
     341       21054 :                         return;
     342             :                 }
     343      103497 :                 return;
     344             :         }
     345             : 
     346      364920 :         status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
     347      364920 :         if (!NT_STATUS_IS_OK(status)) {
     348           0 :                 error = smbd_smb2_request_error(smb2req, status);
     349           0 :                 if (!NT_STATUS_IS_OK(error)) {
     350           0 :                         smbd_server_connection_terminate(smb2req->xconn,
     351             :                                                          nt_errstr(error));
     352           0 :                         return;
     353             :                 }
     354           0 :                 return;
     355             :         }
     356             : 
     357      364920 :         if (out_context_buffer.length > 0) {
     358        1556 :                 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
     359             :         }
     360             : 
     361      364920 :         outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
     362      364920 :         if (outbody.data == NULL) {
     363           0 :                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
     364           0 :                 if (!NT_STATUS_IS_OK(error)) {
     365           0 :                         smbd_server_connection_terminate(smb2req->xconn,
     366             :                                                          nt_errstr(error));
     367           0 :                         return;
     368             :                 }
     369           0 :                 return;
     370             :         }
     371             : 
     372      364920 :         SSVAL(outbody.data, 0x00, 0x58 + 1);    /* struct size */
     373      364920 :         SCVAL(outbody.data, 0x02,
     374             :               out_oplock_level);                /* oplock level */
     375      364920 :         SCVAL(outbody.data, 0x03, 0);           /* reserved */
     376      364920 :         SIVAL(outbody.data, 0x04,
     377             :               out_create_action);               /* create action */
     378      364920 :         put_long_date_full_timespec(conn->ts_res,
     379      364294 :               (char *)outbody.data + 0x08,
     380             :               &out_creation_ts);            /* creation time */
     381      364920 :         put_long_date_full_timespec(conn->ts_res,
     382      364294 :               (char *)outbody.data + 0x10,
     383             :               &out_last_access_ts);         /* last access time */
     384      364920 :         put_long_date_full_timespec(conn->ts_res,
     385      364294 :               (char *)outbody.data + 0x18,
     386             :               &out_last_write_ts);          /* last write time */
     387      364920 :         put_long_date_full_timespec(conn->ts_res,
     388      364294 :               (char *)outbody.data + 0x20,
     389             :               &out_change_ts);                      /* change time */
     390      364920 :         SBVAL(outbody.data, 0x28,
     391             :               out_allocation_size);             /* allocation size */
     392      364920 :         SBVAL(outbody.data, 0x30,
     393             :               out_end_of_file);                 /* end of file */
     394      364920 :         SIVAL(outbody.data, 0x38,
     395             :               out_file_attributes);             /* file attributes */
     396      364920 :         SIVAL(outbody.data, 0x3C, 0);           /* reserved */
     397      364920 :         SBVAL(outbody.data, 0x40,
     398             :               out_file_id_persistent);          /* file id (persistent) */
     399      364920 :         SBVAL(outbody.data, 0x48,
     400             :               out_file_id_volatile);            /* file id (volatile) */
     401      364920 :         SIVAL(outbody.data, 0x50,
     402             :               out_context_buffer_offset);       /* create contexts offset */
     403      364920 :         SIVAL(outbody.data, 0x54,
     404             :               out_context_buffer.length);       /* create contexts length */
     405             : 
     406      364920 :         outdyn = out_context_buffer;
     407             : 
     408      364920 :         error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
     409      364920 :         if (!NT_STATUS_IS_OK(error)) {
     410           0 :                 smbd_server_connection_terminate(smb2req->xconn,
     411             :                                                  nt_errstr(error));
     412           0 :                 return;
     413             :         }
     414             : }
     415             : 
     416        1134 : static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
     417             : {
     418        1134 :         return ((key->data[0] != 0) || (key->data[1] != 0));
     419             : }
     420             : 
     421         128 : static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
     422             :         const char *requested_filename, const struct files_struct *fsp,
     423             :         const struct smb2_lease *lease_ptr)
     424             : {
     425         128 :         char *filename = NULL;
     426         128 :         struct smb_filename *smb_fname = NULL;
     427             :         uint32_t ucf_flags;
     428             :         NTSTATUS status;
     429             : 
     430         128 :         if (lease_ptr == NULL) {
     431          90 :                 if (fsp->oplock_type != LEASE_OPLOCK) {
     432          78 :                         return NT_STATUS_OK;
     433             :                 }
     434          12 :                 DEBUG(10, ("Reopened file has lease, but no lease "
     435             :                            "requested\n"));
     436          12 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     437             :         }
     438             : 
     439          38 :         if (fsp->oplock_type != LEASE_OPLOCK) {
     440           0 :                 DEBUG(10, ("Lease requested, but reopened file has no "
     441             :                            "lease\n"));
     442           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     443             :         }
     444             : 
     445          38 :         if (!smb2_lease_key_equal(&lease_ptr->lease_key,
     446          38 :                                   &fsp->lease->lease.lease_key)) {
     447           8 :                 DEBUG(10, ("Different lease key requested than found "
     448             :                            "in reopened file\n"));
     449           8 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     450             :         }
     451             : 
     452          30 :         filename = talloc_strdup(talloc_tos(), requested_filename);
     453          30 :         if (filename == NULL) {
     454           0 :                 return NT_STATUS_NO_MEMORY;
     455             :         }
     456             : 
     457             :         /* This also converts '\' to '/' */
     458          30 :         status = check_path_syntax(filename);
     459          30 :         if (!NT_STATUS_IS_OK(status)) {
     460           0 :                 TALLOC_FREE(filename);
     461           0 :                 return status;
     462             :         }
     463             : 
     464          30 :         ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
     465          30 :         status = filename_convert(talloc_tos(), fsp->conn,
     466             :                                   filename, ucf_flags,
     467             :                                   0, &smb_fname);
     468          30 :         TALLOC_FREE(filename);
     469          30 :         if (!NT_STATUS_IS_OK(status)) {
     470           0 :                 DEBUG(10, ("filename_convert returned %s\n",
     471             :                            nt_errstr(status)));
     472           0 :                 return status;
     473             :         }
     474             : 
     475          30 :         if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
     476           8 :                 DEBUG(10, ("Lease requested for file %s, reopened file "
     477             :                            "is named %s\n", smb_fname->base_name,
     478             :                            fsp->fsp_name->base_name));
     479           8 :                 TALLOC_FREE(smb_fname);
     480           8 :                 return NT_STATUS_INVALID_PARAMETER;
     481             :         }
     482             : 
     483          22 :         TALLOC_FREE(smb_fname);
     484             : 
     485          22 :         return NT_STATUS_OK;
     486             : }
     487             : 
     488             : struct smbd_smb2_create_state {
     489             :         struct tevent_context *ev;
     490             :         struct smbd_smb2_request *smb2req;
     491             :         struct GUID req_guid;
     492             :         struct smb_request *smb1req;
     493             :         bool open_was_deferred;
     494             :         struct tevent_immediate *im;
     495             :         struct timeval request_time;
     496             :         struct file_id id;
     497             :         struct deferred_open_record *open_rec;
     498             :         files_struct *result;
     499             :         bool replay_operation;
     500             :         uint8_t in_oplock_level;
     501             :         uint32_t in_create_disposition;
     502             :         int requested_oplock_level;
     503             :         int info;
     504             :         char *fname;
     505             :         struct ea_list *ea_list;
     506             :         NTTIME max_access_time;
     507             :         struct security_descriptor *sec_desc;
     508             :         uint64_t allocation_size;
     509             :         struct GUID _create_guid;
     510             :         struct GUID *create_guid;
     511             :         struct GUID _purge_create_guid;
     512             :         struct GUID *purge_create_guid;
     513             :         bool update_open;
     514             :         bool durable_requested;
     515             :         uint32_t durable_timeout_msec;
     516             :         bool do_durable_reconnect;
     517             :         uint64_t persistent_id;
     518             :         struct smb2_lease lease;
     519             :         struct smb2_lease *lease_ptr;
     520             :         ssize_t lease_len;
     521             :         bool need_replay_cache;
     522             :         struct smbXsrv_open *op;
     523             :         NTTIME twrp_time;
     524             : 
     525             :         struct smb2_create_blob *dhnc;
     526             :         struct smb2_create_blob *dh2c;
     527             :         struct smb2_create_blob *dhnq;
     528             :         struct smb2_create_blob *dh2q;
     529             :         struct smb2_create_blob *rqls;
     530             :         struct smb2_create_blob *exta;
     531             :         struct smb2_create_blob *mxac;
     532             :         struct smb2_create_blob *secd;
     533             :         struct smb2_create_blob *alsi;
     534             :         struct smb2_create_blob *twrp;
     535             :         struct smb2_create_blob *qfid;
     536             :         struct smb2_create_blob *svhdx;
     537             : 
     538             :         uint8_t out_oplock_level;
     539             :         uint32_t out_create_action;
     540             :         struct timespec out_creation_ts;
     541             :         struct timespec out_last_access_ts;
     542             :         struct timespec out_last_write_ts;
     543             :         struct timespec out_change_ts;
     544             :         uint64_t out_allocation_size;
     545             :         uint64_t out_end_of_file;
     546             :         uint32_t out_file_attributes;
     547             :         uint64_t out_file_id_persistent;
     548             :         uint64_t out_file_id_volatile;
     549             :         struct smb2_create_blobs *out_context_blobs;
     550             : };
     551             : 
     552             : static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
     553             :                                                 const char *caller_func);
     554             : 
     555      937280 : static void smbd_smb2_create_cleanup(struct tevent_req *req,
     556             :                                      enum tevent_req_state req_state)
     557             : {
     558      937280 :         smbd_smb2_create_purge_replay_cache(req, __func__);
     559      937280 : }
     560             : 
     561      468863 : static NTSTATUS smbd_smb2_create_fetch_create_ctx(
     562             :         struct tevent_req *req,
     563             :         struct smb2_create_blobs *in_context_blobs)
     564             : {
     565      468863 :         struct smbd_smb2_create_state *state = tevent_req_data(
     566             :                 req, struct smbd_smb2_create_state);
     567             : 
     568             :         /*
     569             :          * For now, remove the posix create context from the wire. We
     570             :          * are using it inside smbd and will properly use it once
     571             :          * smb3.11 unix extensions will be done. So in the future we
     572             :          * will remove it only if unix extensions are not negotiated.
     573             :          */
     574      468863 :         smb2_create_blob_remove(in_context_blobs, SMB2_CREATE_TAG_POSIX);
     575             : 
     576      468863 :         state->dhnq = smb2_create_blob_find(in_context_blobs,
     577             :                                             SMB2_CREATE_TAG_DHNQ);
     578      468863 :         state->dhnc = smb2_create_blob_find(in_context_blobs,
     579             :                                             SMB2_CREATE_TAG_DHNC);
     580      468863 :         state->dh2q = smb2_create_blob_find(in_context_blobs,
     581             :                                             SMB2_CREATE_TAG_DH2Q);
     582      468863 :         state->dh2c = smb2_create_blob_find(in_context_blobs,
     583             :                                             SMB2_CREATE_TAG_DH2C);
     584      468863 :         if (state->smb2req->xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
     585      327909 :                 state->rqls = smb2_create_blob_find(in_context_blobs,
     586             :                                                     SMB2_CREATE_TAG_RQLS);
     587             :         }
     588             : 
     589      866211 :         if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
     590      866303 :             ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
     591      866913 :             ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
     592      469813 :             ((state->dh2q != NULL) && (state->dh2c != NULL)))
     593             :         {
     594             :                 /* not both are allowed at the same time */
     595          16 :                 return NT_STATUS_INVALID_PARAMETER;
     596             :         }
     597             : 
     598      468847 :         if (state->dhnc != NULL) {
     599             :                 uint32_t num_blobs_allowed;
     600             : 
     601         118 :                 if (state->dhnc->data.length != 16) {
     602           0 :                         return NT_STATUS_INVALID_PARAMETER;
     603             :                 }
     604             : 
     605             :                 /*
     606             :                  * According to MS-SMB2: 3.3.5.9.7, "Handling the
     607             :                  * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
     608             :                  * we should ignore an additional dhnq blob, but fail
     609             :                  * the request (with status OBJECT_NAME_NOT_FOUND) if
     610             :                  * any other extra create blob has been provided.
     611             :                  *
     612             :                  * (Note that the cases of an additional dh2q or dh2c blob
     613             :                  *  which require a different error code, have been treated
     614             :                  *  above.)
     615             :                  */
     616             : 
     617         118 :                 if (state->dhnq != NULL) {
     618           4 :                         num_blobs_allowed = 2;
     619             :                 } else {
     620         114 :                         num_blobs_allowed = 1;
     621             :                 }
     622             : 
     623         118 :                 if (state->rqls != NULL) {
     624          24 :                         num_blobs_allowed += 1;
     625             :                 }
     626             : 
     627         118 :                 if (in_context_blobs->num_blobs != num_blobs_allowed) {
     628           6 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     629             :                 }
     630             :         }
     631             : 
     632      468841 :         if (state->dh2c!= NULL) {
     633             :                 uint32_t num_blobs_allowed;
     634             : 
     635         100 :                 if (state->dh2c->data.length != 36) {
     636           0 :                         return NT_STATUS_INVALID_PARAMETER;
     637             :                 }
     638             : 
     639             :                 /*
     640             :                  * According to MS-SMB2: 3.3.5.9.12, "Handling the
     641             :                  * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
     642             :                  * we should fail the request with status
     643             :                  * OBJECT_NAME_NOT_FOUND if any other create blob has been
     644             :                  * provided.
     645             :                  *
     646             :                  * (Note that the cases of an additional dhnq, dhnc or dh2q
     647             :                  *  blob which require a different error code, have been
     648             :                  *  treated above.)
     649             :                  */
     650             : 
     651         100 :                 num_blobs_allowed = 1;
     652             : 
     653         100 :                 if (state->rqls != NULL) {
     654          26 :                         num_blobs_allowed += 1;
     655             :                 }
     656             : 
     657         100 :                 if (in_context_blobs->num_blobs != num_blobs_allowed) {
     658           6 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     659             :                 }
     660             :         }
     661             : 
     662      468835 :         state->exta = smb2_create_blob_find(in_context_blobs,
     663             :                                             SMB2_CREATE_TAG_EXTA);
     664      468835 :         state->mxac = smb2_create_blob_find(in_context_blobs,
     665             :                                             SMB2_CREATE_TAG_MXAC);
     666      468835 :         state->secd = smb2_create_blob_find(in_context_blobs,
     667             :                                             SMB2_CREATE_TAG_SECD);
     668      468835 :         state->alsi = smb2_create_blob_find(in_context_blobs,
     669             :                                             SMB2_CREATE_TAG_ALSI);
     670      468835 :         state->twrp = smb2_create_blob_find(in_context_blobs,
     671             :                                             SMB2_CREATE_TAG_TWRP);
     672      468835 :         state->qfid = smb2_create_blob_find(in_context_blobs,
     673             :                                             SMB2_CREATE_TAG_QFID);
     674      468835 :         if (state->smb2req->xconn->protocol >= PROTOCOL_SMB3_02) {
     675             :                 /*
     676             :                  * This was introduced with SMB3_02
     677             :                  */
     678      460557 :                 state->svhdx = smb2_create_blob_find(
     679             :                         in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
     680             :         }
     681             : 
     682      468835 :         return NT_STATUS_OK;
     683             : }
     684             : 
     685             : static void smbd_smb2_create_before_exec(struct tevent_req *req);
     686             : static void smbd_smb2_create_after_exec(struct tevent_req *req);
     687             : static void smbd_smb2_create_finish(struct tevent_req *req);
     688             : 
     689      468863 : static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
     690             :                         struct tevent_context *ev,
     691             :                         struct smbd_smb2_request *smb2req,
     692             :                         uint8_t in_oplock_level,
     693             :                         uint32_t in_impersonation_level,
     694             :                         uint32_t in_desired_access,
     695             :                         uint32_t in_file_attributes,
     696             :                         uint32_t in_share_access,
     697             :                         uint32_t in_create_disposition,
     698             :                         uint32_t in_create_options,
     699             :                         const char *in_name,
     700             :                         struct smb2_create_blobs in_context_blobs)
     701             : {
     702      468863 :         struct tevent_req *req = NULL;
     703      468863 :         struct smbd_smb2_create_state *state = NULL;
     704             :         NTSTATUS status;
     705      468863 :         struct smb_request *smb1req = NULL;
     706      468863 :         struct smb_filename *smb_fname = NULL;
     707             :         uint32_t ucf_flags;
     708             : 
     709      468863 :         req = tevent_req_create(mem_ctx, &state,
     710             :                                 struct smbd_smb2_create_state);
     711      468863 :         if (req == NULL) {
     712           0 :                 return NULL;
     713             :         }
     714      468863 :         *state = (struct smbd_smb2_create_state) {
     715             :                 .ev = ev,
     716             :                 .smb2req = smb2req,
     717             :                 .in_oplock_level = in_oplock_level,
     718             :                 .in_create_disposition = in_create_disposition,
     719             :         };
     720             : 
     721      468863 :         smb1req = smbd_smb2_fake_smb_request(smb2req);
     722      468863 :         if (tevent_req_nomem(smb1req, req)) {
     723           0 :                 return tevent_req_post(req, state->ev);
     724             :         }
     725      468863 :         state->smb1req = smb1req;
     726             : 
     727      468863 :         state->req_guid = smbd_request_guid(smb1req, 0);
     728             : 
     729      468863 :         tevent_req_set_cleanup_fn(req, smbd_smb2_create_cleanup);
     730             : 
     731      468863 :         if (smb2req->subreq == NULL) {
     732      468481 :                 DBG_DEBUG("name [%s]\n", in_name);
     733             :         } else {
     734         382 :                 struct smbd_smb2_create_state *old_state = tevent_req_data(
     735             :                         smb2req->subreq, struct smbd_smb2_create_state);
     736             : 
     737         382 :                 DBG_DEBUG("reentrant for file %s\n", in_name);
     738             : 
     739         382 :                 state->id = old_state->id;
     740         382 :                 state->request_time = old_state->request_time;
     741         382 :                 state->open_rec = talloc_move(state, &old_state->open_rec);
     742         382 :                 state->open_was_deferred = old_state->open_was_deferred;
     743         382 :                 state->_purge_create_guid = old_state->_purge_create_guid;
     744         382 :                 state->purge_create_guid = old_state->purge_create_guid;
     745         382 :                 old_state->purge_create_guid = NULL;
     746             :         }
     747             : 
     748      468863 :         TALLOC_FREE(smb2req->subreq);
     749      468863 :         smb2req->subreq = req;
     750             : 
     751      468863 :         if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
     752           0 :                 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
     753             :         } else {
     754      468863 :                 state->requested_oplock_level = state->in_oplock_level;
     755             :         }
     756             : 
     757             :         /* these are ignored for SMB2 */
     758      468863 :         in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
     759      468863 :         in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
     760             : 
     761      468863 :         in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
     762             : 
     763      468863 :         state->fname = talloc_strdup(state, in_name);
     764      468863 :         if (tevent_req_nomem(state->fname, req)) {
     765           0 :                 return tevent_req_post(req, state->ev);
     766             :         }
     767             : 
     768      468863 :         state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
     769      468863 :         if (tevent_req_nomem(state->out_context_blobs, req)) {
     770           0 :                 return tevent_req_post(req, state->ev);
     771             :         }
     772             : 
     773      468863 :         status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
     774      468863 :         if (tevent_req_nterror(req, status)) {
     775          28 :                 return tevent_req_post(req, state->ev);
     776             :         }
     777             : 
     778      468835 :         if (IS_IPC(smb1req->conn)) {
     779       15873 :                 const char *pipe_name = in_name;
     780             : 
     781       15873 :                 if (state->dhnc != NULL || state->dh2c != NULL) {
     782             :                         /* durable handles are not supported on IPC$ */
     783           0 :                         tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     784           0 :                         return tevent_req_post(req, state->ev);
     785             :                 }
     786             : 
     787       15873 :                 if (!lp_nt_pipe_support()) {
     788           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     789           0 :                         return tevent_req_post(req, state->ev);
     790             :                 }
     791             : 
     792       15873 :                 status = open_np_file(smb1req, pipe_name, &state->result);
     793       15873 :                 if (!NT_STATUS_IS_OK(status)) {
     794          27 :                         tevent_req_nterror(req, status);
     795          27 :                         return tevent_req_post(req, state->ev);
     796             :                 }
     797       15846 :                 state->info = FILE_WAS_OPENED;
     798             : 
     799       15846 :                 smbd_smb2_create_finish(req);
     800       15846 :                 return req;
     801             :         }
     802             : 
     803      452962 :         if (CAN_PRINT(smb1req->conn)) {
     804          26 :                 if (state->dhnc != NULL || state->dh2c != NULL) {
     805             :                         /* durable handles are not supported on printers */
     806           0 :                         tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     807           0 :                         return tevent_req_post(req, state->ev);
     808             :                 }
     809             : 
     810          26 :                 status = file_new(smb1req, smb1req->conn, &state->result);
     811          26 :                 if(!NT_STATUS_IS_OK(status)) {
     812           0 :                         tevent_req_nterror(req, status);
     813           0 :                         return tevent_req_post(req, state->ev);
     814             :                 }
     815             : 
     816          26 :                 status = print_spool_open(state->result, in_name,
     817             :                                           smb1req->vuid);
     818          26 :                 if (!NT_STATUS_IS_OK(status)) {
     819           0 :                         file_free(smb1req, state->result);
     820           0 :                         tevent_req_nterror(req, status);
     821           0 :                         return tevent_req_post(req, state->ev);
     822             :                 }
     823          26 :                 state->info = FILE_WAS_CREATED;
     824             : 
     825          26 :                 smbd_smb2_create_finish(req);
     826          26 :                 return req;
     827             :         }
     828             : 
     829             :         /* Check for trailing slash specific directory handling. */
     830      452936 :         status = windows_name_trailing_check(state->fname, in_create_options);
     831      452936 :         if (!NT_STATUS_IS_OK(status)) {
     832          12 :                 tevent_req_nterror(req, status);
     833          12 :                 return tevent_req_post(req, state->ev);
     834             :         }
     835             : 
     836      452924 :         smbd_smb2_create_before_exec(req);
     837      452924 :         if (!tevent_req_is_in_progress(req)) {
     838         160 :                 return tevent_req_post(req, state->ev);
     839             :         }
     840             : 
     841      452764 :         DBG_DEBUG("open execution phase\n");
     842             : 
     843             :         /*
     844             :          * For the backend file open procedure, there are
     845             :          * three possible modes: replay operation (in which case
     846             :          * there is nothing else to do), durable_reconnect or
     847             :          * new open.
     848             :          */
     849      452764 :         if (state->replay_operation) {
     850          66 :                 state->result = state->op->compat;
     851          66 :                 state->result->op = state->op;
     852          66 :                 state->update_open = false;
     853          66 :                 state->info = state->op->create_action;
     854             : 
     855          66 :                 smbd_smb2_create_after_exec(req);
     856          66 :                 if (!tevent_req_is_in_progress(req)) {
     857           0 :                         return req;
     858             :                 }
     859             : 
     860          66 :                 smbd_smb2_create_finish(req);
     861          66 :                 return req;
     862             :         }
     863             : 
     864      452698 :         if (state->do_durable_reconnect) {
     865         206 :                 DATA_BLOB new_cookie = data_blob_null;
     866         206 :                 NTTIME now = timeval_to_nttime(&smb2req->request_time);
     867             : 
     868         554 :                 status = smb2srv_open_recreate(smb2req->xconn,
     869         206 :                                                smb1req->conn->session_info,
     870         206 :                                                state->persistent_id,
     871         206 :                                                state->create_guid,
     872             :                                                now,
     873         206 :                                                &state->op);
     874         206 :                 if (!NT_STATUS_IS_OK(status)) {
     875          50 :                         DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
     876             :                                    nt_errstr(status));
     877          50 :                         tevent_req_nterror(req, status);
     878          50 :                         return tevent_req_post(req, state->ev);
     879             :                 }
     880             : 
     881         156 :                 DBG_DEBUG("%s to recreate durable handle\n",
     882             :                           state->op->global->durable ? "succeeded" : "failed");
     883             : 
     884         156 :                 if (!state->op->global->durable) {
     885           0 :                         talloc_free(state->op);
     886           0 :                         tevent_req_nterror(req,
     887             :                                            NT_STATUS_OBJECT_NAME_NOT_FOUND);
     888           0 :                         return tevent_req_post(req, state->ev);
     889             :                 }
     890             : 
     891         156 :                 status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
     892             :                                                    smb1req,
     893             :                                                    state->op, /* smbXsrv_open input */
     894             :                                                    state->op->global->backend_cookie,
     895             :                                                    state->op, /* TALLOC_CTX */
     896             :                                                    &state->result,
     897             :                                                    &new_cookie);
     898         156 :                 if (!NT_STATUS_IS_OK(status)) {
     899             :                         NTSTATUS return_status;
     900             : 
     901          28 :                         return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
     902             : 
     903          28 :                         DBG_NOTICE("durable_reconnect failed: %s => %s\n",
     904             :                                    nt_errstr(status),
     905             :                                    nt_errstr(return_status));
     906             : 
     907          28 :                         tevent_req_nterror(req, return_status);
     908          28 :                         return tevent_req_post(req, state->ev);
     909             :                 }
     910             : 
     911         128 :                 DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
     912             :                           (unsigned)state->result->oplock_type, state->lease_ptr);
     913             : 
     914         128 :                 status = smbd_smb2_create_durable_lease_check(
     915         128 :                         smb1req, state->fname, state->result, state->lease_ptr);
     916         128 :                 if (!NT_STATUS_IS_OK(status)) {
     917          28 :                         close_file(smb1req, state->result, SHUTDOWN_CLOSE);
     918          28 :                         tevent_req_nterror(req, status);
     919          28 :                         return tevent_req_post(req, state->ev);
     920             :                 }
     921             : 
     922         100 :                 data_blob_free(&state->op->global->backend_cookie);
     923         100 :                 state->op->global->backend_cookie = new_cookie;
     924             : 
     925         100 :                 state->op->status = NT_STATUS_OK;
     926         100 :                 state->op->global->disconnect_time = 0;
     927             : 
     928             :                 /* save the timout for later update */
     929         100 :                 state->durable_timeout_msec = state->op->global->durable_timeout_msec;
     930             : 
     931         100 :                 state->update_open = true;
     932             : 
     933         100 :                 state->info = FILE_WAS_OPENED;
     934             : 
     935         100 :                 smbd_smb2_create_after_exec(req);
     936         100 :                 if (!tevent_req_is_in_progress(req)) {
     937           0 :                         return req;
     938             :                 }
     939             : 
     940         100 :                 smbd_smb2_create_finish(req);
     941         100 :                 return req;
     942             :         }
     943             : 
     944      452492 :         if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
     945        1080 :                 if (state->lease_ptr == NULL) {
     946          14 :                         state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
     947             :                 }
     948             :         } else {
     949      451412 :                 state->lease_ptr = NULL;
     950             :         }
     951             : 
     952             :         /*
     953             :          * For a DFS path the function parse_dfs_path()
     954             :          * will do the path processing.
     955             :          */
     956             : 
     957      452492 :         if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
     958             :                 /* convert '\\' into '/' */
     959      443838 :                 status = check_path_syntax(state->fname);
     960      443838 :                 if (!NT_STATUS_IS_OK(status)) {
     961          60 :                         tevent_req_nterror(req, status);
     962          60 :                         return tevent_req_post(req, state->ev);
     963             :                 }
     964             :         }
     965             : 
     966      452432 :         ucf_flags = filename_create_ucf_flags(
     967      452432 :                 smb1req, state->in_create_disposition);
     968      835813 :         status = filename_convert(req,
     969             :                                   smb1req->conn,
     970      452432 :                                   state->fname,
     971             :                                   ucf_flags,
     972      452432 :                                   state->twrp_time,
     973             :                                   &smb_fname);
     974      452432 :         if (!NT_STATUS_IS_OK(status)) {
     975        1855 :                 tevent_req_nterror(req, status);
     976        1855 :                 return tevent_req_post(req, state->ev);
     977             :         }
     978             : 
     979             :         /*
     980             :          * MS-SMB2: 2.2.13 SMB2 CREATE Request
     981             :          * ImpersonationLevel ... MUST contain one of the
     982             :          * following values. The server MUST validate this
     983             :          * field, but otherwise ignore it.
     984             :          *
     985             :          * NB. The source4/torture/smb2/durable_open.c test
     986             :          * shows this check is only done on real opens, not
     987             :          * on durable handle-reopens.
     988             :          */
     989             : 
     990      450577 :         if (in_impersonation_level >
     991             :             SMB2_IMPERSONATION_DELEGATE) {
     992           5 :                 tevent_req_nterror(req,
     993             :                                    NT_STATUS_BAD_IMPERSONATION_LEVEL);
     994           5 :                 return tevent_req_post(req, state->ev);
     995             :         }
     996             : 
     997             :         /*
     998             :          * We know we're going to do a local open, so now
     999             :          * we must be protocol strict. JRA.
    1000             :          *
    1001             :          * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
    1002             :          * If the file name length is greater than zero and the
    1003             :          * first character is a path separator character, the
    1004             :          * server MUST fail the request with
    1005             :          * STATUS_INVALID_PARAMETER.
    1006             :          */
    1007      450572 :         if (in_name[0] == '\\' || in_name[0] == '/') {
    1008           5 :                 tevent_req_nterror(req,
    1009             :                                    NT_STATUS_INVALID_PARAMETER);
    1010           5 :                 return tevent_req_post(req, state->ev);
    1011             :         }
    1012             : 
    1013      450567 :         status = SMB_VFS_CREATE_FILE(smb1req->conn,
    1014             :                                      smb1req,
    1015             :                                      smb_fname,
    1016             :                                      in_desired_access,
    1017             :                                      in_share_access,
    1018             :                                      state->in_create_disposition,
    1019             :                                      in_create_options,
    1020             :                                      in_file_attributes,
    1021             :                                      map_smb2_oplock_levels_to_samba(
    1022             :                                              state->requested_oplock_level),
    1023             :                                      state->lease_ptr,
    1024             :                                      state->allocation_size,
    1025             :                                      0, /* private_flags */
    1026             :                                      state->sec_desc,
    1027             :                                      state->ea_list,
    1028             :                                      &state->result,
    1029             :                                      &state->info,
    1030             :                                      &in_context_blobs,
    1031             :                                      state->out_context_blobs);
    1032      450567 :         if (!NT_STATUS_IS_OK(status)) {
    1033      101685 :                 if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
    1034         450 :                         SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
    1035         450 :                         return req;
    1036             :                 }
    1037      101235 :                 tevent_req_nterror(req, status);
    1038      101235 :                 return tevent_req_post(req, state->ev);
    1039             :         }
    1040      348882 :         state->op = state->result->op;
    1041             : 
    1042      348882 :         smbd_smb2_create_after_exec(req);
    1043      348882 :         if (!tevent_req_is_in_progress(req)) {
    1044           0 :                 return req;
    1045             :         }
    1046             : 
    1047      348882 :         smbd_smb2_create_finish(req);
    1048      348882 :         return req;
    1049             : }
    1050             : 
    1051      937280 : static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
    1052             :                                                 const char *caller_func)
    1053             : {
    1054      937280 :         struct smbd_smb2_create_state *state = tevent_req_data(
    1055             :                 req, struct smbd_smb2_create_state);
    1056             :         NTSTATUS status;
    1057             : 
    1058      937280 :         if (state->purge_create_guid == NULL) {
    1059      937202 :                 return;
    1060             :         }
    1061             : 
    1062          78 :         status = smbXsrv_open_purge_replay_cache(state->smb2req->xconn->client,
    1063          78 :                                                  state->purge_create_guid);
    1064          78 :         if (!NT_STATUS_IS_OK(status)) {
    1065             :                 struct GUID_txt_buf buf;
    1066             : 
    1067           0 :                 D_ERR("%s: smbXsrv_open_purge_replay_cache(%s) %s\n",
    1068             :                       caller_func,
    1069             :                       GUID_buf_string(state->purge_create_guid, &buf),
    1070             :                       nt_errstr(status));
    1071             :         }
    1072             : 
    1073          78 :         state->purge_create_guid = NULL;
    1074             : }
    1075             : 
    1076      452924 : static void smbd_smb2_create_before_exec(struct tevent_req *req)
    1077             : {
    1078      452924 :         struct smbd_smb2_create_state *state = tevent_req_data(
    1079             :                 req, struct smbd_smb2_create_state);
    1080      452924 :         struct smbd_smb2_request *smb2req = state->smb2req;
    1081             :         NTSTATUS status;
    1082             : 
    1083      452924 :         if (state->exta != NULL) {
    1084         221 :                 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
    1085           0 :                         tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    1086           0 :                         return;
    1087             :                 }
    1088             : 
    1089         442 :                 state->ea_list = read_nttrans_ea_list(
    1090             :                         state,
    1091         221 :                         (const char *)state->exta->data.data,
    1092         221 :                         state->exta->data.length);
    1093         221 :                 if (state->ea_list == NULL) {
    1094           0 :                         DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
    1095           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1096           0 :                         return;
    1097             :                 }
    1098             : 
    1099             :                 /*
    1100             :                  * NB. When SMB2+ unix extensions are added,
    1101             :                  * we need to relax this check in invalid
    1102             :                  * names - we used to not do this if
    1103             :                  * lp_posix_pathnames() was false.
    1104             :                  */
    1105         221 :                 if (ea_list_has_invalid_name(state->ea_list)) {
    1106           0 :                         tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
    1107           0 :                         return;
    1108             :                 }
    1109             :         }
    1110             : 
    1111      452924 :         if (state->mxac != NULL) {
    1112          32 :                 if (state->mxac->data.length == 0) {
    1113          32 :                         state->max_access_time = 0;
    1114           0 :                 } else if (state->mxac->data.length == 8) {
    1115           0 :                         state->max_access_time = BVAL(state->mxac->data.data, 0);
    1116             :                 } else {
    1117           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1118           0 :                         return;
    1119             :                 }
    1120             :         }
    1121             : 
    1122      452924 :         if (state->secd != NULL) {
    1123             :                 enum ndr_err_code ndr_err;
    1124             : 
    1125          89 :                 state->sec_desc = talloc_zero(state, struct security_descriptor);
    1126          89 :                 if (tevent_req_nomem(state->sec_desc, req)) {
    1127           0 :                         return;
    1128             :                 }
    1129             : 
    1130          89 :                 ndr_err = ndr_pull_struct_blob(&state->secd->data,
    1131          89 :                                                state->sec_desc, state->sec_desc,
    1132             :                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    1133          89 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1134           0 :                         DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
    1135             :                                  ndr_errstr(ndr_err)));
    1136           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1137           0 :                         return;
    1138             :                 }
    1139             :         }
    1140             : 
    1141      452924 :         if (state->dhnq != NULL) {
    1142         313 :                 if (state->dhnq->data.length != 16) {
    1143           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1144           0 :                         return;
    1145             :                 }
    1146             : 
    1147         313 :                 if (state->dh2q != NULL) {
    1148           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1149           0 :                         return;
    1150             :                 }
    1151             : 
    1152             :                 /*
    1153             :                  * durable handle request is processed below.
    1154             :                  */
    1155         313 :                 state->durable_requested = true;
    1156             :                 /*
    1157             :                  * Set the timeout to 16 mins.
    1158             :                  *
    1159             :                  * TODO: test this against Windows 2012
    1160             :                  *       as the default for durable v2 is 1 min.
    1161             :                  */
    1162         313 :                 state->durable_timeout_msec = (16*60*1000);
    1163             :         }
    1164             : 
    1165      452924 :         if (state->dh2q != NULL) {
    1166        1130 :                 const uint8_t *p = state->dh2q->data.data;
    1167        1130 :                 NTTIME now = timeval_to_nttime(&smb2req->request_time);
    1168        1130 :                 uint32_t durable_v2_timeout = 0;
    1169             :                 DATA_BLOB create_guid_blob;
    1170             :                 const uint8_t *hdr;
    1171             :                 uint32_t flags;
    1172             : 
    1173        1130 :                 if (state->dh2q->data.length != 32) {
    1174           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1175           0 :                         return;
    1176             :                 }
    1177             : 
    1178        1130 :                 if (state->dhnq != NULL) {
    1179           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1180           0 :                         return;
    1181             :                 }
    1182             : 
    1183        1130 :                 durable_v2_timeout = IVAL(p, 0);
    1184        1130 :                 create_guid_blob = data_blob_const(p + 16, 16);
    1185             : 
    1186        1130 :                 status = GUID_from_ndr_blob(&create_guid_blob,
    1187             :                                             &state->_create_guid);
    1188        1130 :                 if (tevent_req_nterror(req, status)) {
    1189           0 :                         return;
    1190             :                 }
    1191        1130 :                 state->create_guid = &state->_create_guid;
    1192             : 
    1193             :                 /*
    1194             :                  * we need to store the create_guid later
    1195             :                  */
    1196        1130 :                 state->update_open = true;
    1197             : 
    1198             :                 /*
    1199             :                  * And we need to create a cache for replaying the
    1200             :                  * create.
    1201             :                  */
    1202        1130 :                 state->need_replay_cache = true;
    1203             : 
    1204             :                 /*
    1205             :                  * durable handle v2 request processed below
    1206             :                  */
    1207        1130 :                 state->durable_requested = true;
    1208        1130 :                 state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
    1209        1130 :                 if (state->durable_timeout_msec == 0) {
    1210             :                         /*
    1211             :                          * Set the timeout to 1 min as default.
    1212             :                          *
    1213             :                          * This matches Windows 2012.
    1214             :                          */
    1215         422 :                         state->durable_timeout_msec = (60*1000);
    1216             :                 }
    1217             : 
    1218             :                 /*
    1219             :                  * Check for replay operation.
    1220             :                  * Only consider it when we have dh2q.
    1221             :                  * If we do not have a replay operation, verify that
    1222             :                  * the create_guid is not cached for replay.
    1223             :                  */
    1224        1130 :                 hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
    1225        1130 :                 flags = IVAL(hdr, SMB2_HDR_FLAGS);
    1226        1130 :                 state->replay_operation =
    1227        1130 :                         flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
    1228             : 
    1229        2089 :                 status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
    1230             :                                                           state->req_guid,
    1231        1130 :                                                           *state->create_guid,
    1232        1130 :                                                           state->fname,
    1233             :                                                           now,
    1234             :                                                           &state->op);
    1235        1130 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
    1236             :                         /*
    1237             :                          * We've reserved the replay_cache record
    1238             :                          * for ourself, indicating we're still
    1239             :                          * in progress.
    1240             :                          *
    1241             :                          * It means the smbd_smb2_create_cleanup()
    1242             :                          * may need to call smbXsrv_open_purge_replay_cache()
    1243             :                          * in order to cleanup.
    1244             :                          */
    1245         904 :                         SMB_ASSERT(state->op == NULL);
    1246         904 :                         state->_purge_create_guid = state->_create_guid;
    1247         904 :                         state->purge_create_guid = &state->_purge_create_guid;
    1248         904 :                         status = NT_STATUS_OK;
    1249         904 :                         state->replay_operation = false;
    1250         226 :                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
    1251         152 :                         tevent_req_nterror(req, status);
    1252         153 :                         return;
    1253          74 :                 } else if (!NT_STATUS_IS_OK(status)) {
    1254           0 :                         DBG_WARNING("smb2srv_open_lookup_replay_cache "
    1255             :                                     "failed: %s\n", nt_errstr(status));
    1256           0 :                         tevent_req_nterror(req, status);
    1257           0 :                         return;
    1258          74 :                 } else if (!state->replay_operation) {
    1259             :                         /*
    1260             :                          * If a create without replay operation flag
    1261             :                          * is sent but with a create_guid that is
    1262             :                          * currently in the replay cache -- fail.
    1263             :                          */
    1264           4 :                         status = NT_STATUS_DUPLICATE_OBJECTID;
    1265           4 :                         (void)tevent_req_nterror(req, status);
    1266           4 :                         return;
    1267             :                 }
    1268             :         }
    1269             : 
    1270      452768 :         if (state->dhnc != NULL) {
    1271         112 :                 state->persistent_id = BVAL(state->dhnc->data.data, 0);
    1272         112 :                 state->do_durable_reconnect = true;
    1273             :         }
    1274             : 
    1275      452768 :         if (state->dh2c != NULL) {
    1276          94 :                 const uint8_t *p = state->dh2c->data.data;
    1277             :                 DATA_BLOB create_guid_blob;
    1278             : 
    1279          94 :                 state->persistent_id = BVAL(p, 0);
    1280          94 :                 create_guid_blob = data_blob_const(p + 16, 16);
    1281             : 
    1282          94 :                 status = GUID_from_ndr_blob(&create_guid_blob,
    1283             :                                             &state->_create_guid);
    1284          94 :                 if (tevent_req_nterror(req, status)) {
    1285           0 :                         return;
    1286             :                 }
    1287             : 
    1288          94 :                 state->create_guid = &state->_create_guid;
    1289          94 :                 state->do_durable_reconnect = true;
    1290             :         }
    1291             : 
    1292      452768 :         if (state->alsi != NULL) {
    1293         139 :                 if (state->alsi->data.length != 8) {
    1294           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1295           0 :                         return;
    1296             :                 }
    1297         139 :                 state->allocation_size = BVAL(state->alsi->data.data, 0);
    1298             :         }
    1299             : 
    1300      452768 :         if (state->twrp != NULL) {
    1301        2331 :                 if (state->twrp->data.length != 8) {
    1302           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1303           0 :                         return;
    1304             :                 }
    1305             : 
    1306        2331 :                 state->twrp_time = BVAL(state->twrp->data.data, 0);
    1307             :         }
    1308             : 
    1309      452768 :         if (state->qfid != NULL) {
    1310          36 :                 if (state->qfid->data.length != 0) {
    1311           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1312           0 :                         return;
    1313             :                 }
    1314             :         }
    1315             : 
    1316      452768 :         if (state->rqls != NULL) {
    1317        1134 :                 ssize_t lease_len = -1;
    1318             : 
    1319        2268 :                 lease_len = smb2_lease_pull(state->rqls->data.data,
    1320        1134 :                                             state->rqls->data.length,
    1321             :                                             &state->lease);
    1322        1134 :                 if (lease_len == -1) {
    1323           0 :                         tevent_req_nterror(
    1324             :                                 req, NT_STATUS_INVALID_PARAMETER);
    1325           0 :                         return;
    1326             :                 }
    1327        1134 :                 state->lease_ptr = &state->lease;
    1328             : 
    1329        1134 :                 if (DEBUGLEVEL >= 10) {
    1330           0 :                         DEBUG(10, ("Got lease request size %d\n",
    1331             :                                    (int)lease_len));
    1332           0 :                         NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
    1333             :                 }
    1334             : 
    1335        1134 :                 if (!smb2_lease_key_valid(&state->lease.lease_key)) {
    1336           0 :                         state->lease_ptr = NULL;
    1337           0 :                         state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
    1338             :                 }
    1339             : 
    1340        1134 :                 if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
    1341           0 :                     (state->lease.lease_version != 1))
    1342             :                 {
    1343           0 :                         DEBUG(10, ("v2 lease key only for SMB3\n"));
    1344           0 :                         state->lease_ptr = NULL;
    1345             :                 }
    1346             : 
    1347             :                 /*
    1348             :                  * Replay with a lease is only allowed if the
    1349             :                  * established open carries a lease with the
    1350             :                  * same lease key.
    1351             :                  */
    1352        1134 :                 if (state->replay_operation) {
    1353          18 :                         struct smb2_lease *op_ls =
    1354          18 :                                 &state->op->compat->lease->lease;
    1355          18 :                         int op_oplock = state->op->compat->oplock_type;
    1356             : 
    1357          18 :                         if (map_samba_oplock_levels_to_smb2(op_oplock)
    1358             :                             != SMB2_OPLOCK_LEVEL_LEASE)
    1359             :                         {
    1360           2 :                                 status = NT_STATUS_ACCESS_DENIED;
    1361           2 :                                 (void)tevent_req_nterror(req, status);
    1362           2 :                                 return;
    1363             :                         }
    1364          16 :                         if (!smb2_lease_key_equal(&state->lease.lease_key,
    1365          16 :                                                   &op_ls->lease_key))
    1366             :                         {
    1367           2 :                                 status = NT_STATUS_ACCESS_DENIED;
    1368           2 :                                 (void)tevent_req_nterror(req, status);
    1369           2 :                                 return;
    1370             :                         }
    1371             :                 }
    1372             :         }
    1373             : }
    1374             : 
    1375      349048 : static void smbd_smb2_create_after_exec(struct tevent_req *req)
    1376             : {
    1377      349048 :         struct smbd_smb2_create_state *state = tevent_req_data(
    1378             :                 req, struct smbd_smb2_create_state);
    1379             :         NTSTATUS status;
    1380             : 
    1381             :         /*
    1382             :          * here we have op == result->op
    1383             :          */
    1384             : 
    1385      349048 :         DEBUG(10, ("smbd_smb2_create_send: "
    1386             :                    "response construction phase\n"));
    1387             : 
    1388      349048 :         state->out_file_attributes = fdos_mode(state->result);
    1389             : 
    1390      349048 :         if (state->mxac != NULL) {
    1391             :                 NTTIME last_write_time;
    1392             : 
    1393          32 :                 last_write_time = full_timespec_to_nt_time(
    1394          32 :                         &state->result->fsp_name->st.st_ex_mtime);
    1395          32 :                 if (last_write_time != state->max_access_time) {
    1396             :                         uint8_t p[8];
    1397             :                         uint32_t max_access_granted;
    1398          32 :                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
    1399             : 
    1400          32 :                         status = smbd_calculate_access_mask_fsp(
    1401          32 :                                         state->result->conn->cwd_fsp,
    1402          32 :                                         state->result,
    1403             :                                         false,
    1404             :                                         SEC_FLAG_MAXIMUM_ALLOWED,
    1405             :                                         &max_access_granted);
    1406             : 
    1407          32 :                         SIVAL(p, 0, NT_STATUS_V(status));
    1408          32 :                         SIVAL(p, 4, max_access_granted);
    1409             : 
    1410          58 :                         status = smb2_create_blob_add(
    1411          32 :                                 state->out_context_blobs,
    1412             :                                 state->out_context_blobs,
    1413             :                                 SMB2_CREATE_TAG_MXAC,
    1414             :                                 blob);
    1415          32 :                         if (!NT_STATUS_IS_OK(status)) {
    1416           0 :                                 tevent_req_nterror(req, status);
    1417           0 :                                 tevent_req_post(req, state->ev);
    1418           0 :                                 return;
    1419             :                         }
    1420             :                 }
    1421             :         }
    1422             : 
    1423      349927 :         if (!state->replay_operation && state->durable_requested &&
    1424        1049 :             (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
    1425             :         {
    1426         546 :                 status = SMB_VFS_DURABLE_COOKIE(
    1427             :                         state->result,
    1428             :                         state->op,
    1429             :                         &state->op->global->backend_cookie);
    1430         546 :                 if (!NT_STATUS_IS_OK(status)) {
    1431           0 :                         state->op->global->backend_cookie = data_blob_null;
    1432             :                 }
    1433             :         }
    1434      349048 :         if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
    1435             :         {
    1436         642 :                 state->update_open = true;
    1437             : 
    1438         642 :                 state->op->global->durable = true;
    1439         642 :                 state->op->global->durable_timeout_msec = state->durable_timeout_msec;
    1440             :         }
    1441             : 
    1442      349048 :         if (state->update_open) {
    1443         984 :                 state->op->global->create_guid = state->_create_guid;
    1444         984 :                 if (state->need_replay_cache) {
    1445         736 :                         state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
    1446             :                 }
    1447             : 
    1448         984 :                 status = smbXsrv_open_update(state->op);
    1449         984 :                 DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
    1450             :                            "returned %s\n",
    1451             :                            nt_errstr(status)));
    1452         984 :                 if (!NT_STATUS_IS_OK(status)) {
    1453           0 :                         tevent_req_nterror(req, status);
    1454           0 :                         tevent_req_post(req, state->ev);
    1455           0 :                         return;
    1456             :                 }
    1457             : 
    1458             :                 /*
    1459             :                  * We should not purge the replay cache anymore
    1460             :                  * as it's attached to the smbXsrv_open record now.
    1461             :                  */
    1462         984 :                 state->purge_create_guid = NULL;
    1463             :         }
    1464             : 
    1465      349048 :         if (state->dhnq != NULL && state->op->global->durable) {
    1466         152 :                 uint8_t p[8] = { 0, };
    1467         152 :                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
    1468             : 
    1469         152 :                 status = smb2_create_blob_add(state->out_context_blobs,
    1470             :                                               state->out_context_blobs,
    1471             :                                               SMB2_CREATE_TAG_DHNQ,
    1472             :                                               blob);
    1473         152 :                 if (!NT_STATUS_IS_OK(status)) {
    1474           0 :                         tevent_req_nterror(req, status);
    1475           0 :                         tevent_req_post(req, state->ev);
    1476           0 :                         return;
    1477             :                 }
    1478             :         }
    1479             : 
    1480      349425 :         if (state->dh2q != NULL && state->op->global->durable &&
    1481             :             /*
    1482             :              * For replay operations, we return the dh2q blob
    1483             :              * in the case of oplocks not based on the state of
    1484             :              * the open, but on whether it could have been granted
    1485             :              * for the request data. In the case of leases instead,
    1486             :              * the state of the open is used...
    1487             :              */
    1488         479 :             (!state->replay_operation ||
    1489          63 :              state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
    1490          18 :              state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
    1491             :         {
    1492         436 :                 uint8_t p[8] = { 0, };
    1493         436 :                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
    1494         436 :                 uint32_t durable_v2_response_flags = 0;
    1495             : 
    1496         436 :                 SIVAL(p, 0, state->op->global->durable_timeout_msec);
    1497         436 :                 SIVAL(p, 4, durable_v2_response_flags);
    1498             : 
    1499         436 :                 status = smb2_create_blob_add(state->out_context_blobs,
    1500             :                                               state->out_context_blobs,
    1501             :                                               SMB2_CREATE_TAG_DH2Q,
    1502             :                                               blob);
    1503         436 :                 if (!NT_STATUS_IS_OK(status)) {
    1504           0 :                         tevent_req_nterror(req, status);
    1505           0 :                         tevent_req_post(req, state->ev);
    1506           0 :                         return;
    1507             :                 }
    1508             :         }
    1509             : 
    1510      349048 :         if (state->qfid != NULL) {
    1511             :                 uint8_t p[32];
    1512          36 :                 uint64_t file_id = SMB_VFS_FS_FILE_ID(
    1513             :                         state->result->conn,
    1514             :                         &state->result->fsp_name->st);
    1515          36 :                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
    1516             : 
    1517          36 :                 ZERO_STRUCT(p);
    1518             : 
    1519             :                 /* From conversations with Microsoft engineers at
    1520             :                    the MS plugfest. The first 8 bytes are the "volume index"
    1521             :                    == inode, the second 8 bytes are the "volume id",
    1522             :                    == dev. This will be updated in the SMB2 doc. */
    1523          36 :                 SBVAL(p, 0, file_id);
    1524          36 :                 SIVAL(p, 8, state->result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
    1525             : 
    1526          36 :                 status = smb2_create_blob_add(state->out_context_blobs,
    1527             :                                               state->out_context_blobs,
    1528             :                                               SMB2_CREATE_TAG_QFID,
    1529             :                                               blob);
    1530          36 :                 if (!NT_STATUS_IS_OK(status)) {
    1531           0 :                         tevent_req_nterror(req, status);
    1532           0 :                         tevent_req_post(req, state->ev);
    1533           0 :                         return;
    1534             :                 }
    1535             :         }
    1536             : 
    1537      349048 :         if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
    1538             :                 uint8_t buf[52];
    1539             :                 struct smb2_lease lease;
    1540             :                 size_t lease_len;
    1541             : 
    1542         992 :                 lease = state->result->lease->lease;
    1543             : 
    1544         992 :                 lease_len = sizeof(buf);
    1545         992 :                 if (lease.lease_version == 1) {
    1546         868 :                         lease_len = 32;
    1547             :                 }
    1548             : 
    1549         992 :                 if (!smb2_lease_push(&lease, buf, lease_len)) {
    1550           0 :                         tevent_req_nterror(
    1551             :                                 req, NT_STATUS_INTERNAL_ERROR);
    1552           0 :                         tevent_req_post(req, state->ev);
    1553           0 :                         return;
    1554             :                 }
    1555             : 
    1556         992 :                 status = smb2_create_blob_add(
    1557             :                         state, state->out_context_blobs,
    1558             :                         SMB2_CREATE_TAG_RQLS,
    1559             :                         data_blob_const(buf, lease_len));
    1560         992 :                 if (!NT_STATUS_IS_OK(status)) {
    1561           0 :                         tevent_req_nterror(req, status);
    1562           0 :                         tevent_req_post(req, state->ev);
    1563           0 :                         return;
    1564             :                 }
    1565             :         }
    1566             : 
    1567      349048 :         return;
    1568             : }
    1569             : 
    1570      364920 : static void smbd_smb2_create_finish(struct tevent_req *req)
    1571             : {
    1572      364920 :         struct smbd_smb2_create_state *state = tevent_req_data(
    1573             :                 req, struct smbd_smb2_create_state);
    1574      364920 :         struct smbd_smb2_request *smb2req = state->smb2req;
    1575      364920 :         struct smb_request *smb1req = state->smb1req;
    1576      364920 :         files_struct *result = state->result;
    1577             : 
    1578      364920 :         smb2req->compat_chain_fsp = smb1req->chain_fsp;
    1579             : 
    1580      364920 :         if (state->replay_operation) {
    1581          66 :                 state->out_oplock_level = state->in_oplock_level;
    1582      364854 :         } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
    1583           0 :                 state->out_oplock_level      = state->in_oplock_level;
    1584             :         } else {
    1585      365480 :                 state->out_oplock_level      = map_samba_oplock_levels_to_smb2(result->oplock_type);
    1586             :         }
    1587             : 
    1588      364920 :         if ((state->in_create_disposition == FILE_SUPERSEDE)
    1589         126 :             && (state->info == FILE_WAS_OVERWRITTEN)) {
    1590          21 :                 state->out_create_action = FILE_WAS_SUPERSEDED;
    1591             :         } else {
    1592      364899 :                 state->out_create_action = state->info;
    1593             :         }
    1594      364920 :         result->op->create_action = state->out_create_action;
    1595             : 
    1596      364920 :         state->out_creation_ts = get_create_timespec(smb1req->conn,
    1597      364920 :                                         result, result->fsp_name);
    1598      364920 :         state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
    1599      364920 :         state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
    1600      364920 :         state->out_change_ts = get_change_timespec(smb1req->conn,
    1601      364294 :                                         result, result->fsp_name);
    1602             : 
    1603      364920 :         if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
    1604           0 :                 dos_filetime_timespec(&state->out_creation_ts);
    1605           0 :                 dos_filetime_timespec(&state->out_last_access_ts);
    1606           0 :                 dos_filetime_timespec(&state->out_last_write_ts);
    1607           0 :                 dos_filetime_timespec(&state->out_change_ts);
    1608             :         }
    1609             : 
    1610      364920 :         state->out_allocation_size =
    1611      364920 :                         SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
    1612             :                                                &(result->fsp_name->st));
    1613      364920 :         state->out_end_of_file = result->fsp_name->st.st_ex_size;
    1614      364920 :         if (state->out_file_attributes == 0) {
    1615       15872 :                 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
    1616             :         }
    1617      364920 :         state->out_file_id_persistent = result->op->global->open_persistent_id;
    1618      364920 :         state->out_file_id_volatile = result->op->global->open_volatile_id;
    1619             : 
    1620      364920 :         DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
    1621             : 
    1622      364920 :         tevent_req_done(req);
    1623      364920 :         tevent_req_post(req, state->ev);
    1624      364920 : }
    1625             : 
    1626      468417 : static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
    1627             :                         TALLOC_CTX *mem_ctx,
    1628             :                         uint8_t *out_oplock_level,
    1629             :                         uint32_t *out_create_action,
    1630             :                         struct timespec *out_creation_ts,
    1631             :                         struct timespec *out_last_access_ts,
    1632             :                         struct timespec *out_last_write_ts,
    1633             :                         struct timespec *out_change_ts,
    1634             :                         uint64_t *out_allocation_size,
    1635             :                         uint64_t *out_end_of_file,
    1636             :                         uint32_t *out_file_attributes,
    1637             :                         uint64_t *out_file_id_persistent,
    1638             :                         uint64_t *out_file_id_volatile,
    1639             :                         struct smb2_create_blobs *out_context_blobs)
    1640             : {
    1641             :         NTSTATUS status;
    1642      468417 :         struct smbd_smb2_create_state *state = tevent_req_data(req,
    1643             :                                                struct smbd_smb2_create_state);
    1644             : 
    1645      468417 :         if (tevent_req_is_nterror(req, &status)) {
    1646      103497 :                 tevent_req_received(req);
    1647      103497 :                 return status;
    1648             :         }
    1649             : 
    1650      364920 :         *out_oplock_level       = state->out_oplock_level;
    1651      364920 :         *out_create_action      = state->out_create_action;
    1652      364920 :         *out_creation_ts        = state->out_creation_ts;
    1653      364920 :         *out_last_access_ts     = state->out_last_access_ts;
    1654      364920 :         *out_last_write_ts      = state->out_last_write_ts;
    1655      364920 :         *out_change_ts          = state->out_change_ts;
    1656      364920 :         *out_allocation_size    = state->out_allocation_size;
    1657      364920 :         *out_end_of_file        = state->out_end_of_file;
    1658      364920 :         *out_file_attributes    = state->out_file_attributes;
    1659      364920 :         *out_file_id_persistent = state->out_file_id_persistent;
    1660      364920 :         *out_file_id_volatile   = state->out_file_id_volatile;
    1661      364920 :         *out_context_blobs      = *(state->out_context_blobs);
    1662             : 
    1663      364920 :         talloc_steal(mem_ctx, state->out_context_blobs->blobs);
    1664             : 
    1665      364920 :         tevent_req_received(req);
    1666      364920 :         return NT_STATUS_OK;
    1667             : }
    1668             : 
    1669             : /*********************************************************
    1670             :  Code for dealing with deferred opens.
    1671             : *********************************************************/
    1672             : 
    1673      875648 : bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
    1674             :                         struct timeval *p_request_time,
    1675             :                         struct deferred_open_record **open_rec)
    1676             : {
    1677      875648 :         struct smbd_smb2_create_state *state = NULL;
    1678      875648 :         struct tevent_req *req = NULL;
    1679             : 
    1680      875648 :         if (!smb2req) {
    1681           0 :                 return false;
    1682             :         }
    1683      875648 :         req = smb2req->subreq;
    1684      875648 :         if (!req) {
    1685           0 :                 return false;
    1686             :         }
    1687      875648 :         state = tevent_req_data(req, struct smbd_smb2_create_state);
    1688      875648 :         if (!state) {
    1689           0 :                 return false;
    1690             :         }
    1691      875648 :         if (!state->open_was_deferred) {
    1692      874884 :                 return false;
    1693             :         }
    1694         764 :         if (p_request_time) {
    1695         382 :                 *p_request_time = state->request_time;
    1696             :         }
    1697         764 :         if (open_rec != NULL) {
    1698         382 :                 *open_rec = state->open_rec;
    1699             :         }
    1700         764 :         return true;
    1701             : }
    1702             : 
    1703             : /*********************************************************
    1704             :  Re-process this call early - requested by message or
    1705             :  close.
    1706             : *********************************************************/
    1707             : 
    1708      102465 : static struct smbd_smb2_request *find_open_smb2req(
    1709             :         struct smbXsrv_connection *xconn, uint64_t mid)
    1710             : {
    1711             :         struct smbd_smb2_request *smb2req;
    1712             : 
    1713      102563 :         for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
    1714             :                 uint64_t message_id;
    1715      102563 :                 if (smb2req->subreq == NULL) {
    1716             :                         /* This message has been processed. */
    1717           0 :                         continue;
    1718             :                 }
    1719      102563 :                 if (!tevent_req_is_in_progress(smb2req->subreq)) {
    1720             :                         /* This message has been processed. */
    1721           0 :                         continue;
    1722             :                 }
    1723      102563 :                 message_id = get_mid_from_smb2req(smb2req);
    1724      102563 :                 if (message_id == mid) {
    1725      102465 :                         return smb2req;
    1726             :                 }
    1727             :         }
    1728           0 :         return NULL;
    1729             : }
    1730             : 
    1731      101685 : bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
    1732             : {
    1733      101685 :         struct smbd_smb2_create_state *state = NULL;
    1734             :         struct smbd_smb2_request *smb2req;
    1735             : 
    1736      101685 :         smb2req = find_open_smb2req(xconn, mid);
    1737             : 
    1738      101685 :         if (!smb2req) {
    1739           0 :                 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
    1740             :                         (unsigned long long)mid));
    1741           0 :                 return false;
    1742             :         }
    1743      101685 :         if (!smb2req->subreq) {
    1744           0 :                 return false;
    1745             :         }
    1746      101685 :         if (!tevent_req_is_in_progress(smb2req->subreq)) {
    1747           0 :                 return false;
    1748             :         }
    1749      101685 :         state = tevent_req_data(smb2req->subreq,
    1750             :                         struct smbd_smb2_create_state);
    1751      101685 :         if (!state) {
    1752           0 :                 return false;
    1753             :         }
    1754             :         /* It's not in progress if there's no timeout event. */
    1755      101685 :         if (!state->open_was_deferred) {
    1756      101235 :                 return false;
    1757             :         }
    1758             : 
    1759         450 :         DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
    1760             :                         (unsigned long long)mid));
    1761             : 
    1762         450 :         return true;
    1763             : }
    1764             : 
    1765         386 : static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
    1766             :                                                         uint64_t mid)
    1767             : {
    1768         386 :         struct smbd_smb2_create_state *state = NULL;
    1769             : 
    1770         386 :         if (!smb2req->subreq) {
    1771           0 :                 return;
    1772             :         }
    1773         386 :         if (!tevent_req_is_in_progress(smb2req->subreq)) {
    1774           0 :                 return;
    1775             :         }
    1776         386 :         state = tevent_req_data(smb2req->subreq,
    1777             :                         struct smbd_smb2_create_state);
    1778         386 :         if (!state) {
    1779           0 :                 return;
    1780             :         }
    1781             : 
    1782         386 :         DEBUG(10,("remove_deferred_open_message_smb2_internal: "
    1783             :                 "mid %llu\n",
    1784             :                 (unsigned long long)mid ));
    1785             : 
    1786         386 :         state->open_was_deferred = false;
    1787             :         /* Ensure we don't have any outstanding immediate event. */
    1788         386 :         TALLOC_FREE(state->im);
    1789         386 :         TALLOC_FREE(state->open_rec);
    1790             : }
    1791             : 
    1792         382 : void remove_deferred_open_message_smb2(
    1793             :         struct smbXsrv_connection *xconn, uint64_t mid)
    1794             : {
    1795             :         struct smbd_smb2_request *smb2req;
    1796             : 
    1797         382 :         smb2req = find_open_smb2req(xconn, mid);
    1798             : 
    1799         382 :         if (!smb2req) {
    1800           0 :                 DEBUG(10,("remove_deferred_open_message_smb2: "
    1801             :                         "can't find mid %llu\n",
    1802             :                         (unsigned long long)mid ));
    1803           0 :                 return;
    1804             :         }
    1805         382 :         remove_deferred_open_message_smb2_internal(smb2req, mid);
    1806             : }
    1807             : 
    1808         398 : static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
    1809             :                                         struct tevent_immediate *im,
    1810             :                                         void *private_data)
    1811             : {
    1812         398 :         struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
    1813             :                                         struct smbd_smb2_request);
    1814         398 :         uint64_t mid = get_mid_from_smb2req(smb2req);
    1815             :         NTSTATUS status;
    1816             : 
    1817         398 :         DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
    1818             :                 "re-dispatching mid %llu\n",
    1819             :                 (unsigned long long)mid ));
    1820             : 
    1821         398 :         status = smbd_smb2_request_dispatch(smb2req);
    1822         398 :         if (!NT_STATUS_IS_OK(status)) {
    1823           0 :                 smbd_server_connection_terminate(smb2req->xconn,
    1824             :                                                  nt_errstr(status));
    1825           0 :                 return;
    1826             :         }
    1827             : }
    1828             : 
    1829         398 : bool schedule_deferred_open_message_smb2(
    1830             :         struct smbXsrv_connection *xconn, uint64_t mid)
    1831             : {
    1832         398 :         struct smbd_smb2_create_state *state = NULL;
    1833             :         struct smbd_smb2_request *smb2req;
    1834             : 
    1835         398 :         smb2req = find_open_smb2req(xconn, mid);
    1836             : 
    1837         398 :         if (!smb2req) {
    1838           0 :                 DEBUG(10,("schedule_deferred_open_message_smb2: "
    1839             :                         "can't find mid %llu\n",
    1840             :                         (unsigned long long)mid ));
    1841           0 :                 return false;
    1842             :         }
    1843         398 :         if (!smb2req->subreq) {
    1844           0 :                 return false;
    1845             :         }
    1846         398 :         if (!tevent_req_is_in_progress(smb2req->subreq)) {
    1847           0 :                 return false;
    1848             :         }
    1849         398 :         state = tevent_req_data(smb2req->subreq,
    1850             :                         struct smbd_smb2_create_state);
    1851         398 :         if (!state) {
    1852           0 :                 return false;
    1853             :         }
    1854             : 
    1855             :         /* Ensure we don't have any outstanding immediate event. */
    1856         398 :         TALLOC_FREE(state->im);
    1857             : 
    1858             :         /*
    1859             :          * This is subtle. We must null out the callback
    1860             :          * before rescheduling, else the first call to
    1861             :          * tevent_req_nterror() causes the _receive()
    1862             :          * function to be called, this causing tevent_req_post()
    1863             :          * to crash.
    1864             :          */
    1865         398 :         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
    1866             : 
    1867         398 :         state->im = tevent_create_immediate(smb2req);
    1868         398 :         if (!state->im) {
    1869           0 :                 smbd_server_connection_terminate(smb2req->xconn,
    1870             :                         nt_errstr(NT_STATUS_NO_MEMORY));
    1871           0 :                 return false;
    1872             :         }
    1873             : 
    1874         398 :         DEBUG(10,("schedule_deferred_open_message_smb2: "
    1875             :                 "re-processing mid %llu\n",
    1876             :                 (unsigned long long)mid ));
    1877             : 
    1878         398 :         tevent_schedule_immediate(state->im,
    1879             :                         smb2req->sconn->ev_ctx,
    1880             :                         smbd_smb2_create_request_dispatch_immediate,
    1881             :                         smb2req);
    1882             : 
    1883         398 :         return true;
    1884             : }
    1885             : 
    1886           4 : static bool smbd_smb2_create_cancel(struct tevent_req *req)
    1887             : {
    1888           4 :         struct smbd_smb2_request *smb2req = NULL;
    1889           4 :         struct smbd_smb2_create_state *state = tevent_req_data(req,
    1890             :                                 struct smbd_smb2_create_state);
    1891             :         uint64_t mid;
    1892             : 
    1893           4 :         if (!state) {
    1894           0 :                 return false;
    1895             :         }
    1896             : 
    1897           4 :         if (!state->smb2req) {
    1898           0 :                 return false;
    1899             :         }
    1900             : 
    1901           4 :         smb2req = state->smb2req;
    1902           4 :         mid = get_mid_from_smb2req(smb2req);
    1903             : 
    1904           4 :         if (is_deferred_open_async(state->open_rec)) {
    1905             :                 /* Can't cancel an async create. */
    1906           0 :                 return false;
    1907             :         }
    1908             : 
    1909           4 :         remove_deferred_open_message_smb2_internal(smb2req, mid);
    1910             : 
    1911           4 :         tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
    1912           4 :         tevent_req_nterror(req, NT_STATUS_CANCELLED);
    1913           4 :         return true;
    1914             : }
    1915             : 
    1916         450 : bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
    1917             :                                 struct timeval request_time,
    1918             :                                 struct timeval timeout,
    1919             :                                 struct file_id id,
    1920             :                                 struct deferred_open_record *open_rec)
    1921             : {
    1922         450 :         struct tevent_req *req = NULL;
    1923         450 :         struct smbd_smb2_create_state *state = NULL;
    1924             :         struct timeval end_time;
    1925             : 
    1926         450 :         if (!smb2req) {
    1927           0 :                 return false;
    1928             :         }
    1929         450 :         req = smb2req->subreq;
    1930         450 :         if (!req) {
    1931           0 :                 return false;
    1932             :         }
    1933         450 :         state = tevent_req_data(req, struct smbd_smb2_create_state);
    1934         450 :         if (!state) {
    1935           0 :                 return false;
    1936             :         }
    1937         450 :         state->id = id;
    1938         450 :         state->request_time = request_time;
    1939         450 :         state->open_rec = talloc_move(state, &open_rec);
    1940             : 
    1941             :         /* Re-schedule us to retry on timer expiry. */
    1942         450 :         end_time = timeval_sum(&request_time, &timeout);
    1943             : 
    1944         450 :         DEBUG(10,("push_deferred_open_message_smb2: "
    1945             :                 "timeout at %s\n",
    1946             :                 timeval_string(talloc_tos(),
    1947             :                                 &end_time,
    1948             :                                 true) ));
    1949             : 
    1950         450 :         state->open_was_deferred = true;
    1951             : 
    1952             :         /* allow this request to be canceled */
    1953         450 :         tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
    1954             : 
    1955         450 :         return true;
    1956             : }

Generated by: LCOV version 1.13