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