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