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