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