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