durable-reopen - adapt a comment
[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 new_durable_reconnect_fsp(struct smbXsrv_open *op,
394                                           TALLOC_CTX *mem_ctx,
395                                           files_sruct **_fsp)
396 {
397         NTSTATUS status = NT_STATUS_NO_MEMORY;
398         files_struct *fsp = NULL;
399         TALLOC_CTX *frame = talloc_stackframe();
400         struct smbd_server_connection *sconn = op->connection->sconn;
401
402         fsp = talloc_zero(frame, struct files_struct);
403         if (fsp == NULL) {
404                 goto fail;
405         }
406
407         /*
408          * This can't be a child of fsp because the file_handle can be ref'd
409          * when doing a dos/fcb open, which will then share the file_handle
410          * across multiple fsps.
411          */
412         fsp->fh = talloc_zero(frame, struct fd_handle);
413         if (fsp->fh == NULL) {
414                 goto fail;
415         }
416
417         status = fsp_set_smb_fname(fsp, /*TODO*/ smb_fname);
418         if (!NT_STATUS_IS_OK(status)) {
419                 goto fail;
420         }
421
422         fsp->fh->ref_count = 1;
423         fsp->fh->fd = -1;
424         fsp->fh->gen_id = get_gen_count(sconn);
425
426         fsp->conn = conn;
427
428
429         /* success */
430
431         talloc_steal(mem_ctx, fsp);
432         talloc_steal(mem_ctx, fsp->fh);
433         *_fsp = fsp;
434
435         status = NT_STATUS_OK;
436
437 fail:
438         talloc_free(frame);
439         return status;
440 }
441
442 static NTSTATUS smb2_create_durable_reconnect(struct smbXsrv_open *op,
443                                               struct smb_request *smb1req,
444
445                                               TALLOC_CTX *mem_ctx,
446                                               files_struct **fsp)
447 {
448         struct share_mode_lock *sharemode_lock;
449         files_struct *fsp = NULL;
450
451         /* 1. check entry in locking.tdb */
452
453         /*
454          * Q: fetch with lock right away?
455          */
456         sharemode_lock = fetch_share_mode_unlocked(mem_ctx,
457                                                    op->global->backend_file_id);
458         if (sharemode_lock == NULL) {
459                 /* TODO: use/create other fetch func with better error code */
460                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
461         }
462
463         if (sharemode_lock->data->num_share_modes == 0) {
464                 /* should not happen? internal error? */
465                 return NT_STATUS_INTERNAL_DB_ERROR;
466         }
467
468         if (sharemode_lock->data->num_share_modes > 1) {
469                 /*
470                  * It can't be durable if there is more than one handle
471                  * on the file.
472                  */
473                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
474         }
475
476         if (serverid_exists(&sharemode_lock->data->share_modes[0].pid))  {
477                 /*
478                  * server still exists
479                  * TODO: check whether session exists
480                  *  (could have been a session_logoff())
481                  */
482                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
483         }
484
485         /* 2. proceed with opening file */
486
487         /*
488          * refetch with lock and update the pid
489          */
490         talloc_free(sharemode_lock);
491         sharemode_lock = get_share_mode_lock(mem_ctx,
492                                              op->global->backend_file_id);
493         if (sharemode_lock == NULL) {
494                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
495         }
496
497         sharemode_lock->data->share_modes[0].pid =
498                 messaging_server_id(op->connection->sconn->msg_ctx);
499
500         /*
501          * circumstances seems ok, do the open
502          */
503         status = new_durable_reconnect_fsp( &fsp);
504         if (!NT_STATUS_IS_OK(status)) {
505                 return status;
506         }
507
508         /* TODO */
509         fsp->fh->fd = SMB_VFS_OPEN(smb1req->conn,
510                                    smb_fname,
511                                    fsp,
512                                    sharemode_lock->data->share_modes[0].flags,
513                                    mode);
514         if (fsp->fh->fd == -1) {
515                 /* ... */
516                 return ...;
517         }
518
519         /* - release the sharemode lock: this writes the changes */
520         talloc_free(sharemode_lock);
521
522         /* - update fsp pointer in smbXsrv_open */
523
524         op->;
525
526         /*
527          * - return
528          *
529          * ... think about seek()
530          */
531         return NT_STATUS_NOT_IMPLEMENTED;
532 }
533
534 struct smbd_smb2_create_state {
535         struct smbd_smb2_request *smb2req;
536         struct smb_request *smb1req;
537         struct timed_event *te;
538         struct tevent_immediate *im;
539         struct timeval request_time;
540         struct file_id id;
541         DATA_BLOB private_data;
542         uint8_t out_oplock_level;
543         uint32_t out_create_action;
544         NTTIME out_creation_time;
545         NTTIME out_last_access_time;
546         NTTIME out_last_write_time;
547         NTTIME out_change_time;
548         uint64_t out_allocation_size;
549         uint64_t out_end_of_file;
550         uint32_t out_file_attributes;
551         uint64_t out_file_id_persistent;
552         uint64_t out_file_id_volatile;
553         struct smb2_create_blobs out_context_blobs;
554 };
555
556 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
557                         struct tevent_context *ev,
558                         struct smbd_smb2_request *smb2req,
559                         uint8_t in_oplock_level,
560                         uint32_t in_impersonation_level,
561                         uint32_t in_desired_access,
562                         uint32_t in_file_attributes,
563                         uint32_t in_share_access,
564                         uint32_t in_create_disposition,
565                         uint32_t in_create_options,
566                         const char *in_name,
567                         struct smb2_create_blobs in_context_blobs)
568 {
569         struct tevent_req *req = NULL;
570         struct smbd_smb2_create_state *state = NULL;
571         NTSTATUS status;
572         struct smb_request *smb1req = NULL;
573         files_struct *result = NULL;
574         int info;
575         struct timespec write_time_ts;
576         struct smb2_create_blobs out_context_blobs;
577         int requested_oplock_level;
578         bool do_durable_reconnect = false;
579
580         ZERO_STRUCT(out_context_blobs);
581
582         if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) {
583                 requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
584         } else {
585                 requested_oplock_level = in_oplock_level;
586         }
587
588
589         if (smb2req->subreq == NULL) {
590                 /* New create call. */
591                 req = tevent_req_create(mem_ctx, &state,
592                                 struct smbd_smb2_create_state);
593                 if (req == NULL) {
594                         return NULL;
595                 }
596                 state->smb2req = smb2req;
597
598                 smb1req = smbd_smb2_fake_smb_request(smb2req);
599                 if (tevent_req_nomem(smb1req, req)) {
600                         return tevent_req_post(req, ev);
601                 }
602                 state->smb1req = smb1req;
603                 smb2req->subreq = req;
604                 DEBUG(10,("smbd_smb2_create: name[%s]\n",
605                         in_name));
606         } else {
607                 /* Re-entrant create call. */
608                 req = smb2req->subreq;
609                 state = tevent_req_data(req,
610                                 struct smbd_smb2_create_state);
611                 smb1req = state->smb1req;
612                 DEBUG(10,("smbd_smb2_create_send: reentrant for file %s\n",
613                         in_name ));
614         }
615
616         if (IS_IPC(smb1req->conn)) {
617                 const char *pipe_name = in_name;
618
619                 if (!lp_nt_pipe_support()) {
620                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
621                         return tevent_req_post(req, ev);
622                 }
623
624                 /* Strip \\ off the name. */
625                 if (pipe_name[0] == '\\') {
626                         pipe_name++;
627                 }
628
629                 status = open_np_file(smb1req, pipe_name, &result);
630                 if (!NT_STATUS_IS_OK(status)) {
631                         tevent_req_nterror(req, status);
632                         return tevent_req_post(req, ev);
633                 }
634                 info = FILE_WAS_OPENED;
635         } else if (CAN_PRINT(smb1req->conn)) {
636                 status = file_new(smb1req, smb1req->conn, &result);
637                 if(!NT_STATUS_IS_OK(status)) {
638                         tevent_req_nterror(req, status);
639                         return tevent_req_post(req, ev);
640                 }
641
642                 status = print_spool_open(result, in_name,
643                                           smb1req->vuid);
644                 if (!NT_STATUS_IS_OK(status)) {
645                         file_free(smb1req, result);
646                         tevent_req_nterror(req, status);
647                         return tevent_req_post(req, ev);
648                 }
649                 info = FILE_WAS_CREATED;
650         } else {
651                 char *fname;
652                 struct smb_filename *smb_fname = NULL;
653                 struct smb2_create_blob *exta = NULL;
654                 struct ea_list *ea_list = NULL;
655                 struct smb2_create_blob *mxac = NULL;
656                 NTTIME max_access_time = 0;
657                 struct smb2_create_blob *secd = NULL;
658                 struct security_descriptor *sec_desc = NULL;
659                 struct smb2_create_blob *dhnq = NULL;
660                 struct smb2_create_blob *dhnc = NULL;
661                 struct smb2_create_blob *alsi = NULL;
662                 uint64_t allocation_size = 0;
663                 struct smb2_create_blob *twrp = NULL;
664                 struct smb2_create_blob *qfid = NULL;
665
666                 exta = smb2_create_blob_find(&in_context_blobs,
667                                              SMB2_CREATE_TAG_EXTA);
668                 mxac = smb2_create_blob_find(&in_context_blobs,
669                                              SMB2_CREATE_TAG_MXAC);
670                 secd = smb2_create_blob_find(&in_context_blobs,
671                                              SMB2_CREATE_TAG_SECD);
672                 dhnq = smb2_create_blob_find(&in_context_blobs,
673                                              SMB2_CREATE_TAG_DHNQ);
674                 dhnc = smb2_create_blob_find(&in_context_blobs,
675                                              SMB2_CREATE_TAG_DHNC);
676                 alsi = smb2_create_blob_find(&in_context_blobs,
677                                              SMB2_CREATE_TAG_ALSI);
678                 twrp = smb2_create_blob_find(&in_context_blobs,
679                                              SMB2_CREATE_TAG_TWRP);
680                 qfid = smb2_create_blob_find(&in_context_blobs,
681                                              SMB2_CREATE_TAG_QFID);
682
683                 fname = talloc_strdup(state, in_name);
684                 if (tevent_req_nomem(fname, req)) {
685                         return tevent_req_post(req, ev);
686                 }
687
688                 if (exta) {
689                         if (dhnc) {
690                                 tevent_req_nterror(req,NT_STATUS_OBJECT_NAME_NOT_FOUND);
691                                 return tevent_req_post(req, ev);
692                         }
693
694                         ea_list = read_nttrans_ea_list(mem_ctx,
695                                 (const char *)exta->data.data, exta->data.length);
696                         if (!ea_list) {
697                                 DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
698                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
699                                 return tevent_req_post(req, ev);
700                         }
701                 }
702
703                 if (mxac) {
704                         if (dhnc) {
705                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
706                                 return tevent_req_post(req, ev);
707                         }
708
709                         if (mxac->data.length == 0) {
710                                 max_access_time = 0;
711                         } else if (mxac->data.length == 8) {
712                                 max_access_time = BVAL(mxac->data.data, 0);
713                         } else {
714                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
715                                 return tevent_req_post(req, ev);
716                         }
717                 }
718
719                 if (secd) {
720                         enum ndr_err_code ndr_err;
721
722                         if (dhnc) {
723                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
724                                 return tevent_req_post(req, ev);
725                         }
726
727                         sec_desc = talloc_zero(state, struct security_descriptor);
728                         if (tevent_req_nomem(sec_desc, req)) {
729                                 return tevent_req_post(req, ev);
730                         }
731
732                         ndr_err = ndr_pull_struct_blob(&secd->data,
733                                 sec_desc, sec_desc,
734                                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
735                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
736                                 DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
737                                          ndr_errstr(ndr_err)));
738                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
739                                 return tevent_req_post(req, ev);
740                         }
741                 }
742
743                 if (dhnq) {
744                         if (dhnc) {
745                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
746                                 return tevent_req_post(req, ev);
747                         }
748
749                         if (dhnq->data.length != 16) {
750                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
751                                 return tevent_req_post(req, ev);
752                         }
753                         /*
754                          * durable handle request is processed below.
755                          */
756                 }
757
758                 if (dhnc) {
759                         uint64_t persistent_id;
760                         struct smbXsrv_open *op = NULL;
761
762                         if (dhnc->data.length != 16) {
763                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
764                                 return tevent_req_post(req, ev);
765                         }
766
767                         persistent_id = BVAL(dhnc->data.data, 0);
768
769                         status = smb2srv_open_recreate(smb2req->sconn->conn,
770                                                        persistent_id,
771                                                        &op);
772                         if (!NT_STATUS_IS_OK(status)) {
773                                 tevent_req_nterror(req, status);
774                                 return tevent_req_post(req, ev);
775                         }
776
777                         /* TODO: needed? or is successful global_lookup enough?) */
778
779                         if (!op->global->durable) {
780                                 talloc_free(op);
781                                 tevent_req_nterror(req,
782                                         NT_STATUS_OBJECT_NAME_NOT_FOUND);
783                                 return tevent_req_post(req, ev);
784                         }
785
786                         do_durable_reconnect = true;
787                 }
788
789                 if (alsi) {
790                         if (dhnc) {
791                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
792                                 return tevent_req_post(req, ev);
793                         }
794
795                         if (alsi->data.length != 8) {
796                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
797                                 return tevent_req_post(req, ev);
798                         }
799                         allocation_size = BVAL(alsi->data.data, 0);
800                 }
801
802                 if (twrp) {
803                         NTTIME nttime;
804                         time_t t;
805                         struct tm *tm;
806
807                         if (dhnc) {
808                                 tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
809                                 return tevent_req_post(req, ev);
810                         }
811
812                         if (twrp->data.length != 8) {
813                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
814                                 return tevent_req_post(req, ev);
815                         }
816
817                         nttime = BVAL(twrp->data.data, 0);
818                         t = nt_time_to_unix(nttime);
819                         tm = gmtime(&t);
820
821                         TALLOC_FREE(fname);
822                         fname = talloc_asprintf(state,
823                                         "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
824                                         tm->tm_year + 1900,
825                                         tm->tm_mon + 1,
826                                         tm->tm_mday,
827                                         tm->tm_hour,
828                                         tm->tm_min,
829                                         tm->tm_sec,
830                                         in_name);
831                         if (tevent_req_nomem(fname, req)) {
832                                 return tevent_req_post(req, ev);
833                         }
834                 }
835
836                 if (qfid) {
837                         if (qfid->data.length != 0) {
838                                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
839                                 return tevent_req_post(req, ev);
840                         }
841                 }
842
843                 /* these are ignored for SMB2 */
844                 in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
845                 in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
846
847                 /*
848                  * For a DFS path the function parse_dfs_path()
849                  * will do the path processing.
850                  */
851
852                 if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
853                         /* convert '\\' into '/' */
854                         status = check_path_syntax(fname);
855                         if (!NT_STATUS_IS_OK(status)) {
856                                 tevent_req_nterror(req, status);
857                                 return tevent_req_post(req, ev);
858                         }
859                 }
860
861                 status = filename_convert(req,
862                                           smb1req->conn,
863                                           smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
864                                           fname,
865                                           0,
866                                           NULL,
867                                           &smb_fname);
868                 if (!NT_STATUS_IS_OK(status)) {
869                         tevent_req_nterror(req, status);
870                         return tevent_req_post(req, ev);
871                 }
872
873                 in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
874
875                 /*
876                  * For the backend file open procedure, there are
877                  * two possible modes: durable_reconnect or not.
878                  */
879                 if (do_durable_reconnect) {
880                         status = smb2_create_durable_reconnect(op,
881                                                                smb1req,
882                                                                smb_fname,
883                                                                mem_ctx,
884                                                                &result);
885
886                         if (!NT_STATUS_IS_OK(status)) {
887                                 tevent_req_nterror(req, status);
888                                 return tevent_req_post(req, ev);
889                         }
890
891                         // TODO: response construction
892
893                         tevent_req_done(req);
894                         return tevent_req_post(req, ev);
895                 } else {
896                         status = SMB_VFS_CREATE_FILE(smb1req->conn,
897                                                      smb1req,
898                                                      0, /* root_dir_fid */
899                                                      smb_fname,
900                                                      in_desired_access,
901                                                      in_share_access,
902                                                      in_create_disposition,
903                                                      in_create_options,
904                                                      in_file_attributes,
905                                                      map_smb2_oplock_levels_to_samba(requested_oplock_level),
906                                                      allocation_size,
907                                                      0, /* private_flags */
908                                                      sec_desc,
909                                                      ea_list,
910                                                      &result,
911                                                      &info);
912                         if (!NT_STATUS_IS_OK(status)) {
913                                 if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
914                                         return req;
915                                 }
916                                 tevent_req_nterror(req, status);
917                                 return tevent_req_post(req, ev);
918                         }
919                 }
920
921                 if (mxac) {
922                         NTTIME last_write_time;
923
924                         unix_timespec_to_nt_time(&last_write_time,
925                                                  result->fsp_name->st.st_ex_mtime);
926                         if (last_write_time != max_access_time) {
927                                 uint8_t p[8];
928                                 uint32_t max_access_granted;
929                                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
930
931                                 status = smbd_calculate_access_mask(smb1req->conn,
932                                                         result->fsp_name,
933                                                         SEC_FLAG_MAXIMUM_ALLOWED,
934                                                         &max_access_granted);
935
936                                 SIVAL(p, 0, NT_STATUS_V(status));
937                                 SIVAL(p, 4, max_access_granted);
938
939                                 status = smb2_create_blob_add(state,
940                                                         &out_context_blobs,
941                                                         SMB2_CREATE_TAG_MXAC,
942                                                         blob);
943                                 if (!NT_STATUS_IS_OK(status)) {
944                                         tevent_req_nterror(req, status);
945                                         return tevent_req_post(req, ev);
946                                 }
947                         }
948                 }
949
950                 if (dhnq && BATCH_OPLOCK_TYPE(result->oplock_type)) {
951                         uint8_t p[8];
952                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
953
954                         result->smbXsrv->global->backend_file_id = result->file_id;
955                         result->smbXsrv->global->durable = true;
956
957                         status = smbXsrv_open_update(result->smbXsrv);
958                         if (!NT_STATUS_IS_OK(status)) {
959                                 tevent_req_nterror(req, status);
960                                 return tevent_req_post(req, ev);
961                         }
962
963                         ZERO_STRUCT(p);
964
965                         status = smb2_create_blob_add(state, &out_context_blobs,
966                                                       SMB2_CREATE_TAG_DHNQ,
967                                                       blob);
968                         if (!NT_STATUS_IS_OK(status)) {
969                                 tevent_req_nterror(req, status);
970                                 return tevent_req_post(req, ev);
971                         }
972                 }
973
974                 if (qfid) {
975                         uint8_t p[32];
976                         uint64_t file_index = get_FileIndex(result->conn,
977                                                         &result->fsp_name->st);
978                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
979
980                         ZERO_STRUCT(p);
981
982                         /* From conversations with Microsoft engineers at
983                            the MS plugfest. The first 8 bytes are the "volume index"
984                            == inode, the second 8 bytes are the "volume id",
985                            == dev. This will be updated in the SMB2 doc. */
986                         SBVAL(p, 0, file_index);
987                         SIVAL(p, 8, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
988
989                         status = smb2_create_blob_add(state, &out_context_blobs,
990                                                       SMB2_CREATE_TAG_QFID,
991                                                       blob);
992                         if (!NT_STATUS_IS_OK(status)) {
993                                 tevent_req_nterror(req, status);
994                                 return tevent_req_post(req, ev);
995                         }
996                 }
997         }
998
999         smb2req->compat_chain_fsp = smb1req->chain_fsp;
1000
1001         if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) {
1002                 state->out_oplock_level = in_oplock_level;
1003         } else {
1004                 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1005         }
1006
1007         if ((in_create_disposition == FILE_SUPERSEDE)
1008             && (info == FILE_WAS_OVERWRITTEN)) {
1009                 state->out_create_action = FILE_WAS_SUPERSEDED;
1010         } else {
1011                 state->out_create_action = info;
1012         }
1013         state->out_file_attributes = dos_mode(result->conn,
1014                                            result->fsp_name);
1015         /* Deal with other possible opens having a modified
1016            write time. JRA. */
1017         ZERO_STRUCT(write_time_ts);
1018         get_file_infos(result->file_id, 0, NULL, &write_time_ts);
1019         if (!null_timespec(write_time_ts)) {
1020                 update_stat_ex_mtime(&result->fsp_name->st, write_time_ts);
1021         }
1022
1023         unix_timespec_to_nt_time(&state->out_creation_time,
1024                         get_create_timespec(smb1req->conn, result,
1025                                         result->fsp_name));
1026         unix_timespec_to_nt_time(&state->out_last_access_time,
1027                         result->fsp_name->st.st_ex_atime);
1028         unix_timespec_to_nt_time(&state->out_last_write_time,
1029                         result->fsp_name->st.st_ex_mtime);
1030         unix_timespec_to_nt_time(&state->out_change_time,
1031                         get_change_timespec(smb1req->conn, result,
1032                                         result->fsp_name));
1033         state->out_allocation_size =
1034                         SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1035                                                &(result->fsp_name->st));
1036         state->out_end_of_file = result->fsp_name->st.st_ex_size;
1037         if (state->out_file_attributes == 0) {
1038                 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1039         }
1040
1041         state->out_file_id_persistent = result->smbXsrv->global->open_persistent_id;
1042         state->out_file_id_volatile = result->smbXsrv->global->open_volatile_id;
1043         state->out_context_blobs = out_context_blobs;
1044
1045         tevent_req_done(req);
1046         return tevent_req_post(req, ev);
1047 }
1048
1049 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1050                         TALLOC_CTX *mem_ctx,
1051                         uint8_t *out_oplock_level,
1052                         uint32_t *out_create_action,
1053                         NTTIME *out_creation_time,
1054                         NTTIME *out_last_access_time,
1055                         NTTIME *out_last_write_time,
1056                         NTTIME *out_change_time,
1057                         uint64_t *out_allocation_size,
1058                         uint64_t *out_end_of_file,
1059                         uint32_t *out_file_attributes,
1060                         uint64_t *out_file_id_persistent,
1061                         uint64_t *out_file_id_volatile,
1062                         struct smb2_create_blobs *out_context_blobs)
1063 {
1064         NTSTATUS status;
1065         struct smbd_smb2_create_state *state = tevent_req_data(req,
1066                                                struct smbd_smb2_create_state);
1067
1068         if (tevent_req_is_nterror(req, &status)) {
1069                 tevent_req_received(req);
1070                 return status;
1071         }
1072
1073         *out_oplock_level       = state->out_oplock_level;
1074         *out_create_action      = state->out_create_action;
1075         *out_creation_time      = state->out_creation_time;
1076         *out_last_access_time   = state->out_last_access_time;
1077         *out_last_write_time    = state->out_last_write_time;
1078         *out_change_time        = state->out_change_time;
1079         *out_allocation_size    = state->out_allocation_size;
1080         *out_end_of_file        = state->out_end_of_file;
1081         *out_file_attributes    = state->out_file_attributes;
1082         *out_file_id_persistent = state->out_file_id_persistent;
1083         *out_file_id_volatile   = state->out_file_id_volatile;
1084         *out_context_blobs      = state->out_context_blobs;
1085
1086         talloc_steal(mem_ctx, state->out_context_blobs.blobs);
1087
1088         tevent_req_received(req);
1089         return NT_STATUS_OK;
1090 }
1091
1092 /*********************************************************
1093  Code for dealing with deferred opens.
1094 *********************************************************/
1095
1096 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1097                         struct timeval *p_request_time,
1098                         void **pp_state)
1099 {
1100         struct smbd_smb2_create_state *state = NULL;
1101         struct tevent_req *req = NULL;
1102
1103         if (!smb2req) {
1104                 return false;
1105         }
1106         if (smb2req->async_te == NULL) {
1107                 return false;
1108         }
1109         req = smb2req->subreq;
1110         if (!req) {
1111                 return false;
1112         }
1113         state = tevent_req_data(req, struct smbd_smb2_create_state);
1114         if (!state) {
1115                 return false;
1116         }
1117         if (p_request_time) {
1118                 *p_request_time = state->request_time;
1119         }
1120         if (pp_state) {
1121                 *pp_state = (void *)state->private_data.data;
1122         }
1123         return true;
1124 }
1125
1126 /*********************************************************
1127  Re-process this call early - requested by message or
1128  close.
1129 *********************************************************/
1130
1131 static struct smbd_smb2_request *find_open_smb2req(
1132         struct smbd_server_connection *sconn, uint64_t mid)
1133 {
1134         struct smbd_smb2_request *smb2req;
1135
1136         for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1137                 uint64_t message_id;
1138                 if (smb2req->subreq == NULL) {
1139                         /* This message has been processed. */
1140                         continue;
1141                 }
1142                 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1143                         /* This message has been processed. */
1144                         continue;
1145                 }
1146                 message_id = get_mid_from_smb2req(smb2req);
1147                 if (message_id == mid) {
1148                         return smb2req;
1149                 }
1150         }
1151         return NULL;
1152 }
1153
1154 bool open_was_deferred_smb2(struct smbd_server_connection *sconn, uint64_t mid)
1155 {
1156         struct smbd_smb2_create_state *state = NULL;
1157         struct smbd_smb2_request *smb2req;
1158
1159         smb2req = find_open_smb2req(sconn, mid);
1160
1161         if (!smb2req) {
1162                 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1163                         (unsigned long long)mid));
1164                 return false;
1165         }
1166         if (!smb2req->subreq) {
1167                 return false;
1168         }
1169         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1170                 return false;
1171         }
1172         state = tevent_req_data(smb2req->subreq,
1173                         struct smbd_smb2_create_state);
1174         if (!state) {
1175                 return false;
1176         }
1177         /* It's not in progress if there's no timeout event. */
1178         if (!state->te) {
1179                 return false;
1180         }
1181
1182         DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1183                         (unsigned long long)mid));
1184
1185         return true;
1186 }
1187
1188 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1189                                                         uint64_t mid)
1190 {
1191         struct smbd_smb2_create_state *state = NULL;
1192
1193         if (!smb2req->subreq) {
1194                 return;
1195         }
1196         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1197                 return;
1198         }
1199         state = tevent_req_data(smb2req->subreq,
1200                         struct smbd_smb2_create_state);
1201         if (!state) {
1202                 return;
1203         }
1204
1205         DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1206                 "mid %llu\n",
1207                 (unsigned long long)mid ));
1208
1209         /* Ensure we don't have any outstanding timer event. */
1210         TALLOC_FREE(state->te);
1211         /* Ensure we don't have any outstanding immediate event. */
1212         TALLOC_FREE(state->im);
1213 }
1214
1215 void remove_deferred_open_message_smb2(
1216         struct smbd_server_connection *sconn, uint64_t mid)
1217 {
1218         struct smbd_smb2_request *smb2req;
1219
1220         smb2req = find_open_smb2req(sconn, mid);
1221
1222         if (!smb2req) {
1223                 DEBUG(10,("remove_deferred_open_message_smb2: "
1224                         "can't find mid %llu\n",
1225                         (unsigned long long)mid ));
1226                 return;
1227         }
1228         remove_deferred_open_message_smb2_internal(smb2req, mid);
1229 }
1230
1231 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1232                                         struct tevent_immediate *im,
1233                                         void *private_data)
1234 {
1235         struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1236                                         struct smbd_smb2_request);
1237         struct smbd_server_connection *sconn = smb2req->sconn;
1238         uint64_t mid = get_mid_from_smb2req(smb2req);
1239         NTSTATUS status;
1240
1241         DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1242                 "re-dispatching mid %llu\n",
1243                 (unsigned long long)mid ));
1244
1245         status = smbd_smb2_request_dispatch(smb2req);
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 smbd_server_connection_terminate(sconn, nt_errstr(status));
1248                 return;
1249         }
1250 }
1251
1252 void schedule_deferred_open_message_smb2(
1253         struct smbd_server_connection *sconn, uint64_t mid)
1254 {
1255         struct smbd_smb2_create_state *state = NULL;
1256         struct smbd_smb2_request *smb2req;
1257
1258         smb2req = find_open_smb2req(sconn, mid);
1259
1260         if (!smb2req) {
1261                 DEBUG(10,("schedule_deferred_open_message_smb2: "
1262                         "can't find mid %llu\n",
1263                         (unsigned long long)mid ));
1264                 return;
1265         }
1266         if (!smb2req->subreq) {
1267                 return;
1268         }
1269         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1270                 return;
1271         }
1272         state = tevent_req_data(smb2req->subreq,
1273                         struct smbd_smb2_create_state);
1274         if (!state) {
1275                 return;
1276         }
1277
1278         /* Ensure we don't have any outstanding timer event. */
1279         TALLOC_FREE(state->te);
1280         /* Ensure we don't have any outstanding immediate event. */
1281         TALLOC_FREE(state->im);
1282
1283         /*
1284          * This is subtle. We must null out the callback
1285          * before resheduling, else the first call to
1286          * tevent_req_nterror() causes the _receive()
1287          * function to be called, this causing tevent_req_post()
1288          * to crash.
1289          */
1290         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1291
1292         state->im = tevent_create_immediate(smb2req);
1293         if (!state->im) {
1294                 smbd_server_connection_terminate(smb2req->sconn,
1295                         nt_errstr(NT_STATUS_NO_MEMORY));
1296                 return;
1297         }
1298
1299         DEBUG(10,("schedule_deferred_open_message_smb2: "
1300                 "re-processing mid %llu\n",
1301                 (unsigned long long)mid ));
1302
1303         tevent_schedule_immediate(state->im,
1304                         smb2req->sconn->ev_ctx,
1305                         smbd_smb2_create_request_dispatch_immediate,
1306                         smb2req);
1307 }
1308
1309 /*********************************************************
1310  Re-process this call.
1311 *********************************************************/
1312
1313 static void smb2_deferred_open_timer(struct event_context *ev,
1314                                         struct timed_event *te,
1315                                         struct timeval _tval,
1316                                         void *private_data)
1317 {
1318         NTSTATUS status;
1319         struct smbd_smb2_create_state *state = NULL;
1320         struct smbd_smb2_request *smb2req = talloc_get_type(private_data,
1321                                                 struct smbd_smb2_request);
1322
1323         DEBUG(10,("smb2_deferred_open_timer: [idx=%d], %s\n",
1324                 smb2req->current_idx,
1325                 tevent_req_default_print(smb2req->subreq, talloc_tos()) ));
1326
1327         state = tevent_req_data(smb2req->subreq,
1328                         struct smbd_smb2_create_state);
1329         if (!state) {
1330                 return;
1331         }
1332         /*
1333          * Null this out, don't talloc_free. It will
1334          * be talloc_free'd by the tevent library when
1335          * this returns.
1336          */
1337         state->te = NULL;
1338         /* Ensure we don't have any outstanding immediate event. */
1339         TALLOC_FREE(state->im);
1340
1341         /*
1342          * This is subtle. We must null out the callback
1343          * before resheduling, else the first call to
1344          * tevent_req_nterror() causes the _receive()
1345          * function to be called, this causing tevent_req_post()
1346          * to crash.
1347          */
1348         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
1349
1350         status = smbd_smb2_request_dispatch(smb2req);
1351
1352         if (!NT_STATUS_IS_OK(status)) {
1353                 smbd_server_connection_terminate(smb2req->sconn,
1354                                 nt_errstr(status));
1355         }
1356 }
1357
1358 static bool smbd_smb2_create_cancel(struct tevent_req *req)
1359 {
1360         struct smbd_smb2_request *smb2req = NULL;
1361         struct smbd_smb2_create_state *state = tevent_req_data(req,
1362                                 struct smbd_smb2_create_state);
1363         uint64_t mid;
1364
1365         if (!state) {
1366                 return false;
1367         }
1368
1369         if (!state->smb2req) {
1370                 return false;
1371         }
1372
1373         smb2req = state->smb2req;
1374         mid = get_mid_from_smb2req(smb2req);
1375
1376         remove_deferred_open_entry(state->id, mid,
1377                                    messaging_server_id(smb2req->sconn->msg_ctx));
1378         remove_deferred_open_message_smb2_internal(smb2req, mid);
1379         smb2req->cancelled = true;
1380
1381         tevent_req_done(req);
1382         return true;
1383 }
1384
1385 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
1386                                 struct timeval request_time,
1387                                 struct timeval timeout,
1388                                 struct file_id id,
1389                                 char *private_data,
1390                                 size_t priv_len)
1391 {
1392         struct tevent_req *req = NULL;
1393         struct smbd_smb2_create_state *state = NULL;
1394         struct timeval end_time;
1395
1396         if (!smb2req) {
1397                 return false;
1398         }
1399         req = smb2req->subreq;
1400         if (!req) {
1401                 return false;
1402         }
1403         state = tevent_req_data(req, struct smbd_smb2_create_state);
1404         if (!state) {
1405                 return false;
1406         }
1407         state->id = id;
1408         state->request_time = request_time;
1409         state->private_data = data_blob_talloc(state, private_data,
1410                                                 priv_len);
1411         if (!state->private_data.data) {
1412                 return false;
1413         }
1414
1415         /* Re-schedule us to retry on timer expiry. */
1416         end_time = timeval_sum(&request_time, &timeout);
1417
1418         DEBUG(10,("push_deferred_open_message_smb2: "
1419                 "timeout at %s\n",
1420                 timeval_string(talloc_tos(),
1421                                 &end_time,
1422                                 true) ));
1423
1424         state->te = tevent_add_timer(smb2req->sconn->ev_ctx,
1425                                 state,
1426                                 end_time,
1427                                 smb2_deferred_open_timer,
1428                                 smb2req);
1429         if (!state->te) {
1430                 return false;
1431         }
1432
1433         /* allow this request to be canceled */
1434         tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
1435
1436         return true;
1437 }