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