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