smb2_create_durable_reconnect: update the pid in the share-mode entry from the smbXsr...
[metze/samba/wip.git] / source3 / smbd / smb2_create.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "printing.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../libcli/smb/smb_common.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "../lib/util/tevent_ntstatus.h"
29 #include "messages.h"
30 #include "librpc/gen_ndr/open_files.h"
31 #include "serverid.h"
32
33 int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
34 {
35         switch(in_oplock_level) {
36         case SMB2_OPLOCK_LEVEL_NONE:
37                 return NO_OPLOCK;
38         case SMB2_OPLOCK_LEVEL_II:
39                 return LEVEL_II_OPLOCK;
40         case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
41                 return EXCLUSIVE_OPLOCK;
42         case SMB2_OPLOCK_LEVEL_BATCH:
43                 return BATCH_OPLOCK;
44         case SMB2_OPLOCK_LEVEL_LEASE:
45                 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
46                         "LEASE_OPLOCK_REQUESTED\n"));
47                 return NO_OPLOCK;
48         default:
49                 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
50                         "unknown level %u\n",
51                         (unsigned int)in_oplock_level));
52                 return NO_OPLOCK;
53         }
54 }
55
56 static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
57 {
58         if (BATCH_OPLOCK_TYPE(oplock_type)) {
59                 return SMB2_OPLOCK_LEVEL_BATCH;
60         } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
61                 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
62         } else if (oplock_type == LEVEL_II_OPLOCK) {
63                 /*
64                  * Don't use LEVEL_II_OPLOCK_TYPE here as
65                  * this also includes FAKE_LEVEL_II_OPLOCKs
66                  * which are internal only.
67                  */
68                 return SMB2_OPLOCK_LEVEL_II;
69         } else {
70                 return SMB2_OPLOCK_LEVEL_NONE;
71         }
72 }
73
74 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
75                         struct tevent_context *ev,
76                         struct smbd_smb2_request *smb2req,
77                         uint8_t in_oplock_level,
78                         uint32_t in_impersonation_level,
79                         uint32_t in_desired_access,
80                         uint32_t in_file_attributes,
81                         uint32_t in_share_access,
82                         uint32_t in_create_disposition,
83                         uint32_t in_create_options,
84                         const char *in_name,
85                         struct smb2_create_blobs in_context_blobs);
86 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
87                         TALLOC_CTX *mem_ctx,
88                         uint8_t *out_oplock_level,
89                         uint32_t *out_create_action,
90                         NTTIME *out_creation_time,
91                         NTTIME *out_last_access_time,
92                         NTTIME *out_last_write_time,
93                         NTTIME *out_change_time,
94                         uint64_t *out_allocation_size,
95                         uint64_t *out_end_of_file,
96                         uint32_t *out_file_attributes,
97                         uint64_t *out_file_id_persistent,
98                         uint64_t *out_file_id_volatile,
99                         struct smb2_create_blobs *out_context_blobs);
100
101 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
102 NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
103 {
104         const uint8_t *inbody;
105         const struct iovec *indyniov;
106         int i = smb2req->current_idx;
107         uint8_t in_oplock_level;
108         uint32_t in_impersonation_level;
109         uint32_t in_desired_access;
110         uint32_t in_file_attributes;
111         uint32_t in_share_access;
112         uint32_t in_create_disposition;
113         uint32_t in_create_options;
114         uint16_t in_name_offset;
115         uint16_t in_name_length;
116         DATA_BLOB in_name_buffer;
117         char *in_name_string;
118         size_t in_name_string_size;
119         uint32_t name_offset = 0;
120         uint32_t name_available_length = 0;
121         uint32_t in_context_offset;
122         uint32_t in_context_length;
123         DATA_BLOB in_context_buffer;
124         struct smb2_create_blobs in_context_blobs;
125         uint32_t context_offset = 0;
126         uint32_t context_available_length = 0;
127         uint32_t dyn_offset;
128         NTSTATUS status;
129         bool ok;
130         struct tevent_req *tsubreq;
131
132         status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
133         if (!NT_STATUS_IS_OK(status)) {
134                 return smbd_smb2_request_error(smb2req, status);
135         }
136         inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
137
138         in_oplock_level         = CVAL(inbody, 0x03);
139         in_impersonation_level  = IVAL(inbody, 0x04);
140         in_desired_access       = IVAL(inbody, 0x18);
141         in_file_attributes      = IVAL(inbody, 0x1C);
142         in_share_access         = IVAL(inbody, 0x20);
143         in_create_disposition   = IVAL(inbody, 0x24);
144         in_create_options       = IVAL(inbody, 0x28);
145         in_name_offset          = SVAL(inbody, 0x2C);
146         in_name_length          = SVAL(inbody, 0x2E);
147         in_context_offset       = IVAL(inbody, 0x30);
148         in_context_length       = IVAL(inbody, 0x34);
149
150         /*
151          * First check if the dynamic name and context buffers
152          * are correctly specified.
153          *
154          * Note: That we don't check if the name and context buffers
155          *       overlap
156          */
157
158         dyn_offset = SMB2_HDR_BODY + smb2req->in.vector[i+1].iov_len;
159
160         if (in_name_offset == 0 && in_name_length == 0) {
161                 /* This is ok */
162                 name_offset = 0;
163         } else if (in_name_offset < dyn_offset) {
164                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
165         } else {
166                 name_offset = in_name_offset - dyn_offset;
167         }
168
169         indyniov = &smb2req->in.vector[i+2];
170
171         if (name_offset > indyniov->iov_len) {
172                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
173         }
174
175         name_available_length = indyniov->iov_len - name_offset;
176
177         if (in_name_length > name_available_length) {
178                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
179         }
180
181         in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
182         in_name_buffer.length = in_name_length;
183
184         if (in_context_offset == 0 && in_context_length == 0) {
185                 /* This is ok */
186                 context_offset = 0;
187         } else if (in_context_offset < dyn_offset) {
188                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
189         } else {
190                 context_offset = in_context_offset - dyn_offset;
191         }
192
193         if (context_offset > indyniov->iov_len) {
194                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
195         }
196
197         context_available_length = indyniov->iov_len - context_offset;
198
199         if (in_context_length > context_available_length) {
200                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
201         }
202
203         in_context_buffer.data = (uint8_t *)indyniov->iov_base +
204                 context_offset;
205         in_context_buffer.length = in_context_length;
206
207         /*
208          * Now interpret the name and context buffers
209          */
210
211         ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
212                                    in_name_buffer.data,
213                                    in_name_buffer.length,
214                                    &in_name_string,
215                                    &in_name_string_size);
216         if (!ok) {
217                 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
218         }
219
220         if (in_name_buffer.length == 0) {
221                 in_name_string_size = 0;
222         }
223
224         if (strlen(in_name_string) != in_name_string_size) {
225                 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
226         }
227
228         ZERO_STRUCT(in_context_blobs);
229         status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
230         if (!NT_STATUS_IS_OK(status)) {
231                 return smbd_smb2_request_error(smb2req, status);
232         }
233
234         tsubreq = smbd_smb2_create_send(smb2req,
235                                        smb2req->sconn->ev_ctx,
236                                        smb2req,
237                                        in_oplock_level,
238                                        in_impersonation_level,
239                                        in_desired_access,
240                                        in_file_attributes,
241                                        in_share_access,
242                                        in_create_disposition,
243                                        in_create_options,
244                                        in_name_string,
245                                        in_context_blobs);
246         if (tsubreq == NULL) {
247                 smb2req->subreq = NULL;
248                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
249         }
250         tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
251
252         /*
253          * For now we keep the logic that we do not send STATUS_PENDING
254          * for sharing violations, so we just wait 2 seconds.
255          *
256          * TODO: we need more tests for this.
257          */
258         return smbd_smb2_request_pending_queue(smb2req, tsubreq, 2000000);
259 }
260
261 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
262 {
263         uint8_t *reqhdr = (uint8_t *)smb2req->out.vector[smb2req->current_idx].iov_base;
264         return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
265 }
266
267 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
268 {
269         struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
270                                         struct smbd_smb2_request);
271         DATA_BLOB outbody;
272         DATA_BLOB outdyn;
273         uint8_t out_oplock_level = 0;
274         uint32_t out_create_action = 0;
275         NTTIME out_creation_time = 0;
276         NTTIME out_last_access_time = 0;
277         NTTIME out_last_write_time = 0;
278         NTTIME out_change_time = 0;
279         uint64_t out_allocation_size = 0;
280         uint64_t out_end_of_file = 0;
281         uint32_t out_file_attributes = 0;
282         uint64_t out_file_id_persistent = 0;
283         uint64_t out_file_id_volatile = 0;
284         struct smb2_create_blobs out_context_blobs;
285         DATA_BLOB out_context_buffer;
286         uint16_t out_context_buffer_offset = 0;
287         NTSTATUS status;
288         NTSTATUS error; /* transport error */
289
290         if (smb2req->cancelled) {
291                 uint64_t mid = get_mid_from_smb2req(smb2req);
292                 DEBUG(10,("smbd_smb2_request_create_done: cancelled mid %llu\n",
293                         (unsigned long long)mid ));
294                 error = smbd_smb2_request_error(smb2req, NT_STATUS_CANCELLED);
295                 if (!NT_STATUS_IS_OK(error)) {
296                         smbd_server_connection_terminate(smb2req->sconn,
297                                 nt_errstr(error));
298                         return;
299                 }
300                 return;
301         }
302
303         status = smbd_smb2_create_recv(tsubreq,
304                                        smb2req,
305                                        &out_oplock_level,
306                                        &out_create_action,
307                                        &out_creation_time,
308                                        &out_last_access_time,
309                                        &out_last_write_time,
310                                        &out_change_time,
311                                        &out_allocation_size,
312                                        &out_end_of_file,
313                                        &out_file_attributes,
314                                        &out_file_id_persistent,
315                                        &out_file_id_volatile,
316                                        &out_context_blobs);
317         if (!NT_STATUS_IS_OK(status)) {
318                 error = smbd_smb2_request_error(smb2req, status);
319                 if (!NT_STATUS_IS_OK(error)) {
320                         smbd_server_connection_terminate(smb2req->sconn,
321                                                          nt_errstr(error));
322                         return;
323                 }
324                 return;
325         }
326
327         status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
328         if (!NT_STATUS_IS_OK(status)) {
329                 error = smbd_smb2_request_error(smb2req, status);
330                 if (!NT_STATUS_IS_OK(error)) {
331                         smbd_server_connection_terminate(smb2req->sconn,
332                                                          nt_errstr(error));
333                         return;
334                 }
335                 return;
336         }
337
338         if (out_context_buffer.length > 0) {
339                 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
340         }
341
342         outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x58);
343         if (outbody.data == NULL) {
344                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
345                 if (!NT_STATUS_IS_OK(error)) {
346                         smbd_server_connection_terminate(smb2req->sconn,
347                                                          nt_errstr(error));
348                         return;
349                 }
350                 return;
351         }
352
353         SSVAL(outbody.data, 0x00, 0x58 + 1);    /* struct size */
354         SCVAL(outbody.data, 0x02,
355               out_oplock_level);                /* oplock level */
356         SCVAL(outbody.data, 0x03, 0);           /* reserved */
357         SIVAL(outbody.data, 0x04,
358               out_create_action);               /* create action */
359         SBVAL(outbody.data, 0x08,
360               out_creation_time);               /* creation time */
361         SBVAL(outbody.data, 0x10,
362               out_last_access_time);            /* last access time */
363         SBVAL(outbody.data, 0x18,
364               out_last_write_time);             /* last write time */
365         SBVAL(outbody.data, 0x20,
366               out_change_time);                 /* change time */
367         SBVAL(outbody.data, 0x28,
368               out_allocation_size);             /* allocation size */
369         SBVAL(outbody.data, 0x30,
370               out_end_of_file);                 /* end of file */
371         SIVAL(outbody.data, 0x38,
372               out_file_attributes);             /* file attributes */
373         SIVAL(outbody.data, 0x3C, 0);           /* reserved */
374         SBVAL(outbody.data, 0x40,
375               out_file_id_persistent);          /* file id (persistent) */
376         SBVAL(outbody.data, 0x48,
377               out_file_id_volatile);            /* file id (volatile) */
378         SIVAL(outbody.data, 0x50,
379               out_context_buffer_offset);       /* create contexts offset */
380         SIVAL(outbody.data, 0x54,
381               out_context_buffer.length);       /* create contexts length */
382
383         outdyn = out_context_buffer;
384
385         error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
386         if (!NT_STATUS_IS_OK(error)) {
387                 smbd_server_connection_terminate(smb2req->sconn,
388                                                  nt_errstr(error));
389                 return;
390         }
391 }
392
393 static NTSTATUS smb2_create_durable_reconnect(struct smbXsrv_open *op,
394                                               TALLOC_CTX *mem_ctx,
395                                               files_struct **fsp)
396 {
397         struct share_mode_lock *sharemode_lock;
398
399         /* 1. check entry in locking.tdb */
400
401         /*
402          * Q: fetch with lock right away?
403          */
404         sharemode_lock = fetch_share_mode_unlocked(mem_ctx,
405                                                    op->global->backend_file_id);
406         if (sharemode_lock == NULL) {
407                 /* TODO: use/create other fetch func with better error code */
408                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
409         }
410
411         if (sharemode_lock->data->num_share_modes == 0) {
412                 /* should not happen? internal error? */
413                 return NT_STATUS_INTERNAL_DB_ERROR;
414         }
415
416         if (sharemode_lock->data->num_share_modes > 1) {
417                 /*
418                  * It can't be durable if there is more than one handle
419                  * on the file.
420                  */
421                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
422         }
423
424         if (serverid_exists(&sharemode_lock->data->share_modes[0].pid))  {
425                 /*
426                  * server still exists
427                  * TODO: check whether session exists
428                  *  (could have been a session_logoff())
429                  */
430                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
431         }
432
433         /* 2. proceed with opening file */
434
435         /*
436          * refetch with lock and update the pid
437          */
438         talloc_free(sharemode_lock);
439         sharemode_lock = get_share_mode_lock(mem_ctx,
440                                              op->global->backend_file_id);
441         if (sharemode_lock == NULL) {
442                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
443         }
444
445         sharemode_lock->data->share_modes[0].pid =
446                 messaging_server_id(op->connection->sconn->msg_ctx);
447
448         /*
449          * - reopen the file with SMB_VFS_OPEN()
450          * - build a files_struct
451          * - release the sharemode lock
452          * - update fsp pointer in smbXsrv_open
453          * - return
454          *
455          * ... think about seek()
456          */
457         return NT_STATUS_NOT_IMPLEMENTED;
458 }
459
460 struct smbd_smb2_create_state {
461         struct smbd_smb2_request *smb2req;
462         struct smb_request *smb1req;
463         struct timed_event *te;
464         struct tevent_immediate *im;
465         struct timeval request_time;
466         struct file_id id;
467         DATA_BLOB private_data;
468         uint8_t out_oplock_level;
469         uint32_t out_create_action;
470         NTTIME out_creation_time;
471         NTTIME out_last_access_time;
472         NTTIME out_last_write_time;
473         NTTIME out_change_time;
474         uint64_t out_allocation_size;
475         uint64_t out_end_of_file;
476         uint32_t out_file_attributes;
477         uint64_t out_file_id_persistent;
478         uint64_t out_file_id_volatile;
479         struct smb2_create_blobs out_context_blobs;
480 };
481
482 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
483                         struct tevent_context *ev,
484                         struct smbd_smb2_request *smb2req,
485                         uint8_t in_oplock_level,
486                         uint32_t in_impersonation_level,
487                         uint32_t in_desired_access,
488                         uint32_t in_file_attributes,
489                         uint32_t in_share_access,
490                         uint32_t in_create_disposition,
491                         uint32_t in_create_options,
492                         const char *in_name,
493                         struct smb2_create_blobs in_context_blobs)
494 {
495         struct tevent_req *req = NULL;
496         struct smbd_smb2_create_state *state = NULL;
497         NTSTATUS status;
498         struct smb_request *smb1req = NULL;
499         files_struct *result = NULL;
500         int info;
501         struct timespec write_time_ts;
502         struct smb2_create_blobs out_context_blobs;
503         int requested_oplock_level;
504
505         ZERO_STRUCT(out_context_blobs);
506
507         if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) {
508                 requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
509         } else {
510                 requested_oplock_level = in_oplock_level;
511         }
512
513
514         if (smb2req->subreq == NULL) {
515                 /* New create call. */
516                 req = tevent_req_create(mem_ctx, &state,
517                                 struct smbd_smb2_create_state);
518                 if (req == NULL) {
519                         return NULL;
520                 }
521                 state->smb2req = smb2req;
522
523                 smb1req = smbd_smb2_fake_smb_request(smb2req);
524                 if (tevent_req_nomem(smb1req, req)) {
525                         return tevent_req_post(req, ev);
526                 }
527                 state->smb1req = smb1req;
528                 smb2req->subreq = req;
529                 DEBUG(10,("smbd_smb2_create: name[%s]\n",
530                         in_name));
531         } else {
532                 /* Re-entrant create call. */
533                 req = smb2req->subreq;
534                 state = tevent_req_data(req,
535                                 struct smbd_smb2_create_state);
536                 smb1req = state->smb1req;
537                 DEBUG(10,("smbd_smb2_create_send: reentrant for file %s\n",
538                         in_name ));
539         }
540
541         if (IS_IPC(smb1req->conn)) {
542                 const char *pipe_name = in_name;
543
544                 if (!lp_nt_pipe_support()) {
545                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
546                         return tevent_req_post(req, ev);
547                 }
548
549                 /* Strip \\ off the name. */
550                 if (pipe_name[0] == '\\') {
551                         pipe_name++;
552                 }
553
554                 status = open_np_file(smb1req, pipe_name, &result);
555                 if (!NT_STATUS_IS_OK(status)) {
556                         tevent_req_nterror(req, status);
557                         return tevent_req_post(req, ev);
558                 }
559                 info = FILE_WAS_OPENED;
560         } else if (CAN_PRINT(smb1req->conn)) {
561                 status = file_new(smb1req, smb1req->conn, &result);
562                 if(!NT_STATUS_IS_OK(status)) {
563                         tevent_req_nterror(req, status);
564                         return tevent_req_post(req, ev);
565                 }
566
567                 status = print_spool_open(result, in_name,
568                                           smb1req->vuid);
569                 if (!NT_STATUS_IS_OK(status)) {
570                         file_free(smb1req, result);
571                         tevent_req_nterror(req, status);
572                         return tevent_req_post(req, ev);
573                 }
574                 info = FILE_WAS_CREATED;
575         } else {
576                 char *fname;
577                 struct smb_filename *smb_fname = NULL;
578                 struct smb2_create_blob *exta = NULL;
579                 struct ea_list *ea_list = NULL;
580                 struct smb2_create_blob *mxac = NULL;
581                 NTTIME max_access_time = 0;
582                 struct smb2_create_blob *secd = NULL;
583                 struct security_descriptor *sec_desc = NULL;
584                 struct smb2_create_blob *dhnq = NULL;
585                 struct smb2_create_blob *dhnc = NULL;
586                 struct smb2_create_blob *alsi = NULL;
587                 uint64_t allocation_size = 0;
588                 struct smb2_create_blob *twrp = NULL;
589                 struct smb2_create_blob *qfid = NULL;
590
591                 exta = smb2_create_blob_find(&in_context_blobs,
592                                              SMB2_CREATE_TAG_EXTA);
593                 mxac = smb2_create_blob_find(&in_context_blobs,
594                                              SMB2_CREATE_TAG_MXAC);
595                 secd = smb2_create_blob_find(&in_context_blobs,
596                                              SMB2_CREATE_TAG_SECD);
597                 dhnq = smb2_create_blob_find(&in_context_blobs,
598                                              SMB2_CREATE_TAG_DHNQ);
599                 dhnc = smb2_create_blob_find(&in_context_blobs,
600                                              SMB2_CREATE_TAG_DHNC);
601                 alsi = smb2_create_blob_find(&in_context_blobs,
602                                              SMB2_CREATE_TAG_ALSI);
603                 twrp = smb2_create_blob_find(&in_context_blobs,
604                                              SMB2_CREATE_TAG_TWRP);
605                 qfid = smb2_create_blob_find(&in_context_blobs,
606                                              SMB2_CREATE_TAG_QFID);
607
608                 fname = talloc_strdup(state, in_name);
609                 if (tevent_req_nomem(fname, req)) {
610                         return tevent_req_post(req, ev);
611                 }
612
613                 if (exta) {
614                         if (dhnc) {
615                                 tevent_req_nterror(req,NT_STATUS_OBJECT_NAME_NOT_FOUND);
616                                 return tevent_req_post(req, ev);
617                         }
618
619                         ea_list = read_nttrans_ea_list(mem_ctx,
620                                 (const char *)exta->data.data, exta->data.length);
621                         if (!ea_list) {
622                                 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
623                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
624                                 return tevent_req_post(req, ev);
625                         }
626                 }
627
628                 if (mxac) {
629                         if (dhnc) {
630                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
631                                 return tevent_req_post(req, ev);
632                         }
633
634                         if (mxac->data.length == 0) {
635                                 max_access_time = 0;
636                         } else if (mxac->data.length == 8) {
637                                 max_access_time = BVAL(mxac->data.data, 0);
638                         } else {
639                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
640                                 return tevent_req_post(req, ev);
641                         }
642                 }
643
644                 if (secd) {
645                         enum ndr_err_code ndr_err;
646
647                         if (dhnc) {
648                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
649                                 return tevent_req_post(req, ev);
650                         }
651
652                         sec_desc = talloc_zero(state, struct security_descriptor);
653                         if (tevent_req_nomem(sec_desc, req)) {
654                                 return tevent_req_post(req, ev);
655                         }
656
657                         ndr_err = ndr_pull_struct_blob(&secd->data,
658                                 sec_desc, sec_desc,
659                                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
660                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
661                                 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
662                                          ndr_errstr(ndr_err)));
663                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
664                                 return tevent_req_post(req, ev);
665                         }
666                 }
667
668                 if (dhnq) {
669                         if (dhnc) {
670                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
671                                 return tevent_req_post(req, ev);
672                         }
673
674                         if (dhnq->data.length != 16) {
675                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
676                                 return tevent_req_post(req, ev);
677                         }
678                         /*
679                          * durable handle request is processed below.
680                          */
681                 }
682
683                 if (dhnc) {
684                         uint64_t persistent_id;
685                         struct smbXsrv_open *op = NULL;
686
687                         if (dhnc->data.length != 16) {
688                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
689                                 return tevent_req_post(req, ev);
690                         }
691
692                         persistent_id = BVAL(dhnc->data.data, 0);
693
694                         status = smb2srv_open_recreate(smb2req->sconn->conn,
695                                                        persistent_id,
696                                                        &op);
697                         if (!NT_STATUS_IS_OK(status)) {
698                                 tevent_req_nterror(req, status);
699                                 return tevent_req_post(req, ev);
700                         }
701
702                         /* TODO: needed? or is successful global_lookup enough?) */
703
704                         if (!op->global->durable) {
705                                 talloc_free(op);
706                                 tevent_req_nterror(req,
707                                         NT_STATUS_OBJECT_NAME_NOT_FOUND);
708                                 return tevent_req_post(req, ev);
709                         }
710
711                         // TODO: implement this function..
712                         status = smb2_create_durable_reconnect(op, mem_ctx, &result);
713
714                         if (!NT_STATUS_IS_OK(status)) {
715                                 tevent_req_nterror(req, status);
716                                 return tevent_req_post(req, ev);
717                         }
718
719                         // TODO: response construction
720
721                         tevent_req_done(req);
722                         return tevent_req_post(req, ev);
723                 }
724
725                 if (alsi) {
726                         if (dhnc) {
727                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
728                                 return tevent_req_post(req, ev);
729                         }
730
731                         if (alsi->data.length != 8) {
732                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
733                                 return tevent_req_post(req, ev);
734                         }
735                         allocation_size = BVAL(alsi->data.data, 0);
736                 }
737
738                 if (twrp) {
739                         NTTIME nttime;
740                         time_t t;
741                         struct tm *tm;
742
743                         if (dhnc) {
744                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
745                                 return tevent_req_post(req, ev);
746                         }
747
748                         if (twrp->data.length != 8) {
749                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
750                                 return tevent_req_post(req, ev);
751                         }
752
753                         nttime = BVAL(twrp->data.data, 0);
754                         t = nt_time_to_unix(nttime);
755                         tm = gmtime(&t);
756
757                         TALLOC_FREE(fname);
758                         fname = talloc_asprintf(state,
759                                         "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
760                                         tm->tm_year + 1900,
761                                         tm->tm_mon + 1,
762                                         tm->tm_mday,
763                                         tm->tm_hour,
764                                         tm->tm_min,
765                                         tm->tm_sec,
766                                         in_name);
767                         if (tevent_req_nomem(fname, req)) {
768                                 return tevent_req_post(req, ev);
769                         }
770                 }
771
772                 if (qfid) {
773                         if (qfid->data.length != 0) {
774                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
775                                 return tevent_req_post(req, ev);
776                         }
777                 }
778
779                 /* these are ignored for SMB2 */
780                 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
781                 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
782
783                 /*
784                  * For a DFS path the function parse_dfs_path()
785                  * will do the path processing.
786                  */
787
788                 if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
789                         /* convert '\\' into '/' */
790                         status = check_path_syntax(fname);
791                         if (!NT_STATUS_IS_OK(status)) {
792                                 tevent_req_nterror(req, status);
793                                 return tevent_req_post(req, ev);
794                         }
795                 }
796
797                 status = filename_convert(req,
798                                           smb1req->conn,
799                                           smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
800                                           fname,
801                                           0,
802                                           NULL,
803                                           &smb_fname);
804                 if (!NT_STATUS_IS_OK(status)) {
805                         tevent_req_nterror(req, status);
806                         return tevent_req_post(req, ev);
807                 }
808
809                 in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
810
811                 status = SMB_VFS_CREATE_FILE(smb1req->conn,
812                                              smb1req,
813                                              0, /* root_dir_fid */
814                                              smb_fname,
815                                              in_desired_access,
816                                              in_share_access,
817                                              in_create_disposition,
818                                              in_create_options,
819                                              in_file_attributes,
820                                              map_smb2_oplock_levels_to_samba(requested_oplock_level),
821                                              allocation_size,
822                                              0, /* private_flags */
823                                              sec_desc,
824                                              ea_list,
825                                              &result,
826                                              &info);
827                 if (!NT_STATUS_IS_OK(status)) {
828                         if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
829                                 return req;
830                         }
831                         tevent_req_nterror(req, status);
832                         return tevent_req_post(req, ev);
833                 }
834
835                 if (mxac) {
836                         NTTIME last_write_time;
837
838                         unix_timespec_to_nt_time(&last_write_time,
839                                                  result->fsp_name->st.st_ex_mtime);
840                         if (last_write_time != max_access_time) {
841                                 uint8_t p[8];
842                                 uint32_t max_access_granted;
843                                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
844
845                                 status = smbd_calculate_access_mask(smb1req->conn,
846                                                         result->fsp_name,
847                                                         SEC_FLAG_MAXIMUM_ALLOWED,
848                                                         &max_access_granted);
849
850                                 SIVAL(p, 0, NT_STATUS_V(status));
851                                 SIVAL(p, 4, max_access_granted);
852
853                                 status = smb2_create_blob_add(state,
854                                                         &out_context_blobs,
855                                                         SMB2_CREATE_TAG_MXAC,
856                                                         blob);
857                                 if (!NT_STATUS_IS_OK(status)) {
858                                         tevent_req_nterror(req, status);
859                                         return tevent_req_post(req, ev);
860                                 }
861                         }
862                 }
863
864                 if (dhnq && BATCH_OPLOCK_TYPE(result->oplock_type)) {
865                         uint8_t p[8];
866                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
867
868                         result->smbXsrv->global->backend_file_id = result->file_id;
869                         result->smbXsrv->global->durable = true;
870
871                         status = smbXsrv_open_update(result->smbXsrv);
872                         if (!NT_STATUS_IS_OK(status)) {
873                                 tevent_req_nterror(req, status);
874                                 return tevent_req_post(req, ev);
875                         }
876
877                         ZERO_STRUCT(p);
878
879                         status = smb2_create_blob_add(state, &out_context_blobs,
880                                                       SMB2_CREATE_TAG_DHNQ,
881                                                       blob);
882                         if (!NT_STATUS_IS_OK(status)) {
883                                 tevent_req_nterror(req, status);
884                                 return tevent_req_post(req, ev);
885                         }
886                 }
887
888                 if (qfid) {
889                         uint8_t p[32];
890                         uint64_t file_index = get_FileIndex(result->conn,
891                                                         &result->fsp_name->st);
892                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
893
894                         ZERO_STRUCT(p);
895
896                         /* From conversations with Microsoft engineers at
897                            the MS plugfest. The first 8 bytes are the "volume index"
898                            == inode, the second 8 bytes are the "volume id",
899                            == dev. This will be updated in the SMB2 doc. */
900                         SBVAL(p, 0, file_index);
901                         SIVAL(p, 8, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
902
903                         status = smb2_create_blob_add(state, &out_context_blobs,
904                                                       SMB2_CREATE_TAG_QFID,
905                                                       blob);
906                         if (!NT_STATUS_IS_OK(status)) {
907                                 tevent_req_nterror(req, status);
908                                 return tevent_req_post(req, ev);
909                         }
910                 }
911         }
912
913         smb2req->compat_chain_fsp = smb1req->chain_fsp;
914
915         if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) {
916                 state->out_oplock_level = in_oplock_level;
917         } else {
918                 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
919         }
920
921         if ((in_create_disposition == FILE_SUPERSEDE)
922             && (info == FILE_WAS_OVERWRITTEN)) {
923                 state->out_create_action = FILE_WAS_SUPERSEDED;
924         } else {
925                 state->out_create_action = info;
926         }
927         state->out_file_attributes = dos_mode(result->conn,
928                                            result->fsp_name);
929         /* Deal with other possible opens having a modified
930            write time. JRA. */
931         ZERO_STRUCT(write_time_ts);
932         get_file_infos(result->file_id, 0, NULL, &write_time_ts);
933         if (!null_timespec(write_time_ts)) {
934                 update_stat_ex_mtime(&result->fsp_name->st, write_time_ts);
935         }
936
937         unix_timespec_to_nt_time(&state->out_creation_time,
938                         get_create_timespec(smb1req->conn, result,
939                                         result->fsp_name));
940         unix_timespec_to_nt_time(&state->out_last_access_time,
941                         result->fsp_name->st.st_ex_atime);
942         unix_timespec_to_nt_time(&state->out_last_write_time,
943                         result->fsp_name->st.st_ex_mtime);
944         unix_timespec_to_nt_time(&state->out_change_time,
945                         get_change_timespec(smb1req->conn, result,
946                                         result->fsp_name));
947         state->out_allocation_size =
948                         SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
949                                                &(result->fsp_name->st));
950         state->out_end_of_file = result->fsp_name->st.st_ex_size;
951         if (state->out_file_attributes == 0) {
952                 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
953         }
954
955         state->out_file_id_persistent = result->smbXsrv->global->open_persistent_id;
956         state->out_file_id_volatile = result->smbXsrv->global->open_volatile_id;
957         state->out_context_blobs = out_context_blobs;
958
959         tevent_req_done(req);
960         return tevent_req_post(req, ev);
961 }
962
963 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
964                         TALLOC_CTX *mem_ctx,
965                         uint8_t *out_oplock_level,
966                         uint32_t *out_create_action,
967                         NTTIME *out_creation_time,
968                         NTTIME *out_last_access_time,
969                         NTTIME *out_last_write_time,
970                         NTTIME *out_change_time,
971                         uint64_t *out_allocation_size,
972                         uint64_t *out_end_of_file,
973                         uint32_t *out_file_attributes,
974                         uint64_t *out_file_id_persistent,
975                         uint64_t *out_file_id_volatile,
976                         struct smb2_create_blobs *out_context_blobs)
977 {
978         NTSTATUS status;
979         struct smbd_smb2_create_state *state = tevent_req_data(req,
980                                                struct smbd_smb2_create_state);
981
982         if (tevent_req_is_nterror(req, &status)) {
983                 tevent_req_received(req);
984                 return status;
985         }
986
987         *out_oplock_level       = state->out_oplock_level;
988         *out_create_action      = state->out_create_action;
989         *out_creation_time      = state->out_creation_time;
990         *out_last_access_time   = state->out_last_access_time;
991         *out_last_write_time    = state->out_last_write_time;
992         *out_change_time        = state->out_change_time;
993         *out_allocation_size    = state->out_allocation_size;
994         *out_end_of_file        = state->out_end_of_file;
995         *out_file_attributes    = state->out_file_attributes;
996         *out_file_id_persistent = state->out_file_id_persistent;
997         *out_file_id_volatile   = state->out_file_id_volatile;
998         *out_context_blobs      = state->out_context_blobs;
999
1000         talloc_steal(mem_ctx, state->out_context_blobs.blobs);
1001
1002         tevent_req_received(req);
1003         return NT_STATUS_OK;
1004 }
1005
1006 /*********************************************************
1007  Code for dealing with deferred opens.
1008 *********************************************************/
1009
1010 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1011                         struct timeval *p_request_time,
1012                         void **pp_state)
1013 {
1014         struct smbd_smb2_create_state *state = NULL;
1015         struct tevent_req *req = NULL;
1016
1017         if (!smb2req) {
1018                 return false;
1019         }
1020         if (smb2req->async_te == NULL) {
1021                 return false;
1022         }
1023         req = smb2req->subreq;
1024         if (!req) {
1025                 return false;
1026         }
1027         state = tevent_req_data(req, struct smbd_smb2_create_state);
1028         if (!state) {
1029                 return false;
1030         }
1031         if (p_request_time) {
1032                 *p_request_time = state->request_time;
1033         }
1034         if (pp_state) {
1035                 *pp_state = (void *)state->private_data.data;
1036         }
1037         return true;
1038 }
1039
1040 /*********************************************************
1041  Re-process this call early - requested by message or
1042  close.
1043 *********************************************************/
1044
1045 static struct smbd_smb2_request *find_open_smb2req(
1046         struct smbd_server_connection *sconn, uint64_t mid)
1047 {
1048         struct smbd_smb2_request *smb2req;
1049
1050         for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1051                 uint64_t message_id;
1052                 if (smb2req->subreq == NULL) {
1053                         /* This message has been processed. */
1054                         continue;
1055                 }
1056                 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1057                         /* This message has been processed. */
1058                         continue;
1059                 }
1060                 message_id = get_mid_from_smb2req(smb2req);
1061                 if (message_id == mid) {
1062                         return smb2req;
1063                 }
1064         }
1065         return NULL;
1066 }
1067
1068 bool open_was_deferred_smb2(struct smbd_server_connection *sconn, uint64_t mid)
1069 {
1070         struct smbd_smb2_create_state *state = NULL;
1071         struct smbd_smb2_request *smb2req;
1072
1073         smb2req = find_open_smb2req(sconn, mid);
1074
1075         if (!smb2req) {
1076                 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1077                         (unsigned long long)mid));
1078                 return false;
1079         }
1080         if (!smb2req->subreq) {
1081                 return false;
1082         }
1083         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1084                 return false;
1085         }
1086         state = tevent_req_data(smb2req->subreq,
1087                         struct smbd_smb2_create_state);
1088         if (!state) {
1089                 return false;
1090         }
1091         /* It's not in progress if there's no timeout event. */
1092         if (!state->te) {
1093                 return false;
1094         }
1095
1096         DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1097                         (unsigned long long)mid));
1098
1099         return true;
1100 }
1101
1102 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1103                                                         uint64_t mid)
1104 {
1105         struct smbd_smb2_create_state *state = NULL;
1106
1107         if (!smb2req->subreq) {
1108                 return;
1109         }
1110         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1111                 return;
1112         }
1113         state = tevent_req_data(smb2req->subreq,
1114                         struct smbd_smb2_create_state);
1115         if (!state) {
1116                 return;
1117         }
1118
1119         DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1120                 "mid %llu\n",
1121                 (unsigned long long)mid ));
1122
1123         /* Ensure we don't have any outstanding timer event. */
1124         TALLOC_FREE(state->te);
1125         /* Ensure we don't have any outstanding immediate event. */
1126         TALLOC_FREE(state->im);
1127 }
1128
1129 void remove_deferred_open_message_smb2(
1130         struct smbd_server_connection *sconn, uint64_t mid)
1131 {
1132         struct smbd_smb2_request *smb2req;
1133
1134         smb2req = find_open_smb2req(sconn, mid);
1135
1136         if (!smb2req) {
1137                 DEBUG(10,("remove_deferred_open_message_smb2: "
1138                         "can't find mid %llu\n",
1139                         (unsigned long long)mid ));
1140                 return;
1141         }
1142         remove_deferred_open_message_smb2_internal(smb2req, mid);
1143 }
1144
1145 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1146                                         struct tevent_immediate *im,
1147                                         void *private_data)
1148 {
1149         struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1150                                         struct smbd_smb2_request);
1151         struct smbd_server_connection *sconn = smb2req->sconn;
1152         uint64_t mid = get_mid_from_smb2req(smb2req);
1153         NTSTATUS status;
1154
1155         DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1156                 "re-dispatching mid %llu\n",
1157                 (unsigned long long)mid ));
1158
1159         status = smbd_smb2_request_dispatch(smb2req);
1160         if (!NT_STATUS_IS_OK(status)) {
1161                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1162                 return;
1163         }
1164 }
1165
1166 void schedule_deferred_open_message_smb2(
1167         struct smbd_server_connection *sconn, uint64_t mid)
1168 {
1169         struct smbd_smb2_create_state *state = NULL;
1170         struct smbd_smb2_request *smb2req;
1171
1172         smb2req = find_open_smb2req(sconn, mid);
1173
1174         if (!smb2req) {
1175                 DEBUG(10,("schedule_deferred_open_message_smb2: "
1176                         "can't find mid %llu\n",
1177                         (unsigned long long)mid ));
1178                 return;
1179         }
1180         if (!smb2req->subreq) {
1181                 return;
1182         }
1183         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1184                 return;
1185         }
1186         state = tevent_req_data(smb2req->subreq,
1187                         struct smbd_smb2_create_state);
1188         if (!state) {
1189                 return;
1190         }
1191
1192         /* Ensure we don't have any outstanding timer event. */
1193         TALLOC_FREE(state->te);
1194         /* Ensure we don't have any outstanding immediate event. */
1195         TALLOC_FREE(state->im);
1196
1197         /*
1198          * This is subtle. We must null out the callback
1199          * before resheduling, else the first call to
1200          * tevent_req_nterror() causes the _receive()
1201          * function to be called, this causing tevent_req_post()
1202          * to crash.
1203          */
1204         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1205
1206         state->im = tevent_create_immediate(smb2req);
1207         if (!state->im) {
1208                 smbd_server_connection_terminate(smb2req->sconn,
1209                         nt_errstr(NT_STATUS_NO_MEMORY));
1210                 return;
1211         }
1212
1213         DEBUG(10,("schedule_deferred_open_message_smb2: "
1214                 "re-processing mid %llu\n",
1215                 (unsigned long long)mid ));
1216
1217         tevent_schedule_immediate(state->im,
1218                         smb2req->sconn->ev_ctx,
1219                         smbd_smb2_create_request_dispatch_immediate,
1220                         smb2req);
1221 }
1222
1223 /*********************************************************
1224  Re-process this call.
1225 *********************************************************/
1226
1227 static void smb2_deferred_open_timer(struct event_context *ev,
1228                                         struct timed_event *te,
1229                                         struct timeval _tval,
1230                                         void *private_data)
1231 {
1232         NTSTATUS status;
1233         struct smbd_smb2_create_state *state = NULL;
1234         struct smbd_smb2_request *smb2req = talloc_get_type(private_data,
1235                                                 struct smbd_smb2_request);
1236
1237         DEBUG(10,("smb2_deferred_open_timer: [idx=%d], %s\n",
1238                 smb2req->current_idx,
1239                 tevent_req_default_print(smb2req->subreq, talloc_tos()) ));
1240
1241         state = tevent_req_data(smb2req->subreq,
1242                         struct smbd_smb2_create_state);
1243         if (!state) {
1244                 return;
1245         }
1246         /*
1247          * Null this out, don't talloc_free. It will
1248          * be talloc_free'd by the tevent library when
1249          * this returns.
1250          */
1251         state->te = NULL;
1252         /* Ensure we don't have any outstanding immediate event. */
1253         TALLOC_FREE(state->im);
1254
1255         /*
1256          * This is subtle. We must null out the callback
1257          * before resheduling, else the first call to
1258          * tevent_req_nterror() causes the _receive()
1259          * function to be called, this causing tevent_req_post()
1260          * to crash.
1261          */
1262         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1263
1264         status = smbd_smb2_request_dispatch(smb2req);
1265
1266         if (!NT_STATUS_IS_OK(status)) {
1267                 smbd_server_connection_terminate(smb2req->sconn,
1268                                 nt_errstr(status));
1269         }
1270 }
1271
1272 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1273 {
1274         struct smbd_smb2_request *smb2req = NULL;
1275         struct smbd_smb2_create_state *state = tevent_req_data(req,
1276                                 struct smbd_smb2_create_state);
1277         uint64_t mid;
1278
1279         if (!state) {
1280                 return false;
1281         }
1282
1283         if (!state->smb2req) {
1284                 return false;
1285         }
1286
1287         smb2req = state->smb2req;
1288         mid = get_mid_from_smb2req(smb2req);
1289
1290         remove_deferred_open_entry(state->id, mid,
1291                                    messaging_server_id(smb2req->sconn->msg_ctx));
1292         remove_deferred_open_message_smb2_internal(smb2req, mid);
1293         smb2req->cancelled = true;
1294
1295         tevent_req_done(req);
1296         return true;
1297 }
1298
1299 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1300                                 struct timeval request_time,
1301                                 struct timeval timeout,
1302                                 struct file_id id,
1303                                 char *private_data,
1304                                 size_t priv_len)
1305 {
1306         struct tevent_req *req = NULL;
1307         struct smbd_smb2_create_state *state = NULL;
1308         struct timeval end_time;
1309
1310         if (!smb2req) {
1311                 return false;
1312         }
1313         req = smb2req->subreq;
1314         if (!req) {
1315                 return false;
1316         }
1317         state = tevent_req_data(req, struct smbd_smb2_create_state);
1318         if (!state) {
1319                 return false;
1320         }
1321         state->id = id;
1322         state->request_time = request_time;
1323         state->private_data = data_blob_talloc(state, private_data,
1324                                                 priv_len);
1325         if (!state->private_data.data) {
1326                 return false;
1327         }
1328
1329         /* Re-schedule us to retry on timer expiry. */
1330         end_time = timeval_sum(&request_time, &timeout);
1331
1332         DEBUG(10,("push_deferred_open_message_smb2: "
1333                 "timeout at %s\n",
1334                 timeval_string(talloc_tos(),
1335                                 &end_time,
1336                                 true) ));
1337
1338         state->te = tevent_add_timer(smb2req->sconn->ev_ctx,
1339                                 state,
1340                                 end_time,
1341                                 smb2_deferred_open_timer,
1342                                 smb2req);
1343         if (!state->te) {
1344                 return false;
1345         }
1346
1347         /* allow this request to be canceled */
1348         tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
1349
1350         return true;
1351 }