smbd: Add conn_protocol()
[samba.git] / source3 / smbd / smb2_create.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "printing.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "smbd/smbXsrv_open.h"
27 #include "../libcli/smb/smb_common.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
30 #include "../librpc/gen_ndr/ndr_smb3posix.h"
31 #include "../lib/util/tevent_ntstatus.h"
32 #include "messages.h"
33 #include "lib/util_ea.h"
34 #include "source3/passdb/lookup_sid.h"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_SMB2
38
39 int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
40 {
41         switch(in_oplock_level) {
42         case SMB2_OPLOCK_LEVEL_NONE:
43                 return NO_OPLOCK;
44         case SMB2_OPLOCK_LEVEL_II:
45                 return LEVEL_II_OPLOCK;
46         case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
47                 return EXCLUSIVE_OPLOCK;
48         case SMB2_OPLOCK_LEVEL_BATCH:
49                 return BATCH_OPLOCK;
50         case SMB2_OPLOCK_LEVEL_LEASE:
51                 return LEASE_OPLOCK;
52         default:
53                 DEBUG(2,("map_smb2_oplock_levels_to_samba: "
54                         "unknown level %u\n",
55                         (unsigned int)in_oplock_level));
56                 return NO_OPLOCK;
57         }
58 }
59
60 static uint8_t map_samba_oplock_levels_to_smb2(int oplock_type)
61 {
62         if (BATCH_OPLOCK_TYPE(oplock_type)) {
63                 return SMB2_OPLOCK_LEVEL_BATCH;
64         } else if (EXCLUSIVE_OPLOCK_TYPE(oplock_type)) {
65                 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
66         } else if (oplock_type == LEVEL_II_OPLOCK) {
67                 return SMB2_OPLOCK_LEVEL_II;
68         } else if (oplock_type == LEASE_OPLOCK) {
69                 return SMB2_OPLOCK_LEVEL_LEASE;
70         } else {
71                 return SMB2_OPLOCK_LEVEL_NONE;
72         }
73 }
74
75 /*
76  MS-FSA 2.1.5.1 Server Requests an Open of a File
77  Trailing '/' or '\\' checker.
78  Must be done before the filename parser removes any
79  trailing characters. If we decide to add this to SMB1
80  NTCreate processing we can make this public.
81
82  Note this is Windows pathname processing only. When
83  POSIX pathnames are added to SMB2 this will not apply.
84 */
85
86 static NTSTATUS windows_name_trailing_check(const char *name,
87                         uint32_t create_options)
88 {
89         size_t name_len = strlen(name);
90         char trail_c;
91
92         if (name_len <= 1) {
93                 return NT_STATUS_OK;
94         }
95
96         trail_c = name[name_len-1];
97
98         /*
99          * Trailing '/' is always invalid.
100          */
101         if (trail_c == '/') {
102                 return NT_STATUS_OBJECT_NAME_INVALID;
103         }
104
105         if (create_options & FILE_NON_DIRECTORY_FILE) {
106                 if (trail_c == '\\') {
107                         return NT_STATUS_OBJECT_NAME_INVALID;
108                 }
109         }
110         return NT_STATUS_OK;
111 }
112
113 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
114                         struct tevent_context *ev,
115                         struct smbd_smb2_request *smb2req,
116                         uint8_t in_oplock_level,
117                         uint32_t in_impersonation_level,
118                         uint32_t in_desired_access,
119                         uint32_t in_file_attributes,
120                         uint32_t in_share_access,
121                         uint32_t in_create_disposition,
122                         uint32_t _in_create_options,
123                         const char *in_name,
124                         struct smb2_create_blobs in_context_blobs);
125 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
126                         TALLOC_CTX *mem_ctx,
127                         uint8_t *out_oplock_level,
128                         uint32_t *out_create_action,
129                         struct timespec *out_creation_ts,
130                         struct timespec *out_last_access_ts,
131                         struct timespec *out_last_write_ts,
132                         struct timespec *out_change_ts,
133                         uint64_t *out_allocation_size,
134                         uint64_t *out_end_of_file,
135                         uint32_t *out_file_attributes,
136                         uint64_t *out_file_id_persistent,
137                         uint64_t *out_file_id_volatile,
138                         struct smb2_create_blobs *out_context_blobs);
139
140 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq);
141 NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
142 {
143         const uint8_t *inbody;
144         const struct iovec *indyniov;
145         uint8_t in_oplock_level;
146         uint32_t in_impersonation_level;
147         uint32_t in_desired_access;
148         uint32_t in_file_attributes;
149         uint32_t in_share_access;
150         uint32_t in_create_disposition;
151         uint32_t in_create_options;
152         uint16_t in_name_offset;
153         uint16_t in_name_length;
154         DATA_BLOB in_name_buffer;
155         char *in_name_string;
156         size_t in_name_string_size;
157         uint32_t name_offset = 0;
158         uint32_t name_available_length = 0;
159         uint32_t in_context_offset;
160         uint32_t in_context_length;
161         DATA_BLOB in_context_buffer;
162         struct smb2_create_blobs in_context_blobs;
163         uint32_t context_offset = 0;
164         uint32_t context_available_length = 0;
165         uint32_t dyn_offset;
166         NTSTATUS status;
167         bool ok;
168         struct tevent_req *tsubreq;
169
170         status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
171         if (!NT_STATUS_IS_OK(status)) {
172                 return smbd_smb2_request_error(smb2req, status);
173         }
174         inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
175
176         in_oplock_level         = CVAL(inbody, 0x03);
177         in_impersonation_level  = IVAL(inbody, 0x04);
178         in_desired_access       = IVAL(inbody, 0x18);
179         in_file_attributes      = IVAL(inbody, 0x1C);
180         in_share_access         = IVAL(inbody, 0x20);
181         in_create_disposition   = IVAL(inbody, 0x24);
182         in_create_options       = IVAL(inbody, 0x28);
183         in_name_offset          = SVAL(inbody, 0x2C);
184         in_name_length          = SVAL(inbody, 0x2E);
185         in_context_offset       = IVAL(inbody, 0x30);
186         in_context_length       = IVAL(inbody, 0x34);
187
188         /*
189          * First check if the dynamic name and context buffers
190          * are correctly specified.
191          *
192          * Note: That we don't check if the name and context buffers
193          *       overlap
194          */
195
196         dyn_offset = SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req);
197
198         if (in_name_offset == 0 && in_name_length == 0) {
199                 /* This is ok */
200                 name_offset = 0;
201         } else if (in_name_offset < dyn_offset) {
202                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
203         } else {
204                 name_offset = in_name_offset - dyn_offset;
205         }
206
207         indyniov = SMBD_SMB2_IN_DYN_IOV(smb2req);
208
209         if (name_offset > indyniov->iov_len) {
210                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
211         }
212
213         name_available_length = indyniov->iov_len - name_offset;
214
215         if (in_name_length > name_available_length) {
216                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
217         }
218
219         in_name_buffer.data = (uint8_t *)indyniov->iov_base + name_offset;
220         in_name_buffer.length = in_name_length;
221
222         if (in_context_offset == 0 && in_context_length == 0) {
223                 /* This is ok */
224                 context_offset = 0;
225         } else if (in_context_offset < dyn_offset) {
226                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
227         } else {
228                 context_offset = in_context_offset - dyn_offset;
229         }
230
231         if (context_offset > indyniov->iov_len) {
232                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
233         }
234
235         context_available_length = indyniov->iov_len - context_offset;
236
237         if (in_context_length > context_available_length) {
238                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
239         }
240
241         in_context_buffer.data = (uint8_t *)indyniov->iov_base +
242                 context_offset;
243         in_context_buffer.length = in_context_length;
244
245         /*
246          * Now interpret the name and context buffers
247          */
248
249         ok = convert_string_talloc(smb2req, CH_UTF16, CH_UNIX,
250                                    in_name_buffer.data,
251                                    in_name_buffer.length,
252                                    &in_name_string,
253                                    &in_name_string_size);
254         if (!ok) {
255                 return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
256         }
257
258         if (in_name_buffer.length == 0) {
259                 in_name_string_size = 0;
260         }
261
262         if (strlen(in_name_string) != in_name_string_size) {
263                 return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
264         }
265
266         ZERO_STRUCT(in_context_blobs);
267         status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
268         if (!NT_STATUS_IS_OK(status)) {
269                 return smbd_smb2_request_error(smb2req, status);
270         }
271
272         if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
273                 char *str = talloc_asprintf(
274                         talloc_tos(),
275                         "\nGot %"PRIu32" create blobs\n",
276                         in_context_blobs.num_blobs);
277                 uint32_t i;
278
279                 for (i=0; i<in_context_blobs.num_blobs; i++) {
280                         struct smb2_create_blob *b =
281                                 &in_context_blobs.blobs[i];
282                         talloc_asprintf_addbuf(&str, "[%"PRIu32"]\n", i);
283                         dump_data_addbuf(
284                                 (uint8_t *)b->tag, strlen(b->tag), &str);
285                         dump_data_addbuf(
286                                 b->data.data, b->data.length, &str);
287                 }
288                 DBG_DEBUG("%s", str);
289                 TALLOC_FREE(str);
290         }
291
292         tsubreq = smbd_smb2_create_send(smb2req,
293                                        smb2req->sconn->ev_ctx,
294                                        smb2req,
295                                        in_oplock_level,
296                                        in_impersonation_level,
297                                        in_desired_access,
298                                        in_file_attributes,
299                                        in_share_access,
300                                        in_create_disposition,
301                                        in_create_options,
302                                        in_name_string,
303                                        in_context_blobs);
304         if (tsubreq == NULL) {
305                 smb2req->subreq = NULL;
306                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
307         }
308         tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
309
310         return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500);
311 }
312
313 static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
314 {
315         uint8_t *reqhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
316         return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
317 }
318
319 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
320 {
321         struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
322                                         struct smbd_smb2_request);
323         DATA_BLOB outbody;
324         DATA_BLOB outdyn;
325         uint8_t out_oplock_level = 0;
326         uint32_t out_create_action = 0;
327         connection_struct *conn = smb2req->tcon->compat;
328         struct timespec out_creation_ts = { 0, };
329         struct timespec out_last_access_ts = { 0, };
330         struct timespec out_last_write_ts = { 0, };
331         struct timespec out_change_ts = { 0, };
332         uint64_t out_allocation_size = 0;
333         uint64_t out_end_of_file = 0;
334         uint32_t out_file_attributes = 0;
335         uint64_t out_file_id_persistent = 0;
336         uint64_t out_file_id_volatile = 0;
337         struct smb2_create_blobs out_context_blobs;
338         DATA_BLOB out_context_buffer;
339         uint16_t out_context_buffer_offset = 0;
340         NTSTATUS status;
341         NTSTATUS error; /* transport error */
342
343         status = smbd_smb2_create_recv(tsubreq,
344                                        smb2req,
345                                        &out_oplock_level,
346                                        &out_create_action,
347                                        &out_creation_ts,
348                                        &out_last_access_ts,
349                                        &out_last_write_ts,
350                                        &out_change_ts,
351                                        &out_allocation_size,
352                                        &out_end_of_file,
353                                        &out_file_attributes,
354                                        &out_file_id_persistent,
355                                        &out_file_id_volatile,
356                                        &out_context_blobs);
357         if (!NT_STATUS_IS_OK(status)) {
358                 if (smbd_smb2_is_compound(smb2req)) {
359                         smb2req->compound_create_err = status;
360                 }
361                 error = smbd_smb2_request_error(smb2req, status);
362                 if (!NT_STATUS_IS_OK(error)) {
363                         smbd_server_connection_terminate(smb2req->xconn,
364                                                          nt_errstr(error));
365                         return;
366                 }
367                 return;
368         }
369
370         status = smb2_create_blob_push(smb2req, &out_context_buffer, out_context_blobs);
371         if (!NT_STATUS_IS_OK(status)) {
372                 error = smbd_smb2_request_error(smb2req, status);
373                 if (!NT_STATUS_IS_OK(error)) {
374                         smbd_server_connection_terminate(smb2req->xconn,
375                                                          nt_errstr(error));
376                         return;
377                 }
378                 return;
379         }
380
381         if (out_context_buffer.length > 0) {
382                 out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
383         }
384
385         outbody = smbd_smb2_generate_outbody(smb2req, 0x58);
386         if (outbody.data == NULL) {
387                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
388                 if (!NT_STATUS_IS_OK(error)) {
389                         smbd_server_connection_terminate(smb2req->xconn,
390                                                          nt_errstr(error));
391                         return;
392                 }
393                 return;
394         }
395
396         SSVAL(outbody.data, 0x00, 0x58 + 1);    /* struct size */
397         SCVAL(outbody.data, 0x02,
398               out_oplock_level);                /* oplock level */
399         SCVAL(outbody.data, 0x03, 0);           /* reserved */
400         SIVAL(outbody.data, 0x04,
401               out_create_action);               /* create action */
402         put_long_date_full_timespec(conn->ts_res,
403               (char *)outbody.data + 0x08,
404               &out_creation_ts);                /* creation time */
405         put_long_date_full_timespec(conn->ts_res,
406               (char *)outbody.data + 0x10,
407               &out_last_access_ts);             /* last access time */
408         put_long_date_full_timespec(conn->ts_res,
409               (char *)outbody.data + 0x18,
410               &out_last_write_ts);              /* last write time */
411         put_long_date_full_timespec(conn->ts_res,
412               (char *)outbody.data + 0x20,
413               &out_change_ts);                  /* change time */
414         SBVAL(outbody.data, 0x28,
415               out_allocation_size);             /* allocation size */
416         SBVAL(outbody.data, 0x30,
417               out_end_of_file);                 /* end of file */
418         SIVAL(outbody.data, 0x38,
419               out_file_attributes);             /* file attributes */
420         SIVAL(outbody.data, 0x3C, 0);           /* reserved */
421         SBVAL(outbody.data, 0x40,
422               out_file_id_persistent);          /* file id (persistent) */
423         SBVAL(outbody.data, 0x48,
424               out_file_id_volatile);            /* file id (volatile) */
425         SIVAL(outbody.data, 0x50,
426               out_context_buffer_offset);       /* create contexts offset */
427         SIVAL(outbody.data, 0x54,
428               out_context_buffer.length);       /* create contexts length */
429
430         outdyn = out_context_buffer;
431
432         error = smbd_smb2_request_done(smb2req, outbody, &outdyn);
433         if (!NT_STATUS_IS_OK(error)) {
434                 smbd_server_connection_terminate(smb2req->xconn,
435                                                  nt_errstr(error));
436                 return;
437         }
438 }
439
440 static bool smb2_lease_key_valid(const struct smb2_lease_key *key)
441 {
442         return ((key->data[0] != 0) || (key->data[1] != 0));
443 }
444
445 static NTSTATUS smbd_smb2_create_durable_lease_check(struct smb_request *smb1req,
446         const char *requested_filename, const struct files_struct *fsp,
447         const struct smb2_lease *lease_ptr)
448 {
449         struct files_struct *dirfsp = NULL;
450         char *filename = NULL;
451         struct smb_filename *smb_fname = NULL;
452         uint32_t ucf_flags;
453         NTTIME twrp = fsp->fsp_name->twrp;
454         NTSTATUS status;
455         bool is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
456         bool is_posix = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
457
458         if (lease_ptr == NULL) {
459                 if (fsp->oplock_type != LEASE_OPLOCK) {
460                         return NT_STATUS_OK;
461                 }
462                 DEBUG(10, ("Reopened file has lease, but no lease "
463                            "requested\n"));
464                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
465         }
466
467         if (fsp->oplock_type != LEASE_OPLOCK) {
468                 DEBUG(10, ("Lease requested, but reopened file has no "
469                            "lease\n"));
470                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
471         }
472
473         if (!smb2_lease_key_equal(&lease_ptr->lease_key,
474                                   &fsp->lease->lease.lease_key)) {
475                 DEBUG(10, ("Different lease key requested than found "
476                            "in reopened file\n"));
477                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
478         }
479
480         if (is_dfs) {
481                 const char *non_dfs_requested_filename = NULL;
482                 /*
483                  * With a DFS flag set, remove any DFS prefix
484                  * before further processing.
485                  */
486                 status = smb2_strip_dfs_path(requested_filename,
487                                              &non_dfs_requested_filename);
488                 if (!NT_STATUS_IS_OK(status)) {
489                         return status;
490                 }
491                 /*
492                  * TODO: Note for dealing with reparse point errors.
493                  * We will need to remember and store the number of characters
494                  * we have removed here, which is
495                  * (requested_filename - non_dfs_requested_filename)
496                  * in order to correctly report how many characters we
497                  * have removed before hitting the reparse point.
498                  * This will be a patch needed once we properly
499                  * deal with reparse points later.
500                  */
501                 requested_filename = non_dfs_requested_filename;
502                 /*
503                  * Now we're no longer dealing with a DFS path, so
504                  * remove the flag.
505                  */
506                 smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
507                 is_dfs = false;
508         }
509
510         filename = talloc_strdup(talloc_tos(), requested_filename);
511         if (filename == NULL) {
512                 return NT_STATUS_NO_MEMORY;
513         }
514
515         /* This also converts '\' to '/' */
516         status = check_path_syntax(filename, is_posix);
517         if (!NT_STATUS_IS_OK(status)) {
518                 TALLOC_FREE(filename);
519                 return status;
520         }
521
522         ucf_flags = filename_create_ucf_flags(smb1req, FILE_OPEN);
523         status = filename_convert_dirfsp(talloc_tos(),
524                                          fsp->conn,
525                                          filename,
526                                          ucf_flags,
527                                          twrp,
528                                          &dirfsp,
529                                          &smb_fname);
530         TALLOC_FREE(filename);
531         if (!NT_STATUS_IS_OK(status)) {
532                 DEBUG(10, ("filename_convert returned %s\n",
533                            nt_errstr(status)));
534                 return status;
535         }
536
537         if (!strequal(fsp->fsp_name->base_name, smb_fname->base_name)) {
538                 DEBUG(10, ("Lease requested for file %s, reopened file "
539                            "is named %s\n", smb_fname->base_name,
540                            fsp->fsp_name->base_name));
541                 TALLOC_FREE(smb_fname);
542                 return NT_STATUS_INVALID_PARAMETER;
543         }
544
545         TALLOC_FREE(smb_fname);
546
547         return NT_STATUS_OK;
548 }
549
550 struct smbd_smb2_create_state {
551         struct tevent_context *ev;
552         struct smbd_smb2_request *smb2req;
553         struct GUID req_guid;
554         struct smb_request *smb1req;
555         bool open_was_deferred;
556         struct tevent_immediate *im;
557         struct timeval request_time;
558         struct file_id id;
559         struct deferred_open_record *open_rec;
560         files_struct *result;
561         bool replay_operation;
562         uint8_t in_oplock_level;
563         uint32_t in_create_disposition;
564         uint32_t in_create_options;
565         int requested_oplock_level;
566         int info;
567         char *fname;
568         struct ea_list *ea_list;
569         NTTIME max_access_time;
570         struct security_descriptor *sec_desc;
571         uint64_t allocation_size;
572         struct GUID _create_guid;
573         struct GUID *create_guid;
574         struct GUID _purge_create_guid;
575         struct GUID *purge_create_guid;
576         bool update_open;
577         bool durable_requested;
578         uint32_t durable_timeout_msec;
579         bool do_durable_reconnect;
580         uint64_t persistent_id;
581         struct smb2_lease lease;
582         struct smb2_lease *lease_ptr;
583         ssize_t lease_len;
584         bool need_replay_cache;
585         struct smbXsrv_open *op;
586         NTTIME twrp_time;
587
588         struct smb2_create_blob *dhnc;
589         struct smb2_create_blob *dh2c;
590         struct smb2_create_blob *dhnq;
591         struct smb2_create_blob *dh2q;
592         struct smb2_create_blob *rqls;
593         struct smb2_create_blob *exta;
594         struct smb2_create_blob *mxac;
595         struct smb2_create_blob *secd;
596         struct smb2_create_blob *alsi;
597         struct smb2_create_blob *twrp;
598         struct smb2_create_blob *qfid;
599         struct smb2_create_blob *posx;
600         struct smb2_create_blob *svhdx;
601
602         uint8_t out_oplock_level;
603         uint32_t out_create_action;
604         struct timespec out_creation_ts;
605         struct timespec out_last_access_ts;
606         struct timespec out_last_write_ts;
607         struct timespec out_change_ts;
608         uint64_t out_allocation_size;
609         uint64_t out_end_of_file;
610         uint32_t out_file_attributes;
611         uint64_t out_file_id_persistent;
612         uint64_t out_file_id_volatile;
613         struct smb2_create_blobs *out_context_blobs;
614 };
615
616 static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
617                                                 const char *caller_func);
618
619 static void smbd_smb2_create_cleanup(struct tevent_req *req,
620                                      enum tevent_req_state req_state)
621 {
622         smbd_smb2_create_purge_replay_cache(req, __func__);
623 }
624
625 static NTSTATUS smbd_smb2_create_fetch_create_ctx(
626         struct tevent_req *req,
627         struct smb2_create_blobs *in_context_blobs)
628 {
629         struct smbd_smb2_create_state *state = tevent_req_data(
630                 req, struct smbd_smb2_create_state);
631         struct smbd_smb2_request *smb2req = state->smb2req;
632         struct smbXsrv_connection *xconn = smb2req->xconn;
633
634         state->dhnq = smb2_create_blob_find(in_context_blobs,
635                                             SMB2_CREATE_TAG_DHNQ);
636         state->dhnc = smb2_create_blob_find(in_context_blobs,
637                                             SMB2_CREATE_TAG_DHNC);
638         state->dh2q = smb2_create_blob_find(in_context_blobs,
639                                             SMB2_CREATE_TAG_DH2Q);
640         state->dh2c = smb2_create_blob_find(in_context_blobs,
641                                             SMB2_CREATE_TAG_DH2C);
642         if (xconn->smb2.server.capabilities & SMB2_CAP_LEASING) {
643                 state->rqls = smb2_create_blob_find(in_context_blobs,
644                                                     SMB2_CREATE_TAG_RQLS);
645         }
646
647         if (((state->dhnc != NULL) && (state->dh2c != NULL)) ||
648             ((state->dhnc != NULL) && (state->dh2q != NULL)) ||
649             ((state->dh2c != NULL) && (state->dhnq != NULL)) ||
650             ((state->dh2q != NULL) && (state->dh2c != NULL)))
651         {
652                 /* not both are allowed at the same time */
653                 return NT_STATUS_INVALID_PARAMETER;
654         }
655
656         if (state->dhnc != NULL) {
657                 uint32_t num_blobs_allowed;
658
659                 if (state->dhnc->data.length != 16) {
660                         return NT_STATUS_INVALID_PARAMETER;
661                 }
662
663                 /*
664                  * According to MS-SMB2: 3.3.5.9.7, "Handling the
665                  * SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context",
666                  * we should ignore an additional dhnq blob, but fail
667                  * the request (with status OBJECT_NAME_NOT_FOUND) if
668                  * any other extra create blob has been provided.
669                  *
670                  * (Note that the cases of an additional dh2q or dh2c blob
671                  *  which require a different error code, have been treated
672                  *  above.)
673                  */
674
675                 if (state->dhnq != NULL) {
676                         num_blobs_allowed = 2;
677                 } else {
678                         num_blobs_allowed = 1;
679                 }
680
681                 if (state->rqls != NULL) {
682                         num_blobs_allowed += 1;
683                 }
684
685                 if (in_context_blobs->num_blobs != num_blobs_allowed) {
686                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
687                 }
688         }
689
690         if (state->dh2c!= NULL) {
691                 uint32_t num_blobs_allowed;
692
693                 if (state->dh2c->data.length != 36) {
694                         return NT_STATUS_INVALID_PARAMETER;
695                 }
696
697                 /*
698                  * According to MS-SMB2: 3.3.5.9.12, "Handling the
699                  * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context",
700                  * we should fail the request with status
701                  * OBJECT_NAME_NOT_FOUND if any other create blob has been
702                  * provided.
703                  *
704                  * (Note that the cases of an additional dhnq, dhnc or dh2q
705                  *  blob which require a different error code, have been
706                  *  treated above.)
707                  */
708
709                 num_blobs_allowed = 1;
710
711                 if (state->rqls != NULL) {
712                         num_blobs_allowed += 1;
713                 }
714
715                 if (in_context_blobs->num_blobs != num_blobs_allowed) {
716                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
717                 }
718         }
719
720         state->exta = smb2_create_blob_find(in_context_blobs,
721                                             SMB2_CREATE_TAG_EXTA);
722         state->mxac = smb2_create_blob_find(in_context_blobs,
723                                             SMB2_CREATE_TAG_MXAC);
724         state->secd = smb2_create_blob_find(in_context_blobs,
725                                             SMB2_CREATE_TAG_SECD);
726         state->alsi = smb2_create_blob_find(in_context_blobs,
727                                             SMB2_CREATE_TAG_ALSI);
728         state->twrp = smb2_create_blob_find(in_context_blobs,
729                                             SMB2_CREATE_TAG_TWRP);
730         state->qfid = smb2_create_blob_find(in_context_blobs,
731                                             SMB2_CREATE_TAG_QFID);
732         if (xconn->protocol >= PROTOCOL_SMB3_02) {
733                 /*
734                  * This was introduced with SMB3_02
735                  */
736                 state->svhdx = smb2_create_blob_find(
737                         in_context_blobs, SVHDX_OPEN_DEVICE_CONTEXT);
738         }
739         if (xconn->smb2.server.posix_extensions_negotiated &&
740             lp_smb3_unix_extensions(SNUM(state->smb1req->conn)))
741         {
742                 /*
743                  * Negprot only allowed this for proto>=3.11
744                  */
745                 SMB_ASSERT(xconn->protocol >= PROTOCOL_SMB3_11);
746
747                 state->posx = smb2_create_blob_find(
748                         in_context_blobs, SMB2_CREATE_TAG_POSIX);
749                 /*
750                  * Setting the bool below will cause
751                  * ucf_flags_from_smb_request() to
752                  * return UCF_POSIX_PATHNAMES in ucf_flags.
753                  */
754                 state->smb1req->posix_pathnames = (state->posx != NULL);
755         }
756
757         return NT_STATUS_OK;
758 }
759
760 static void smbd_smb2_create_before_exec(struct tevent_req *req);
761 static void smbd_smb2_create_after_exec(struct tevent_req *req);
762 static void smbd_smb2_create_finish(struct tevent_req *req);
763
764 static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
765                         struct tevent_context *ev,
766                         struct smbd_smb2_request *smb2req,
767                         uint8_t in_oplock_level,
768                         uint32_t in_impersonation_level,
769                         uint32_t in_desired_access,
770                         uint32_t in_file_attributes,
771                         uint32_t in_share_access,
772                         uint32_t in_create_disposition,
773                         uint32_t _in_create_options,
774                         const char *in_name,
775                         struct smb2_create_blobs in_context_blobs)
776 {
777         struct tevent_req *req = NULL;
778         struct smbd_smb2_create_state *state = NULL;
779         NTSTATUS status;
780         struct smb_request *smb1req = NULL;
781         struct files_struct *dirfsp = NULL;
782         struct smb_filename *smb_fname = NULL;
783         uint32_t ucf_flags;
784         bool is_dfs = false;
785         bool is_posix = false;
786
787         req = tevent_req_create(mem_ctx, &state,
788                                 struct smbd_smb2_create_state);
789         if (req == NULL) {
790                 return NULL;
791         }
792         *state = (struct smbd_smb2_create_state) {
793                 .ev = ev,
794                 .smb2req = smb2req,
795                 .in_oplock_level = in_oplock_level,
796                 .in_create_disposition = in_create_disposition,
797                 .in_create_options = _in_create_options,
798         };
799
800         smb1req = smbd_smb2_fake_smb_request(smb2req, NULL);
801         if (tevent_req_nomem(smb1req, req)) {
802                 return tevent_req_post(req, state->ev);
803         }
804         state->smb1req = smb1req;
805
806         state->req_guid = smbd_request_guid(smb1req, 0);
807
808         tevent_req_set_cleanup_fn(req, smbd_smb2_create_cleanup);
809
810         if (smb2req->subreq == NULL) {
811                 DBG_DEBUG("name [%s]\n", in_name);
812         } else {
813                 struct smbd_smb2_create_state *old_state = tevent_req_data(
814                         smb2req->subreq, struct smbd_smb2_create_state);
815
816                 DBG_DEBUG("reentrant for file %s\n", in_name);
817
818                 state->id = old_state->id;
819                 state->request_time = old_state->request_time;
820                 state->open_rec = talloc_move(state, &old_state->open_rec);
821                 state->open_was_deferred = old_state->open_was_deferred;
822                 state->_purge_create_guid = old_state->_purge_create_guid;
823                 state->purge_create_guid = old_state->purge_create_guid;
824                 old_state->purge_create_guid = NULL;
825         }
826
827         TALLOC_FREE(smb2req->subreq);
828         smb2req->subreq = req;
829
830         if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
831                 state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
832         } else {
833                 state->requested_oplock_level = state->in_oplock_level;
834         }
835
836         /* these are ignored for SMB2 */
837         state->in_create_options &= ~(0x10); /* NTCREATEX_OPTIONS_SYNC_ALERT */
838         state->in_create_options &= ~(0x20); /* NTCREATEX_OPTIONS_ASYNC_ALERT */
839
840         in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
841
842         is_dfs = (smb1req->flags2 & FLAGS2_DFS_PATHNAMES);
843         if (is_dfs) {
844                 const char *non_dfs_in_name = NULL;
845                 /*
846                  * With a DFS flag set, remove any DFS prefix
847                  * before further processing.
848                  */
849                 status = smb2_strip_dfs_path(in_name, &non_dfs_in_name);
850                 if (!NT_STATUS_IS_OK(status)) {
851                         tevent_req_nterror(req, status);
852                         return tevent_req_post(req, state->ev);
853                 }
854                 /*
855                  * TODO: Note for dealing with reparse point errors.
856                  * We will need to remember and store the number of characters
857                  * we have removed here, which is (non_dfs_in_name - in_name)
858                  * in order to correctly report how many characters we
859                  * have removed before hitting the reparse point.
860                  * This will be a patch needed once we properly
861                  * deal with reparse points later.
862                  */
863                 in_name = non_dfs_in_name;
864                 /*
865                  * Now we're no longer dealing with a DFS path, so
866                  * remove the flag.
867                  */
868                 smb1req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
869                 is_dfs = false;
870         }
871
872         state->fname = talloc_strdup(state, in_name);
873         if (tevent_req_nomem(state->fname, req)) {
874                 return tevent_req_post(req, state->ev);
875         }
876
877         state->out_context_blobs = talloc_zero(state, struct smb2_create_blobs);
878         if (tevent_req_nomem(state->out_context_blobs, req)) {
879                 return tevent_req_post(req, state->ev);
880         }
881
882         status = smbd_smb2_create_fetch_create_ctx(req, &in_context_blobs);
883         if (tevent_req_nterror(req, status)) {
884                 return tevent_req_post(req, state->ev);
885         }
886
887         if (IS_IPC(smb1req->conn)) {
888                 const char *pipe_name = in_name;
889
890                 if (state->dhnc != NULL || state->dh2c != NULL) {
891                         /* durable handles are not supported on IPC$ */
892                         tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
893                         return tevent_req_post(req, state->ev);
894                 }
895
896                 if (!lp_nt_pipe_support()) {
897                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
898                         return tevent_req_post(req, state->ev);
899                 }
900
901                 status = open_np_file(smb1req, pipe_name, &state->result);
902                 if (tevent_req_nterror(req, status)) {
903                         return tevent_req_post(req, state->ev);
904                 }
905                 state->info = FILE_WAS_OPENED;
906
907                 smbd_smb2_create_finish(req);
908                 return req;
909         }
910
911         if (CAN_PRINT(smb1req->conn)) {
912                 if (state->dhnc != NULL || state->dh2c != NULL) {
913                         /* durable handles are not supported on printers */
914                         tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
915                         return tevent_req_post(req, state->ev);
916                 }
917
918                 status = file_new(smb1req, smb1req->conn, &state->result);
919                 if (tevent_req_nterror(req, status)) {
920                         return tevent_req_post(req, state->ev);
921                 }
922
923                 status = print_spool_open(state->result, in_name,
924                                           smb1req->vuid);
925                 if (tevent_req_nterror(req, status)) {
926                         file_free(smb1req, state->result);
927                         return tevent_req_post(req, state->ev);
928                 }
929                 state->info = FILE_WAS_CREATED;
930
931                 smbd_smb2_create_finish(req);
932                 return req;
933         }
934
935         /* Check for trailing slash specific directory handling. */
936         status = windows_name_trailing_check(state->fname,
937                                              state->in_create_options);
938         if (tevent_req_nterror(req, status)) {
939                 return tevent_req_post(req, state->ev);
940         }
941
942         smbd_smb2_create_before_exec(req);
943         if (!tevent_req_is_in_progress(req)) {
944                 return tevent_req_post(req, state->ev);
945         }
946
947         DBG_DEBUG("open execution phase\n");
948
949         /*
950          * For the backend file open procedure, there are
951          * three possible modes: replay operation (in which case
952          * there is nothing else to do), durable_reconnect or
953          * new open.
954          */
955         if (state->replay_operation) {
956                 state->result = state->op->compat;
957                 state->result->op = state->op;
958                 state->update_open = false;
959                 state->info = state->op->create_action;
960
961                 smbd_smb2_create_after_exec(req);
962                 if (!tevent_req_is_in_progress(req)) {
963                         return tevent_req_post(req, state->ev);
964                 }
965
966                 smbd_smb2_create_finish(req);
967                 return req;
968         }
969
970         if (state->do_durable_reconnect) {
971                 DATA_BLOB new_cookie = data_blob_null;
972                 NTTIME now = timeval_to_nttime(&smb2req->request_time);
973
974                 status = smb2srv_open_recreate(smb2req->xconn,
975                                                smb1req->conn->session_info,
976                                                state->persistent_id,
977                                                state->create_guid,
978                                                now,
979                                                &state->op);
980                 if (tevent_req_nterror(req, status)) {
981                         DBG_NOTICE("smb2srv_open_recreate failed: %s\n",
982                                    nt_errstr(status));
983                         return tevent_req_post(req, state->ev);
984                 }
985
986                 DBG_DEBUG("%s to recreate durable handle\n",
987                           state->op->global->durable ? "succeeded" : "failed");
988
989                 if (!state->op->global->durable) {
990                         talloc_free(state->op);
991                         tevent_req_nterror(req,
992                                            NT_STATUS_OBJECT_NAME_NOT_FOUND);
993                         return tevent_req_post(req, state->ev);
994                 }
995
996                 status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
997                                                    smb1req,
998                                                    state->op, /* smbXsrv_open input */
999                                                    state->op->global->backend_cookie,
1000                                                    state->op, /* TALLOC_CTX */
1001                                                    &state->result,
1002                                                    &new_cookie);
1003                 if (!NT_STATUS_IS_OK(status)) {
1004                         NTSTATUS return_status;
1005
1006                         return_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1007
1008                         DBG_NOTICE("durable_reconnect failed: %s => %s\n",
1009                                    nt_errstr(status),
1010                                    nt_errstr(return_status));
1011
1012                         tevent_req_nterror(req, return_status);
1013                         return tevent_req_post(req, state->ev);
1014                 }
1015
1016                 DBG_DEBUG("oplock_type=%u, lease_ptr==%p\n",
1017                           (unsigned)state->result->oplock_type, state->lease_ptr);
1018
1019                 status = smbd_smb2_create_durable_lease_check(
1020                         smb1req, state->fname, state->result, state->lease_ptr);
1021                 if (tevent_req_nterror(req, status)) {
1022                         close_file_free(
1023                                 smb1req, &state->result, SHUTDOWN_CLOSE);
1024                         return tevent_req_post(req, state->ev);
1025                 }
1026
1027                 data_blob_free(&state->op->global->backend_cookie);
1028                 state->op->global->backend_cookie = new_cookie;
1029
1030                 state->op->status = NT_STATUS_OK;
1031                 state->op->global->disconnect_time = 0;
1032
1033                 /* save the timeout for later update */
1034                 state->durable_timeout_msec = state->op->global->durable_timeout_msec;
1035
1036                 state->update_open = true;
1037
1038                 state->info = FILE_WAS_OPENED;
1039
1040                 smbd_smb2_create_after_exec(req);
1041                 if (!tevent_req_is_in_progress(req)) {
1042                         return tevent_req_post(req, state->ev);
1043                 }
1044
1045                 smbd_smb2_create_finish(req);
1046                 return req;
1047         }
1048
1049         if (state->requested_oplock_level == SMB2_OPLOCK_LEVEL_LEASE) {
1050                 if (state->lease_ptr == NULL) {
1051                         state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1052                 }
1053         } else {
1054                 state->lease_ptr = NULL;
1055         }
1056
1057         is_posix = (state->posx != NULL);
1058
1059         /* convert '\\' into '/' */
1060         status = check_path_syntax(state->fname, is_posix);
1061         if (tevent_req_nterror(req, status)) {
1062                 return tevent_req_post(req, state->ev);
1063         }
1064
1065         ucf_flags = filename_create_ucf_flags(
1066                 smb1req, state->in_create_disposition);
1067
1068         status = filename_convert_dirfsp(
1069                 req,
1070                 smb1req->conn,
1071                 state->fname,
1072                 ucf_flags,
1073                 state->twrp_time,
1074                 &dirfsp,
1075                 &smb_fname);
1076         if (tevent_req_nterror(req, status)) {
1077                 return tevent_req_post(req, state->ev);
1078         }
1079
1080         /*
1081          * MS-SMB2: 2.2.13 SMB2 CREATE Request
1082          * ImpersonationLevel ... MUST contain one of the
1083          * following values. The server MUST validate this
1084          * field, but otherwise ignore it.
1085          *
1086          * NB. The source4/torture/smb2/durable_open.c test
1087          * shows this check is only done on real opens, not
1088          * on durable handle-reopens.
1089          */
1090
1091         if (in_impersonation_level >
1092             SMB2_IMPERSONATION_DELEGATE) {
1093                 tevent_req_nterror(req,
1094                                    NT_STATUS_BAD_IMPERSONATION_LEVEL);
1095                 return tevent_req_post(req, state->ev);
1096         }
1097
1098         /*
1099          * We know we're going to do a local open, so now
1100          * we must be protocol strict. JRA.
1101          *
1102          * MS-SMB2: 3.3.5.9 - Receiving an SMB2 CREATE Request
1103          * If the file name length is greater than zero and the
1104          * first character is a path separator character, the
1105          * server MUST fail the request with
1106          * STATUS_INVALID_PARAMETER.
1107          */
1108         if (in_name[0] == '/') {
1109                 /* Names starting with '/' are never allowed. */
1110                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1111                 return tevent_req_post(req, ev);
1112         }
1113         if (!is_posix && (in_name[0] == '\\')) {
1114                 /*
1115                  * Windows names starting with '\' are not allowed.
1116                  */
1117                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1118                 return tevent_req_post(req, ev);
1119         }
1120
1121         status = SMB_VFS_CREATE_FILE(smb1req->conn,
1122                                      smb1req,
1123                                      dirfsp,
1124                                      smb_fname,
1125                                      in_desired_access,
1126                                      in_share_access,
1127                                      state->in_create_disposition,
1128                                      state->in_create_options,
1129                                      in_file_attributes,
1130                                      map_smb2_oplock_levels_to_samba(
1131                                              state->requested_oplock_level),
1132                                      state->lease_ptr,
1133                                      state->allocation_size,
1134                                      0, /* private_flags */
1135                                      state->sec_desc,
1136                                      state->ea_list,
1137                                      &state->result,
1138                                      &state->info,
1139                                      &in_context_blobs,
1140                                      state->out_context_blobs);
1141         if (NT_STATUS_IS_OK(status) &&
1142             !(state->in_create_options & FILE_OPEN_REPARSE_POINT))
1143         {
1144
1145                 mode_t mode = state->result->fsp_name->st.st_ex_mode;
1146
1147                 if (!(S_ISREG(mode) || S_ISDIR(mode))) {
1148                         /*
1149                          * Only open files and dirs without
1150                          * FILE_OPEN_REPARSE_POINT
1151                          */
1152                         close_file_free(smb1req, &state->result, ERROR_CLOSE);
1153                         status = NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED;
1154                 }
1155         }
1156         if (!NT_STATUS_IS_OK(status)) {
1157                 if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
1158                         SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
1159                         return req;
1160                 }
1161                 tevent_req_nterror(req, status);
1162                 return tevent_req_post(req, state->ev);
1163         }
1164         state->op = state->result->op;
1165
1166         smbd_smb2_create_after_exec(req);
1167         if (!tevent_req_is_in_progress(req)) {
1168                 return tevent_req_post(req, state->ev);
1169         }
1170
1171         smbd_smb2_create_finish(req);
1172         return req;
1173 }
1174
1175 static void smbd_smb2_create_purge_replay_cache(struct tevent_req *req,
1176                                                 const char *caller_func)
1177 {
1178         struct smbd_smb2_create_state *state = tevent_req_data(
1179                 req, struct smbd_smb2_create_state);
1180         NTSTATUS status;
1181
1182         if (state->purge_create_guid == NULL) {
1183                 return;
1184         }
1185
1186         status = smbXsrv_open_purge_replay_cache(state->smb2req->xconn->client,
1187                                                  state->purge_create_guid);
1188         if (!NT_STATUS_IS_OK(status)) {
1189                 struct GUID_txt_buf buf;
1190
1191                 D_ERR("%s: smbXsrv_open_purge_replay_cache(%s) %s\n",
1192                       caller_func,
1193                       GUID_buf_string(state->purge_create_guid, &buf),
1194                       nt_errstr(status));
1195         }
1196
1197         state->purge_create_guid = NULL;
1198 }
1199
1200 static void smbd_smb2_create_before_exec(struct tevent_req *req)
1201 {
1202         struct smbd_smb2_create_state *state = tevent_req_data(
1203                 req, struct smbd_smb2_create_state);
1204         struct smbd_smb2_request *smb2req = state->smb2req;
1205         NTSTATUS status;
1206
1207         if (state->exta != NULL) {
1208                 if (!lp_ea_support(SNUM(smb2req->tcon->compat))) {
1209                         tevent_req_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1210                         return;
1211                 }
1212
1213                 state->ea_list = read_nttrans_ea_list(
1214                         state,
1215                         (const char *)state->exta->data.data,
1216                         state->exta->data.length);
1217                 if (state->ea_list == NULL) {
1218                         DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
1219                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1220                         return;
1221                 }
1222
1223                 if ((state->posx == NULL) &&
1224                     ea_list_has_invalid_name(state->ea_list)) {
1225                         tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
1226                         return;
1227                 }
1228         }
1229
1230         if (state->mxac != NULL) {
1231                 if (state->mxac->data.length == 0) {
1232                         state->max_access_time = 0;
1233                 } else if (state->mxac->data.length == 8) {
1234                         state->max_access_time = BVAL(state->mxac->data.data, 0);
1235                 } else {
1236                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1237                         return;
1238                 }
1239         }
1240
1241         if (state->secd != NULL) {
1242                 enum ndr_err_code ndr_err;
1243
1244                 state->sec_desc = talloc_zero(state, struct security_descriptor);
1245                 if (tevent_req_nomem(state->sec_desc, req)) {
1246                         return;
1247                 }
1248
1249                 ndr_err = ndr_pull_struct_blob(&state->secd->data,
1250                                                state->sec_desc, state->sec_desc,
1251                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1252                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1253                         DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
1254                                  ndr_errstr(ndr_err)));
1255                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1256                         return;
1257                 }
1258         }
1259
1260         if (state->dhnq != NULL) {
1261                 if (state->dhnq->data.length != 16) {
1262                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1263                         return;
1264                 }
1265
1266                 if (state->dh2q != NULL) {
1267                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1268                         return;
1269                 }
1270
1271                 /*
1272                  * durable handle request is processed below.
1273                  */
1274                 state->durable_requested = true;
1275                 /*
1276                  * Set the timeout to 16 mins.
1277                  *
1278                  * TODO: test this against Windows 2012
1279                  *       as the default for durable v2 is 1 min.
1280                  */
1281                 state->durable_timeout_msec = (16*60*1000);
1282         }
1283
1284         if (state->dh2q != NULL) {
1285                 const uint8_t *p = state->dh2q->data.data;
1286                 NTTIME now = timeval_to_nttime(&smb2req->request_time);
1287                 uint32_t durable_v2_timeout = 0;
1288                 DATA_BLOB create_guid_blob;
1289                 const uint8_t *hdr;
1290                 uint32_t flags;
1291
1292                 if (state->dh2q->data.length != 32) {
1293                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1294                         return;
1295                 }
1296
1297                 if (state->dhnq != NULL) {
1298                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1299                         return;
1300                 }
1301
1302                 durable_v2_timeout = IVAL(p, 0);
1303                 create_guid_blob = data_blob_const(p + 16, 16);
1304
1305                 status = GUID_from_ndr_blob(&create_guid_blob,
1306                                             &state->_create_guid);
1307                 if (tevent_req_nterror(req, status)) {
1308                         return;
1309                 }
1310                 state->create_guid = &state->_create_guid;
1311
1312                 /*
1313                  * we need to store the create_guid later
1314                  */
1315                 state->update_open = true;
1316
1317                 /*
1318                  * And we need to create a cache for replaying the
1319                  * create.
1320                  */
1321                 state->need_replay_cache = true;
1322
1323                 /*
1324                  * durable handle v2 request processed below
1325                  */
1326                 state->durable_requested = true;
1327                 state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
1328                 if (state->durable_timeout_msec == 0) {
1329                         /*
1330                          * Set the timeout to 1 min as default.
1331                          *
1332                          * This matches Windows 2012.
1333                          */
1334                         state->durable_timeout_msec = (60*1000);
1335                 }
1336
1337                 /*
1338                  * Check for replay operation.
1339                  * Only consider it when we have dh2q.
1340                  * If we do not have a replay operation, verify that
1341                  * the create_guid is not cached for replay.
1342                  */
1343                 hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
1344                 flags = IVAL(hdr, SMB2_HDR_FLAGS);
1345                 state->replay_operation =
1346                         flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
1347
1348                 status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
1349                                                           state->req_guid,
1350                                                           *state->create_guid,
1351                                                           state->fname,
1352                                                           now,
1353                                                           &state->op);
1354                 if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
1355                         /*
1356                          * We've reserved the replay_cache record
1357                          * for ourself, indicating we're still
1358                          * in progress.
1359                          *
1360                          * It means the smbd_smb2_create_cleanup()
1361                          * may need to call smbXsrv_open_purge_replay_cache()
1362                          * in order to cleanup.
1363                          */
1364                         SMB_ASSERT(state->op == NULL);
1365                         state->_purge_create_guid = state->_create_guid;
1366                         state->purge_create_guid = &state->_purge_create_guid;
1367                         status = NT_STATUS_OK;
1368                         state->replay_operation = false;
1369                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
1370                         tevent_req_nterror(req, status);
1371                         return;
1372                 } else if (tevent_req_nterror(req, status)) {
1373                         DBG_WARNING("smb2srv_open_lookup_replay_cache "
1374                                     "failed: %s\n", nt_errstr(status));
1375                         return;
1376                 } else if (!state->replay_operation) {
1377                         /*
1378                          * If a create without replay operation flag
1379                          * is sent but with a create_guid that is
1380                          * currently in the replay cache -- fail.
1381                          */
1382                         status = NT_STATUS_DUPLICATE_OBJECTID;
1383                         (void)tevent_req_nterror(req, status);
1384                         return;
1385                 }
1386         }
1387
1388         if (state->dhnc != NULL) {
1389                 state->persistent_id = BVAL(state->dhnc->data.data, 0);
1390                 state->do_durable_reconnect = true;
1391         }
1392
1393         if (state->dh2c != NULL) {
1394                 const uint8_t *p = state->dh2c->data.data;
1395                 DATA_BLOB create_guid_blob;
1396
1397                 state->persistent_id = BVAL(p, 0);
1398                 create_guid_blob = data_blob_const(p + 16, 16);
1399
1400                 status = GUID_from_ndr_blob(&create_guid_blob,
1401                                             &state->_create_guid);
1402                 if (tevent_req_nterror(req, status)) {
1403                         return;
1404                 }
1405
1406                 state->create_guid = &state->_create_guid;
1407                 state->do_durable_reconnect = true;
1408         }
1409
1410         if (state->alsi != NULL) {
1411                 if (state->alsi->data.length != 8) {
1412                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1413                         return;
1414                 }
1415                 state->allocation_size = BVAL(state->alsi->data.data, 0);
1416         }
1417
1418         if (state->twrp != NULL) {
1419                 if (state->twrp->data.length != 8) {
1420                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1421                         return;
1422                 }
1423
1424                 state->twrp_time = BVAL(state->twrp->data.data, 0);
1425         }
1426
1427         if (state->qfid != NULL) {
1428                 if (state->qfid->data.length != 0) {
1429                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1430                         return;
1431                 }
1432         }
1433
1434         if (state->rqls != NULL) {
1435                 ssize_t lease_len = -1;
1436
1437                 lease_len = smb2_lease_pull(state->rqls->data.data,
1438                                             state->rqls->data.length,
1439                                             &state->lease);
1440                 if (lease_len == -1) {
1441                         tevent_req_nterror(
1442                                 req, NT_STATUS_INVALID_PARAMETER);
1443                         return;
1444                 }
1445                 state->lease_ptr = &state->lease;
1446
1447                 if (DEBUGLEVEL >= 10) {
1448                         DEBUG(10, ("Got lease request size %d\n",
1449                                    (int)lease_len));
1450                         NDR_PRINT_DEBUG(smb2_lease, state->lease_ptr);
1451                 }
1452
1453                 if (!smb2_lease_key_valid(&state->lease.lease_key)) {
1454                         state->lease_ptr = NULL;
1455                         state->requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
1456                 }
1457
1458                 if ((smb2req->xconn->protocol < PROTOCOL_SMB3_00) &&
1459                     (state->lease.lease_version != 1))
1460                 {
1461                         DEBUG(10, ("v2 lease key only for SMB3\n"));
1462                         state->lease_ptr = NULL;
1463                 }
1464
1465                 /*
1466                  * Replay with a lease is only allowed if the
1467                  * established open carries a lease with the
1468                  * same lease key.
1469                  */
1470                 if (state->replay_operation) {
1471                         struct smb2_lease *op_ls =
1472                                 &state->op->compat->lease->lease;
1473                         int op_oplock = state->op->compat->oplock_type;
1474
1475                         if (map_samba_oplock_levels_to_smb2(op_oplock)
1476                             != SMB2_OPLOCK_LEVEL_LEASE)
1477                         {
1478                                 status = NT_STATUS_ACCESS_DENIED;
1479                                 (void)tevent_req_nterror(req, status);
1480                                 return;
1481                         }
1482                         if (!smb2_lease_key_equal(&state->lease.lease_key,
1483                                                   &op_ls->lease_key))
1484                         {
1485                                 status = NT_STATUS_ACCESS_DENIED;
1486                                 (void)tevent_req_nterror(req, status);
1487                                 return;
1488                         }
1489                 }
1490         }
1491
1492         if (state->posx != NULL) {
1493                 if (state->posx->data.length != 4) {
1494                         DBG_DEBUG("Got %zu bytes POSX cctx, expected 4\n",
1495                                   state->posx->data.length);
1496                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1497                         return;
1498                 }
1499         }
1500 }
1501
1502 static void smbd_smb2_create_after_exec(struct tevent_req *req)
1503 {
1504         struct smbd_smb2_create_state *state = tevent_req_data(
1505                 req, struct smbd_smb2_create_state);
1506         connection_struct *conn = state->result->conn;
1507         NTSTATUS status;
1508
1509         /*
1510          * here we have op == result->op
1511          */
1512
1513         DBG_DEBUG("response construction phase\n");
1514
1515         state->out_file_attributes = fdos_mode(state->result);
1516
1517         if (state->mxac != NULL) {
1518                 NTTIME last_write_time;
1519
1520                 last_write_time = full_timespec_to_nt_time(
1521                         &state->result->fsp_name->st.st_ex_mtime);
1522                 if (last_write_time != state->max_access_time) {
1523                         uint8_t p[8];
1524                         uint32_t max_access_granted;
1525                         DATA_BLOB blob = data_blob_const(p, sizeof(p));
1526
1527                         status = smbd_calculate_access_mask_fsp(
1528                                         conn->cwd_fsp,
1529                                         state->result,
1530                                         false,
1531                                         SEC_FLAG_MAXIMUM_ALLOWED,
1532                                         &max_access_granted);
1533
1534                         SIVAL(p, 0, NT_STATUS_V(status));
1535                         SIVAL(p, 4, max_access_granted);
1536
1537                         status = smb2_create_blob_add(
1538                                 state->out_context_blobs,
1539                                 state->out_context_blobs,
1540                                 SMB2_CREATE_TAG_MXAC,
1541                                 blob);
1542                         if (!NT_STATUS_IS_OK(status)) {
1543                                 goto fail;
1544                         }
1545                 }
1546         }
1547
1548         if (!state->replay_operation && state->durable_requested &&
1549             (fsp_lease_type(state->result) & SMB2_LEASE_HANDLE))
1550         {
1551                 status = SMB_VFS_DURABLE_COOKIE(
1552                         state->result,
1553                         state->op,
1554                         &state->op->global->backend_cookie);
1555                 if (!NT_STATUS_IS_OK(status)) {
1556                         state->op->global->backend_cookie = data_blob_null;
1557                 }
1558         }
1559         if (!state->replay_operation && state->op->global->backend_cookie.length > 0)
1560         {
1561                 state->update_open = true;
1562
1563                 state->op->global->durable = true;
1564                 state->op->global->durable_timeout_msec = state->durable_timeout_msec;
1565         }
1566
1567         if (state->update_open) {
1568                 state->op->global->create_guid = state->_create_guid;
1569                 if (state->need_replay_cache) {
1570                         state->op->flags |= SMBXSRV_OPEN_NEED_REPLAY_CACHE;
1571                 }
1572
1573                 status = smbXsrv_open_update(state->op);
1574                 DEBUG(10, ("smb2_create_send: smbXsrv_open_update "
1575                            "returned %s\n",
1576                            nt_errstr(status)));
1577                 if (!NT_STATUS_IS_OK(status)) {
1578                         goto fail;
1579                 }
1580
1581                 /*
1582                  * We should not purge the replay cache anymore
1583                  * as it's attached to the smbXsrv_open record now.
1584                  */
1585                 state->purge_create_guid = NULL;
1586         }
1587
1588         if (state->dhnq != NULL && state->op->global->durable) {
1589                 uint8_t p[8] = { 0, };
1590                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1591
1592                 status = smb2_create_blob_add(state->out_context_blobs,
1593                                               state->out_context_blobs,
1594                                               SMB2_CREATE_TAG_DHNQ,
1595                                               blob);
1596                 if (!NT_STATUS_IS_OK(status)) {
1597                         goto fail;
1598                 }
1599         }
1600
1601         if (state->dh2q != NULL && state->op->global->durable &&
1602             /*
1603              * For replay operations, we return the dh2q blob
1604              * in the case of oplocks not based on the state of
1605              * the open, but on whether it could have been granted
1606              * for the request data. In the case of leases instead,
1607              * the state of the open is used...
1608              */
1609             (!state->replay_operation ||
1610              state->in_oplock_level == SMB2_OPLOCK_LEVEL_BATCH ||
1611              state->in_oplock_level == SMB2_OPLOCK_LEVEL_LEASE))
1612         {
1613                 uint8_t p[8] = { 0, };
1614                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1615                 uint32_t durable_v2_response_flags = 0;
1616
1617                 SIVAL(p, 0, state->op->global->durable_timeout_msec);
1618                 SIVAL(p, 4, durable_v2_response_flags);
1619
1620                 status = smb2_create_blob_add(state->out_context_blobs,
1621                                               state->out_context_blobs,
1622                                               SMB2_CREATE_TAG_DH2Q,
1623                                               blob);
1624                 if (!NT_STATUS_IS_OK(status)) {
1625                         goto fail;
1626                 }
1627         }
1628
1629         if (state->qfid != NULL) {
1630                 uint8_t p[32];
1631                 SMB_STRUCT_STAT *base_sp = state->result->base_fsp ?
1632                         &state->result->base_fsp->fsp_name->st :
1633                         &state->result->fsp_name->st;
1634                 uint64_t file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
1635                 DATA_BLOB blob = data_blob_const(p, sizeof(p));
1636
1637                 ZERO_STRUCT(p);
1638
1639                 /* From conversations with Microsoft engineers at
1640                    the MS plugfest. The first 8 bytes are the "volume index"
1641                    == inode, the second 8 bytes are the "volume id",
1642                    == dev. This will be updated in the SMB2 doc. */
1643                 SBVAL(p, 0, file_id);
1644                 SIVAL(p, 8, base_sp->st_ex_dev);/* FileIndexHigh */
1645
1646                 status = smb2_create_blob_add(state->out_context_blobs,
1647                                               state->out_context_blobs,
1648                                               SMB2_CREATE_TAG_QFID,
1649                                               blob);
1650                 if (!NT_STATUS_IS_OK(status)) {
1651                         goto fail;
1652                 }
1653         }
1654
1655         if ((state->rqls != NULL) && (state->result->oplock_type == LEASE_OPLOCK)) {
1656                 uint8_t buf[52];
1657                 struct smb2_lease lease;
1658                 size_t lease_len;
1659
1660                 lease = state->result->lease->lease;
1661
1662                 lease_len = sizeof(buf);
1663                 if (lease.lease_version == 1) {
1664                         lease_len = 32;
1665                 }
1666
1667                 if (!smb2_lease_push(&lease, buf, lease_len)) {
1668                         status = NT_STATUS_INTERNAL_ERROR;
1669                         goto fail;
1670                 }
1671
1672                 status = smb2_create_blob_add(
1673                         state, state->out_context_blobs,
1674                         SMB2_CREATE_TAG_RQLS,
1675                         data_blob_const(buf, lease_len));
1676                 if (!NT_STATUS_IS_OK(status)) {
1677                         goto fail;
1678                 }
1679         }
1680
1681         if (state->posx != NULL) {
1682                 struct stat_ex *psbuf = &state->result->fsp_name->st;
1683                 struct smb3_posix_cc_info cc = {
1684                         .nlinks = psbuf->st_ex_nlink,
1685                         .posix_perms = unix_perms_to_wire(psbuf->st_ex_mode &
1686                                                           ~S_IFMT),
1687                 };
1688                 uint8_t buf[sizeof(struct smb3_posix_cc_info)];
1689                 struct ndr_push ndr = {
1690                         .data = buf,
1691                         .alloc_size = sizeof(buf),
1692                         .fixed_buf_size = true,
1693                 };
1694                 enum ndr_err_code ndr_err;
1695
1696                 uid_to_sid(&cc.owner, psbuf->st_ex_uid);
1697                 gid_to_sid(&cc.group, psbuf->st_ex_gid);
1698
1699                 ndr_err =
1700                         ndr_push_smb3_posix_cc_info(&ndr,
1701                                                     NDR_SCALARS | NDR_BUFFERS,
1702                                                     &cc);
1703                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1704                         status = NT_STATUS_INSUFFICIENT_RESOURCES;
1705                         goto fail;
1706                 }
1707
1708                 status = smb2_create_blob_add(state->out_context_blobs,
1709                                               state->out_context_blobs,
1710                                               SMB2_CREATE_TAG_POSIX,
1711                                               (DATA_BLOB){
1712                                                       .data = buf,
1713                                                       .length = ndr.offset,
1714                                               });
1715                 if (!NT_STATUS_IS_OK(status)) {
1716                         goto fail;
1717                 }
1718         }
1719
1720         return;
1721
1722 fail:
1723         close_file_free(state->smb1req, &state->result, ERROR_CLOSE);
1724         tevent_req_nterror(req, status);
1725 }
1726
1727 static void smbd_smb2_create_finish(struct tevent_req *req)
1728 {
1729         struct smbd_smb2_create_state *state = tevent_req_data(
1730                 req, struct smbd_smb2_create_state);
1731         struct smbd_smb2_request *smb2req = state->smb2req;
1732         struct smb_request *smb1req = state->smb1req;
1733         files_struct *result = state->result;
1734
1735         smb2req->compat_chain_fsp = smb1req->chain_fsp;
1736
1737         if (state->replay_operation) {
1738                 state->out_oplock_level = state->in_oplock_level;
1739         } else if (lp_fake_oplocks(SNUM(smb2req->tcon->compat))) {
1740                 state->out_oplock_level = state->in_oplock_level;
1741         } else {
1742                 state->out_oplock_level = map_samba_oplock_levels_to_smb2(result->oplock_type);
1743         }
1744
1745         if ((state->in_create_disposition == FILE_SUPERSEDE)
1746             && (state->info == FILE_WAS_OVERWRITTEN)) {
1747                 state->out_create_action = FILE_WAS_SUPERSEDED;
1748         } else {
1749                 state->out_create_action = state->info;
1750         }
1751         result->op->create_action = state->out_create_action;
1752
1753         state->out_creation_ts = get_create_timespec(smb1req->conn,
1754                                         result, result->fsp_name);
1755         state->out_last_access_ts = result->fsp_name->st.st_ex_atime;
1756         state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
1757         state->out_change_ts = get_change_timespec(smb1req->conn,
1758                                         result, result->fsp_name);
1759
1760         if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
1761                 dos_filetime_timespec(&state->out_creation_ts);
1762                 dos_filetime_timespec(&state->out_last_access_ts);
1763                 dos_filetime_timespec(&state->out_last_write_ts);
1764                 dos_filetime_timespec(&state->out_change_ts);
1765         }
1766
1767         state->out_allocation_size =
1768                         SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
1769                                                &(result->fsp_name->st));
1770         state->out_end_of_file = result->fsp_name->st.st_ex_size;
1771         if (state->out_file_attributes == 0) {
1772                 state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
1773         }
1774         state->out_file_id_persistent = result->op->global->open_persistent_id;
1775         state->out_file_id_volatile = result->op->global->open_volatile_id;
1776
1777         DBG_DEBUG("%s - %s\n", fsp_str_dbg(result), fsp_fnum_dbg(result));
1778
1779         tevent_req_done(req);
1780         tevent_req_post(req, state->ev);
1781 }
1782
1783 static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
1784                         TALLOC_CTX *mem_ctx,
1785                         uint8_t *out_oplock_level,
1786                         uint32_t *out_create_action,
1787                         struct timespec *out_creation_ts,
1788                         struct timespec *out_last_access_ts,
1789                         struct timespec *out_last_write_ts,
1790                         struct timespec *out_change_ts,
1791                         uint64_t *out_allocation_size,
1792                         uint64_t *out_end_of_file,
1793                         uint32_t *out_file_attributes,
1794                         uint64_t *out_file_id_persistent,
1795                         uint64_t *out_file_id_volatile,
1796                         struct smb2_create_blobs *out_context_blobs)
1797 {
1798         NTSTATUS status;
1799         struct smbd_smb2_create_state *state = tevent_req_data(req,
1800                                                struct smbd_smb2_create_state);
1801
1802         if (tevent_req_is_nterror(req, &status)) {
1803                 tevent_req_received(req);
1804                 return status;
1805         }
1806
1807         *out_oplock_level       = state->out_oplock_level;
1808         *out_create_action      = state->out_create_action;
1809         *out_creation_ts        = state->out_creation_ts;
1810         *out_last_access_ts     = state->out_last_access_ts;
1811         *out_last_write_ts      = state->out_last_write_ts;
1812         *out_change_ts          = state->out_change_ts;
1813         *out_allocation_size    = state->out_allocation_size;
1814         *out_end_of_file        = state->out_end_of_file;
1815         *out_file_attributes    = state->out_file_attributes;
1816         *out_file_id_persistent = state->out_file_id_persistent;
1817         *out_file_id_volatile   = state->out_file_id_volatile;
1818         *out_context_blobs      = *(state->out_context_blobs);
1819
1820         talloc_steal(mem_ctx, state->out_context_blobs->blobs);
1821
1822         tevent_req_received(req);
1823         return NT_STATUS_OK;
1824 }
1825
1826 /*********************************************************
1827  Code for dealing with deferred opens.
1828 *********************************************************/
1829
1830 bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
1831                         struct timeval *p_request_time,
1832                         struct deferred_open_record **open_rec)
1833 {
1834         struct smbd_smb2_create_state *state = NULL;
1835         struct tevent_req *req = NULL;
1836
1837         if (!smb2req) {
1838                 return false;
1839         }
1840         req = smb2req->subreq;
1841         if (!req) {
1842                 return false;
1843         }
1844         state = tevent_req_data(req, struct smbd_smb2_create_state);
1845         if (!state) {
1846                 return false;
1847         }
1848         if (!state->open_was_deferred) {
1849                 return false;
1850         }
1851         if (p_request_time) {
1852                 *p_request_time = state->request_time;
1853         }
1854         if (open_rec != NULL) {
1855                 *open_rec = state->open_rec;
1856         }
1857         return true;
1858 }
1859
1860 /*********************************************************
1861  Re-process this call early - requested by message or
1862  close.
1863 *********************************************************/
1864
1865 static struct smbd_smb2_request *find_open_smb2req(
1866         struct smbXsrv_connection *xconn, uint64_t mid)
1867 {
1868         struct smbd_smb2_request *smb2req;
1869
1870         for (smb2req = xconn->smb2.requests; smb2req; smb2req = smb2req->next) {
1871                 uint64_t message_id;
1872                 if (smb2req->subreq == NULL) {
1873                         /* This message has been processed. */
1874                         continue;
1875                 }
1876                 if (!tevent_req_is_in_progress(smb2req->subreq)) {
1877                         /* This message has been processed. */
1878                         continue;
1879                 }
1880                 message_id = get_mid_from_smb2req(smb2req);
1881                 if (message_id == mid) {
1882                         return smb2req;
1883                 }
1884         }
1885         return NULL;
1886 }
1887
1888 bool open_was_deferred_smb2(struct smbXsrv_connection *xconn, uint64_t mid)
1889 {
1890         struct smbd_smb2_create_state *state = NULL;
1891         struct smbd_smb2_request *smb2req;
1892
1893         smb2req = find_open_smb2req(xconn, mid);
1894
1895         if (!smb2req) {
1896                 DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
1897                         (unsigned long long)mid));
1898                 return false;
1899         }
1900         if (!smb2req->subreq) {
1901                 return false;
1902         }
1903         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1904                 return false;
1905         }
1906         state = tevent_req_data(smb2req->subreq,
1907                         struct smbd_smb2_create_state);
1908         if (!state) {
1909                 return false;
1910         }
1911         /* It's not in progress if there's no timeout event. */
1912         if (!state->open_was_deferred) {
1913                 return false;
1914         }
1915
1916         DEBUG(10,("open_was_deferred_smb2: mid = %llu\n",
1917                         (unsigned long long)mid));
1918
1919         return true;
1920 }
1921
1922 static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
1923                                                         uint64_t mid)
1924 {
1925         struct smbd_smb2_create_state *state = NULL;
1926
1927         if (!smb2req->subreq) {
1928                 return;
1929         }
1930         if (!tevent_req_is_in_progress(smb2req->subreq)) {
1931                 return;
1932         }
1933         state = tevent_req_data(smb2req->subreq,
1934                         struct smbd_smb2_create_state);
1935         if (!state) {
1936                 return;
1937         }
1938
1939         DEBUG(10,("remove_deferred_open_message_smb2_internal: "
1940                 "mid %llu\n",
1941                 (unsigned long long)mid ));
1942
1943         state->open_was_deferred = false;
1944         /* Ensure we don't have any outstanding immediate event. */
1945         TALLOC_FREE(state->im);
1946         TALLOC_FREE(state->open_rec);
1947 }
1948
1949 void remove_deferred_open_message_smb2(
1950         struct smbXsrv_connection *xconn, uint64_t mid)
1951 {
1952         struct smbd_smb2_request *smb2req;
1953
1954         smb2req = find_open_smb2req(xconn, mid);
1955
1956         if (!smb2req) {
1957                 DEBUG(10,("remove_deferred_open_message_smb2: "
1958                         "can't find mid %llu\n",
1959                         (unsigned long long)mid ));
1960                 return;
1961         }
1962         remove_deferred_open_message_smb2_internal(smb2req, mid);
1963 }
1964
1965 static void smbd_smb2_create_request_dispatch_immediate(struct tevent_context *ctx,
1966                                         struct tevent_immediate *im,
1967                                         void *private_data)
1968 {
1969         struct smbd_smb2_request *smb2req = talloc_get_type_abort(private_data,
1970                                         struct smbd_smb2_request);
1971         uint64_t mid = get_mid_from_smb2req(smb2req);
1972         NTSTATUS status;
1973
1974         DEBUG(10,("smbd_smb2_create_request_dispatch_immediate: "
1975                 "re-dispatching mid %llu\n",
1976                 (unsigned long long)mid ));
1977
1978         status = smbd_smb2_request_dispatch(smb2req);
1979         if (!NT_STATUS_IS_OK(status)) {
1980                 smbd_server_connection_terminate(smb2req->xconn,
1981                                                  nt_errstr(status));
1982                 return;
1983         }
1984 }
1985
1986 bool schedule_deferred_open_message_smb2(
1987         struct smbXsrv_connection *xconn, uint64_t mid)
1988 {
1989         struct smbd_smb2_create_state *state = NULL;
1990         struct smbd_smb2_request *smb2req;
1991
1992         smb2req = find_open_smb2req(xconn, mid);
1993
1994         if (!smb2req) {
1995                 DEBUG(10,("schedule_deferred_open_message_smb2: "
1996                         "can't find mid %llu\n",
1997                         (unsigned long long)mid ));
1998                 return false;
1999         }
2000         if (!smb2req->subreq) {
2001                 return false;
2002         }
2003         if (!tevent_req_is_in_progress(smb2req->subreq)) {
2004                 return false;
2005         }
2006         state = tevent_req_data(smb2req->subreq,
2007                         struct smbd_smb2_create_state);
2008         if (!state) {
2009                 return false;
2010         }
2011
2012         /* Ensure we don't have any outstanding immediate event. */
2013         TALLOC_FREE(state->im);
2014
2015         /*
2016          * This is subtle. We must null out the callback
2017          * before rescheduling, else the first call to
2018          * tevent_req_nterror() causes the _receive()
2019          * function to be called, this causing tevent_req_post()
2020          * to crash.
2021          */
2022         tevent_req_set_callback(smb2req->subreq, NULL, NULL);
2023
2024         state->im = tevent_create_immediate(smb2req);
2025         if (!state->im) {
2026                 smbd_server_connection_terminate(smb2req->xconn,
2027                         nt_errstr(NT_STATUS_NO_MEMORY));
2028                 return false;
2029         }
2030
2031         DEBUG(10,("schedule_deferred_open_message_smb2: "
2032                 "re-processing mid %llu\n",
2033                 (unsigned long long)mid ));
2034
2035         tevent_schedule_immediate(state->im,
2036                         smb2req->sconn->ev_ctx,
2037                         smbd_smb2_create_request_dispatch_immediate,
2038                         smb2req);
2039
2040         return true;
2041 }
2042
2043 static bool smbd_smb2_create_cancel(struct tevent_req *req)
2044 {
2045         struct smbd_smb2_request *smb2req = NULL;
2046         struct smbd_smb2_create_state *state = tevent_req_data(req,
2047                                 struct smbd_smb2_create_state);
2048         uint64_t mid;
2049
2050         if (!state) {
2051                 return false;
2052         }
2053
2054         if (!state->smb2req) {
2055                 return false;
2056         }
2057
2058         smb2req = state->smb2req;
2059         mid = get_mid_from_smb2req(smb2req);
2060
2061         if (is_deferred_open_async(state->open_rec)) {
2062                 /* Can't cancel an async create. */
2063                 return false;
2064         }
2065
2066         remove_deferred_open_message_smb2_internal(smb2req, mid);
2067
2068         tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
2069         tevent_req_nterror(req, NT_STATUS_CANCELLED);
2070         return true;
2071 }
2072
2073 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
2074                                 struct timeval request_time,
2075                                 struct timeval timeout,
2076                                 struct file_id id,
2077                                 struct deferred_open_record *open_rec)
2078 {
2079         struct tevent_req *req = NULL;
2080         struct smbd_smb2_create_state *state = NULL;
2081         struct timeval end_time;
2082
2083         if (!smb2req) {
2084                 return false;
2085         }
2086         req = smb2req->subreq;
2087         if (!req) {
2088                 return false;
2089         }
2090         state = tevent_req_data(req, struct smbd_smb2_create_state);
2091         if (!state) {
2092                 return false;
2093         }
2094         state->id = id;
2095         state->request_time = request_time;
2096         state->open_rec = talloc_move(state, &open_rec);
2097
2098         /* Re-schedule us to retry on timer expiry. */
2099         end_time = timeval_sum(&request_time, &timeout);
2100
2101         DEBUG(10,("push_deferred_open_message_smb2: "
2102                 "timeout at %s\n",
2103                 timeval_string(talloc_tos(),
2104                                 &end_time,
2105                                 true) ));
2106
2107         state->open_was_deferred = true;
2108
2109         /* allow this request to be canceled */
2110         tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
2111
2112         return true;
2113 }