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