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