Coverage Report

Created: 2026-07-25 07:00

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