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