LCOV - code coverage report
Current view: top level - source3/smbd - smb2_create.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 776 978 79.3 %
Date: 2024-05-31 13:13:24 Functions: 25 25 100.0 %

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

Generated by: LCOV version 1.14