Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/close.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   file closing
4
   Copyright (C) Andrew Tridgell 1992-1998
5
   Copyright (C) Jeremy Allison 1992-2007.
6
   Copyright (C) Volker Lendecke 2005
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 "system/filesys.h"
24
#include "lib/util/server_id.h"
25
#include "printing.h"
26
#include "locking/share_mode_lock.h"
27
#include "smbd/smbd.h"
28
#include "smbd/globals.h"
29
#include "smbd/smbXsrv_open.h"
30
#include "smbd/scavenger.h"
31
#include "fake_file.h"
32
#include "transfer_file.h"
33
#include "auth.h"
34
#include "messages.h"
35
#include "librpc/gen_ndr/ndr_open_files.h"
36
#include "lib/util/tevent_ntstatus.h"
37
#include "source3/smbd/dir.h"
38
39
/****************************************************************************
40
 Run a file if it is a magic script.
41
****************************************************************************/
42
43
static NTSTATUS check_magic(struct files_struct *fsp)
44
0
{
45
0
  int ret;
46
0
  const struct loadparm_substitution *lp_sub =
47
0
    loadparm_s3_global_substitution();
48
0
  const char *magic_output = NULL;
49
0
  SMB_STRUCT_STAT st;
50
0
  int tmp_fd, outfd;
51
0
  TALLOC_CTX *ctx = NULL;
52
0
  const char *p;
53
0
  struct connection_struct *conn = fsp->conn;
54
0
  char *fname = NULL;
55
0
  NTSTATUS status;
56
57
0
  if (!*lp_magic_script(talloc_tos(), lp_sub, SNUM(conn))) {
58
0
    return NT_STATUS_OK;
59
0
  }
60
61
0
  DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
62
63
0
  ctx = talloc_stackframe();
64
65
0
  fname = fsp->fsp_name->base_name;
66
67
0
  if (!(p = strrchr_m(fname,'/'))) {
68
0
    p = fname;
69
0
  } else {
70
0
    p++;
71
0
  }
72
73
0
  if (!strequal(lp_magic_script(talloc_tos(), lp_sub, SNUM(conn)),p)) {
74
0
    status = NT_STATUS_OK;
75
0
    goto out;
76
0
  }
77
78
0
  if (*lp_magic_output(talloc_tos(), lp_sub, SNUM(conn))) {
79
0
    magic_output = lp_magic_output(talloc_tos(), lp_sub, SNUM(conn));
80
0
  } else {
81
0
    magic_output = talloc_asprintf(ctx,
82
0
        "%s.out",
83
0
        fname);
84
0
  }
85
0
  if (!magic_output) {
86
0
    status = NT_STATUS_NO_MEMORY;
87
0
    goto out;
88
0
  }
89
90
  /* Ensure we don't depend on user's PATH. */
91
0
  p = talloc_asprintf(ctx, "./%s", fname);
92
0
  if (!p) {
93
0
    status = NT_STATUS_NO_MEMORY;
94
0
    goto out;
95
0
  }
96
97
0
  if (chmod(fname, 0755) == -1) {
98
0
    status = map_nt_error_from_unix(errno);
99
0
    goto out;
100
0
  }
101
0
  ret = smbrun(p, &tmp_fd, NULL);
102
0
  DEBUG(3,("Invoking magic command %s gave %d\n",
103
0
    p,ret));
104
105
0
  unlink(fname);
106
0
  if (ret != 0 || tmp_fd == -1) {
107
0
    if (tmp_fd != -1) {
108
0
      close(tmp_fd);
109
0
    }
110
0
    status = NT_STATUS_UNSUCCESSFUL;
111
0
    goto out;
112
0
  }
113
0
  outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
114
0
  if (outfd == -1) {
115
0
    int err = errno;
116
0
    close(tmp_fd);
117
0
    status = map_nt_error_from_unix(err);
118
0
    goto out;
119
0
  }
120
121
0
  if (sys_fstat(tmp_fd, &st, false) == -1) {
122
0
    int err = errno;
123
0
    close(tmp_fd);
124
0
    close(outfd);
125
0
    status = map_nt_error_from_unix(err);
126
0
    goto out;
127
0
  }
128
129
0
  if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
130
0
    int err = errno;
131
0
    close(tmp_fd);
132
0
    close(outfd);
133
0
    status = map_nt_error_from_unix(err);
134
0
    goto out;
135
0
  }
136
0
  close(tmp_fd);
137
0
  if (close(outfd) == -1) {
138
0
    status = map_nt_error_from_unix(errno);
139
0
    goto out;
140
0
  }
141
142
0
  status = NT_STATUS_OK;
143
144
0
 out:
145
0
  TALLOC_FREE(ctx);
146
0
  return status;
147
0
}
148
149
/****************************************************************************
150
 Delete all streams
151
****************************************************************************/
152
153
NTSTATUS delete_all_streams(struct files_struct *fsp,
154
          struct files_struct *dirfsp,
155
          struct smb_filename *fsp_atname)
156
0
{
157
0
  struct smb_filename *smb_fname = fsp->fsp_name;
158
0
  struct stream_struct *stream_info = NULL;
159
0
  unsigned int i;
160
0
  unsigned int num_streams = 0;
161
0
  TALLOC_CTX *frame = talloc_stackframe();
162
0
  NTSTATUS status;
163
164
0
  status = vfs_fstreaminfo(fsp,
165
0
         talloc_tos(),
166
0
         &num_streams,
167
0
         &stream_info);
168
169
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
170
0
    DEBUG(10, ("no streams around\n"));
171
0
    TALLOC_FREE(frame);
172
0
    return NT_STATUS_OK;
173
0
  }
174
175
0
  if (!NT_STATUS_IS_OK(status)) {
176
0
    DEBUG(10, ("vfs_fstreaminfo failed: %s\n",
177
0
         nt_errstr(status)));
178
0
    goto fail;
179
0
  }
180
181
0
  DEBUG(10, ("delete_all_streams found %d streams\n",
182
0
       num_streams));
183
184
0
  if (num_streams == 0) {
185
0
    TALLOC_FREE(frame);
186
0
    return NT_STATUS_OK;
187
0
  }
188
189
0
  for (i=0; i<num_streams; i++) {
190
0
    int res;
191
0
    struct smb_filename *smb_fname_stream;
192
193
0
    if (strequal(stream_info[i].name, "::$DATA")) {
194
0
      continue;
195
0
    }
196
197
0
    smb_fname_stream = synthetic_smb_fname(
198
0
      talloc_tos(),
199
0
      fsp_atname->base_name,
200
0
      stream_info[i].name,
201
0
      NULL,
202
0
      smb_fname->twrp,
203
0
      (smb_fname->flags & ~SMB_FILENAME_POSIX_PATH));
204
0
    if (!NT_STATUS_IS_OK(status)) {
205
0
      DEBUG(0, ("talloc_aprintf failed\n"));
206
0
      status = NT_STATUS_NO_MEMORY;
207
0
      goto fail;
208
0
    }
209
210
0
    res = SMB_VFS_UNLINKAT(dirfsp->conn,
211
0
               dirfsp,
212
0
               smb_fname_stream,
213
0
               0);
214
215
0
    if (res == -1) {
216
0
      status = map_nt_error_from_unix(errno);
217
0
      DEBUG(10, ("Could not delete stream %s: %s\n",
218
0
           smb_fname_str_dbg(smb_fname_stream),
219
0
           strerror(errno)));
220
0
      TALLOC_FREE(smb_fname_stream);
221
0
      break;
222
0
    }
223
0
    TALLOC_FREE(smb_fname_stream);
224
0
  }
225
226
0
 fail:
227
0
  TALLOC_FREE(frame);
228
0
  return status;
229
0
}
230
231
struct has_other_nonposix_opens_state {
232
  files_struct *fsp;
233
  bool found_another;
234
};
235
236
static bool has_other_nonposix_opens_fn(
237
  struct share_mode_entry *e,
238
  bool *modified,
239
  void *private_data)
240
0
{
241
0
  struct has_other_nonposix_opens_state *state = private_data;
242
0
  struct files_struct *fsp = state->fsp;
243
244
0
  if (e->flags & SHARE_ENTRY_FLAG_POSIX_OPEN) {
245
0
    return false;
246
0
  }
247
0
  if (fsp != NULL) {
248
0
    if (e->name_hash != fsp->name_hash) {
249
0
      return false;
250
0
    }
251
0
    if (e->share_file_id == fh_get_gen_id(fsp->fh)) {
252
0
      struct server_id self = messaging_server_id(
253
0
        fsp->conn->sconn->msg_ctx);
254
0
      if (server_id_equal(&self, &e->pid)) {
255
0
        return false;
256
0
      }
257
0
    }
258
0
  }
259
0
  if (share_entry_stale_pid(e)) {
260
0
    return false;
261
0
  }
262
263
0
  state->found_another = true;
264
0
  return true;
265
0
}
266
267
bool has_other_nonposix_opens(struct share_mode_lock *lck,
268
            struct files_struct *fsp)
269
0
{
270
0
  struct has_other_nonposix_opens_state state = { .fsp = fsp };
271
0
  bool ok;
272
273
0
  ok = share_mode_forall_entries(
274
0
    lck, has_other_nonposix_opens_fn, &state);
275
0
  if (!ok) {
276
0
    return false;
277
0
  }
278
0
  return state.found_another;
279
0
}
280
281
struct has_delete_access_opens_state {
282
  bool delete_access;
283
  bool delete_pending;
284
};
285
286
static bool has_delete_access_opens_fn(
287
  struct share_mode_entry *e,
288
  bool *modified,
289
  void *private_data)
290
0
{
291
0
  struct has_delete_access_opens_state *state = private_data;
292
293
0
  if (share_entry_stale_pid(e)) {
294
0
    return false;
295
0
  }
296
297
0
  if (e->access_mask & SEC_STD_DELETE) {
298
0
    state->delete_access = true;
299
0
  }
300
0
  return false;
301
0
}
302
303
bool has_delete_opens(struct files_struct *fsp,
304
          struct share_mode_lock *lck,
305
          bool *delete_access,
306
          bool *delete_pending)
307
0
{
308
0
  struct has_delete_access_opens_state state = {};
309
0
  bool ok;
310
311
0
  ok = share_mode_forall_entries(
312
0
    lck, has_delete_access_opens_fn, &state);
313
0
  if (!ok) {
314
0
    return false;
315
0
  }
316
317
0
  *delete_access = state.delete_access;
318
0
  *delete_pending = is_delete_on_close_set(lck, fsp->name_hash);
319
0
  return true;
320
0
}
321
322
bool has_nonposix_opens(struct share_mode_lock *lck)
323
0
{
324
0
  struct has_other_nonposix_opens_state state = {};
325
0
  bool ok;
326
327
0
  ok = share_mode_forall_entries(
328
0
    lck, has_other_nonposix_opens_fn, &state);
329
0
  if (!ok) {
330
0
    return false;
331
0
  }
332
0
  return state.found_another;
333
0
}
334
335
struct close_share_mode_lock_state {
336
  struct share_mode_entry_prepare_state prepare_state;
337
  const char *object_type;
338
  struct files_struct *fsp;
339
  enum file_close_type close_type;
340
  bool delete_object;
341
  bool got_tokens;
342
  struct smb2_lease_key parent_lease_key;
343
  const struct security_unix_token *del_token;
344
  const struct security_token *del_nt_token;
345
  bool reset_delete_on_close;
346
  share_mode_entry_prepare_unlock_fn_t cleanup_fn;
347
};
348
349
static void close_share_mode_lock_prepare(struct share_mode_lock *lck,
350
            bool *keep_locked,
351
            void *private_data)
352
0
{
353
0
  struct close_share_mode_lock_state *state =
354
0
    (struct close_share_mode_lock_state *)private_data;
355
0
  struct files_struct *fsp = state->fsp;
356
0
  bool normal_close;
357
0
  bool ok;
358
359
  /*
360
   * By default drop the g_lock again if we leave the
361
   * tdb chainlock.
362
   */
363
0
  *keep_locked = false;
364
365
0
  if (fsp->current_lock_count > 0) {
366
    /*
367
     * Remove the byte-range locks under the glock
368
     */
369
0
    *keep_locked = true;
370
0
  }
371
372
0
  if (fh_get_refcount(fsp->fh) > 1) {
373
0
    return;
374
0
  }
375
376
0
  if (fsp->oplock_type != NO_OPLOCK) {
377
0
    ok = remove_share_oplock(lck, fsp);
378
0
    if (!ok) {
379
0
      struct file_id_buf buf;
380
381
0
      DBG_ERR("failed to remove share oplock for "
382
0
        "%s %s, %s, %s\n",
383
0
        state->object_type,
384
0
        fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
385
0
        file_id_str_buf(fsp->file_id, &buf));
386
0
    }
387
0
  }
388
389
0
  if (fsp->fsp_flags.initial_delete_on_close &&
390
0
      !is_delete_on_close_set(lck, fsp->name_hash)) {
391
    /* Initial delete on close was set and no one else
392
     * wrote a real delete on close. */
393
394
0
    fsp->fsp_flags.delete_on_close = true;
395
0
    set_delete_on_close_lck(fsp, lck,
396
0
          fsp->conn->session_info->security_token,
397
0
          fsp->conn->session_info->unix_token);
398
0
  }
399
400
0
  state->delete_object = is_delete_on_close_set(lck, fsp->name_hash) &&
401
0
    !has_other_nonposix_opens(lck, fsp);
402
403
  /*
404
   * NT can set delete_on_close of the last open
405
   * reference to a file.
406
   */
407
408
0
  normal_close = (state->close_type == NORMAL_CLOSE || state->close_type == SHUTDOWN_CLOSE);
409
0
  if (!normal_close) {
410
    /*
411
     * Never try to delete the file/directory for ERROR_CLOSE
412
     */
413
0
    state->delete_object = false;
414
0
  }
415
416
0
  if (!state->delete_object) {
417
0
    ok = del_share_mode(lck, fsp);
418
0
    if (!ok) {
419
0
      DBG_ERR("Could not delete share entry for %s %s\n",
420
0
        state->object_type, fsp_str_dbg(fsp));
421
0
    }
422
0
    return;
423
0
  }
424
425
  /*
426
   * We're going to remove the file/directory
427
   * so keep the g_lock after the tdb chainlock
428
   * is left, so we hold the share_mode_lock
429
   * also during the deletion
430
   */
431
0
  *keep_locked = true;
432
433
0
  state->got_tokens = get_delete_on_close_token(lck,
434
0
                  fsp->name_hash,
435
0
                  &state->del_nt_token,
436
0
                  &state->del_token,
437
0
                  &state->parent_lease_key);
438
0
  if (state->close_type != ERROR_CLOSE) {
439
0
    SMB_ASSERT(state->got_tokens);
440
0
  }
441
0
}
442
443
static void close_share_mode_lock_cleanup(struct share_mode_lock *lck,
444
            void *private_data)
445
0
{
446
0
  struct close_share_mode_lock_state *state =
447
0
    (struct close_share_mode_lock_state *)private_data;
448
0
  struct files_struct *fsp = state->fsp;
449
0
  bool ok;
450
451
0
  if (state->reset_delete_on_close) {
452
0
    reset_delete_on_close_lck(fsp, lck);
453
0
  }
454
455
0
  ok = del_share_mode(lck, fsp);
456
0
  if (!ok) {
457
0
    DBG_ERR("Could not delete share entry for %s %s\n",
458
0
      state->object_type, fsp_str_dbg(fsp));
459
0
  }
460
0
}
461
462
/****************************************************************************
463
 Deal with removing a share mode on last close.
464
****************************************************************************/
465
466
static NTSTATUS close_remove_share_mode(files_struct *fsp,
467
          enum file_close_type close_type)
468
0
{
469
0
  connection_struct *conn = fsp->conn;
470
0
  struct close_share_mode_lock_state lck_state = {};
471
0
  bool changed_user = false;
472
0
  NTSTATUS status = NT_STATUS_OK;
473
0
  NTSTATUS tmp_status;
474
0
  NTSTATUS ulstatus;
475
0
  struct file_id id;
476
0
  struct smb_filename *parent_fname = NULL;
477
0
  struct smb_filename *base_fname = NULL;
478
0
  int ret;
479
480
  /*
481
   * Lock the share entries, and determine if we should delete
482
   * on close. If so delete whilst the lock is still in effect.
483
   * This prevents race conditions with the file being created. JRA.
484
   */
485
486
0
  lck_state = (struct close_share_mode_lock_state) {
487
0
    .fsp      = fsp,
488
0
    .object_type    = "file",
489
0
    .close_type   = close_type,
490
0
  };
491
492
0
  status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
493
0
               fsp->file_id,
494
0
               close_share_mode_lock_prepare,
495
0
               &lck_state);
496
0
  if (!NT_STATUS_IS_OK(status)) {
497
0
    DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
498
0
      fsp_str_dbg(fsp), nt_errstr(status));
499
0
    return status;
500
0
  }
501
502
0
  locking_close_file(fsp, close_type);
503
504
0
  if (fh_get_refcount(fsp->fh) > 1) {
505
0
    goto done;
506
0
  }
507
508
  /* Remove the oplock before potentially deleting the file. */
509
0
  if (fsp->oplock_type != NO_OPLOCK) {
510
0
    release_file_oplock(fsp);
511
0
  }
512
513
  /*
514
   * NT can set delete_on_close of the last open
515
   * reference to a file.
516
   */
517
518
0
  if (!lck_state.delete_object) {
519
0
    status = NT_STATUS_OK;
520
0
    goto done;
521
0
  }
522
523
  /*
524
   * Ok, we have to delete the file
525
   */
526
0
  lck_state.cleanup_fn = close_share_mode_lock_cleanup;
527
528
0
  DBG_INFO("%s. Delete on close was set - deleting file.\n",
529
0
     fsp_str_dbg(fsp));
530
531
0
  if (lck_state.got_tokens &&
532
0
      !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
533
0
  {
534
    /* Become the user who requested the delete. */
535
536
0
    DBG_INFO("file %s. Change user to uid %u\n",
537
0
       fsp_str_dbg(fsp),
538
0
       (unsigned int)lck_state.del_token->uid);
539
540
0
    if (!push_sec_ctx()) {
541
0
      char *msg = talloc_asprintf(
542
0
        talloc_tos(),
543
0
        "close_remove_share_mode: file %s. "
544
0
        "failed to push sec_ctx.\n", fsp_str_dbg(fsp));
545
0
      smb_panic(msg);
546
0
    }
547
548
0
    set_sec_ctx(lck_state.del_token->uid,
549
0
          lck_state.del_token->gid,
550
0
          lck_state.del_token->ngroups,
551
0
          lck_state.del_token->groups,
552
0
          lck_state.del_nt_token);
553
554
0
    changed_user = true;
555
0
  }
556
557
  /* We can only delete the file if the name we have is still valid and
558
     hasn't been renamed. */
559
560
0
  tmp_status = vfs_stat_fsp(fsp);
561
0
  if (!NT_STATUS_IS_OK(tmp_status)) {
562
0
    DBG_INFO("file %s. Delete on close "
563
0
       "was set and stat failed with error %s\n",
564
0
       fsp_str_dbg(fsp),
565
0
       nt_errstr(tmp_status));
566
    /*
567
     * Don't save the errno here, we ignore this error
568
     */
569
0
    goto done;
570
0
  }
571
572
0
  id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
573
574
0
  if (!file_id_equal(&fsp->file_id, &id)) {
575
0
    struct file_id_buf ftmp1, ftmp2;
576
0
    DBG_INFO("file %s. Delete on close "
577
0
       "was set and dev and/or inode does not match\n",
578
0
       fsp_str_dbg(fsp));
579
0
    DBG_INFO("file %s. stored file_id %s, stat file_id %s\n",
580
0
       fsp_str_dbg(fsp),
581
0
       file_id_str_buf(fsp->file_id, &ftmp1),
582
0
       file_id_str_buf(id, &ftmp2));
583
    /*
584
     * Don't save the errno here, we ignore this error
585
     */
586
0
    goto done;
587
0
  }
588
589
0
  status = parent_pathref(talloc_tos(),
590
0
        conn->cwd_fsp,
591
0
        fsp->fsp_name,
592
0
        &parent_fname,
593
0
        &base_fname);
594
0
  if (!NT_STATUS_IS_OK(status)) {
595
0
    goto done;
596
0
  }
597
598
0
  if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
599
0
      && !fsp_is_alternate_stream(fsp)) {
600
601
0
    status = delete_all_streams(fsp,
602
0
              parent_fname->fsp,
603
0
              base_fname);
604
605
0
    if (!NT_STATUS_IS_OK(status)) {
606
0
      DEBUG(5, ("delete_all_streams failed: %s\n",
607
0
          nt_errstr(status)));
608
0
      goto done;
609
0
    }
610
0
  }
611
612
0
  if (fsp->fsp_flags.kernel_share_modes_taken) {
613
    /*
614
     * A file system sharemode could block the unlink;
615
     * remove filesystem sharemodes first.
616
     */
617
0
    ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
618
0
    if (ret == -1) {
619
0
      DBG_INFO("Removing file system sharemode for %s "
620
0
         "failed: %s\n",
621
0
         fsp_str_dbg(fsp), strerror(errno));
622
0
    }
623
624
0
    fsp->fsp_flags.kernel_share_modes_taken = false;
625
0
  }
626
627
0
  ret = SMB_VFS_UNLINKAT(conn,
628
0
             parent_fname->fsp,
629
0
             base_fname,
630
0
             0);
631
0
  TALLOC_FREE(parent_fname);
632
0
  base_fname = NULL;
633
0
  if (ret != 0) {
634
    /*
635
     * This call can potentially fail as another smbd may
636
     * have had the file open with delete on close set and
637
     * deleted it when its last reference to this file
638
     * went away. Hence we log this but not at debug level
639
     * zero.
640
     */
641
642
0
    DBG_INFO("file %s. Delete on close "
643
0
       "was set and unlink failed with error %s\n",
644
0
       fsp_str_dbg(fsp),
645
0
       strerror(errno));
646
647
0
    status = map_nt_error_from_unix(errno);
648
0
  }
649
650
  /* As we now have POSIX opens which can unlink
651
   * with other open files we may have taken
652
   * this code path with more than one share mode
653
   * entry - ensure we only delete once by resetting
654
   * the delete on close flag. JRA.
655
   */
656
657
0
  fsp->fsp_flags.delete_on_close = false;
658
0
  fsp->fsp_flags.fstat_before_close = false;
659
0
  lck_state.reset_delete_on_close = true;
660
661
0
 done:
662
663
0
  if (changed_user) {
664
    /* unbecome user. */
665
0
    pop_sec_ctx();
666
0
  }
667
668
0
  if (fsp->fsp_flags.kernel_share_modes_taken) {
669
    /* remove filesystem sharemodes */
670
0
    ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
671
0
    if (ret == -1) {
672
0
      DBG_INFO("Removing file system sharemode for "
673
0
         "%s failed: %s\n",
674
0
         fsp_str_dbg(fsp), strerror(errno));
675
0
    }
676
0
  }
677
678
0
  ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
679
0
               lck_state.cleanup_fn,
680
0
               &lck_state);
681
0
  if (!NT_STATUS_IS_OK(ulstatus)) {
682
0
    DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
683
0
      fsp_str_dbg(fsp), nt_errstr(ulstatus));
684
0
    smb_panic("share_mode_entry_prepare_unlock() failed!");
685
0
  }
686
687
0
  if (lck_state.delete_object && NT_STATUS_IS_OK(status)) {
688
0
    const struct smb2_lease *lease = fsp_get_smb2_lease(fsp);
689
690
0
    if (lease != NULL) {
691
      /*
692
       * If parent lease key of handle on which delete
693
       * disposition was set does not match the parent key of
694
       * last closed handle, break all leases on the parent
695
       * directory.
696
       */
697
0
      if (!smb2_lease_key_equal(&lease->parent_lease_key,
698
0
              &lck_state.parent_lease_key))
699
0
      {
700
0
        lease = NULL;
701
0
      }
702
0
    }
703
0
    notify_fname(conn,
704
0
           NOTIFY_ACTION_REMOVED |
705
0
           NOTIFY_ACTION_DIRLEASE_BREAK,
706
0
           FILE_NOTIFY_CHANGE_FILE_NAME,
707
0
           fsp->fsp_name,
708
0
           lease);
709
0
  }
710
711
0
  return status;
712
0
}
713
714
/*
715
 * This is now only used for SMB1 closes that send an
716
 * explicit write time.
717
 */
718
void set_close_write_time(struct files_struct *fsp, struct timespec ts)
719
0
{
720
0
  DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
721
722
0
  if (is_omit_timespec(&ts)) {
723
0
    return;
724
0
  }
725
0
  fsp->fsp_flags.write_time_forced = false;
726
0
  fsp->close_write_time = ts;
727
0
}
728
729
/*
730
 * This is now only used for SMB1 closes that send an
731
 * explicit write time.
732
 */
733
static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
734
0
{
735
0
  struct smb_file_time ft;
736
0
  NTSTATUS status;
737
738
0
  init_smb_file_time(&ft);
739
740
0
  if (is_omit_timespec(&fsp->close_write_time)) {
741
0
    return NT_STATUS_OK;
742
0
  }
743
744
  /* Ensure we have a valid stat struct for the source. */
745
0
  status = vfs_stat_fsp(fsp);
746
0
  if (!NT_STATUS_IS_OK(status)) {
747
0
    return status;
748
0
  }
749
750
0
  if (!VALID_STAT(fsp->fsp_name->st)) {
751
    /* if it doesn't seem to be a real file */
752
0
    return NT_STATUS_OK;
753
0
  }
754
755
0
  ft.mtime = fsp->close_write_time;
756
757
0
  status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
758
0
  if (!NT_STATUS_IS_OK(status)) {
759
0
    DEBUG(10,("update_write_time_on_close: smb_set_file_time "
760
0
      "on file %s returned %s\n",
761
0
      fsp_str_dbg(fsp),
762
0
      nt_errstr(status)));
763
0
    return status;
764
0
  }
765
766
0
  return status;
767
0
}
768
769
static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
770
0
{
771
0
  if (!NT_STATUS_IS_OK(s1)) {
772
0
    return s1;
773
0
  }
774
0
  return s2;
775
0
}
776
777
static void assert_no_pending_aio(struct files_struct *fsp,
778
          enum file_close_type close_type)
779
0
{
780
0
  struct smbXsrv_client *client = global_smbXsrv_client;
781
0
  size_t num_connections_alive;
782
0
  unsigned num_requests = fsp->num_aio_requests;
783
784
0
  if (num_requests == 0) {
785
0
    return;
786
0
  }
787
788
0
  num_connections_alive = smbXsrv_client_valid_connections(client);
789
790
0
  if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
791
    /*
792
     * fsp->aio_requests and the contents (fsp->aio_requests[x])
793
     * are both independently owned by fsp and are not in a
794
     * talloc hierarchy. This allows the fsp->aio_requests array to
795
     * be reallocated independently of the array contents so it can
796
     * grow on demand.
797
     *
798
     * This means we must ensure order of deallocation
799
     * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
800
     * contents first, as their destructors access the
801
     * fsp->aio_request array. If we don't deallocate them
802
     * first, when fsp is deallocated fsp->aio_requests
803
     * could have been deallocated *before* its contents
804
     * fsp->aio_requests[x], causing a crash.
805
     */
806
0
    while (fsp->num_aio_requests != 0) {
807
      /*
808
       * NB. We *MUST* use
809
       * talloc_free(fsp->aio_requests[0]),
810
       * and *NOT* TALLOC_FREE() here, as
811
       * TALLOC_FREE(fsp->aio_requests[0])
812
       * will overwrite any new contents of
813
       * fsp->aio_requests[0] that were
814
       * copied into it via the destructor
815
       * aio_del_req_from_fsp().
816
       *
817
       * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
818
       */
819
0
      talloc_free(fsp->aio_requests[0]);
820
0
    }
821
0
    return;
822
0
  }
823
824
0
  DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
825
0
  smb_panic("can not close with outstanding aio requests");
826
0
  return;
827
0
}
828
829
/****************************************************************************
830
 Close a file.
831
832
 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
833
 printing and magic scripts are only run on normal close.
834
 delete on close is done on normal and shutdown close.
835
****************************************************************************/
836
837
static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
838
          enum file_close_type close_type)
839
0
{
840
0
  NTSTATUS status = NT_STATUS_OK;
841
0
  NTSTATUS tmp;
842
0
  connection_struct *conn = fsp->conn;
843
0
  bool is_durable = false;
844
845
0
  SMB_ASSERT(fsp->fsp_flags.is_fsa);
846
847
0
  assert_no_pending_aio(fsp, close_type);
848
849
0
  while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
850
0
    smbd_smb1_brl_finish_by_req(
851
0
      fsp->blocked_smb1_lock_reqs[0],
852
0
      NT_STATUS_RANGE_NOT_LOCKED);
853
0
  }
854
855
0
  if (fsp->op != NULL) {
856
0
    is_durable = fsp->op->global->durable;
857
0
  }
858
859
0
  if (close_type != SHUTDOWN_CLOSE) {
860
0
    is_durable = false;
861
0
  }
862
863
0
  if (is_durable) {
864
0
    DATA_BLOB new_cookie = data_blob_null;
865
866
0
    tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
867
0
          fsp->op->global->backend_cookie,
868
0
          fsp->op,
869
0
          &new_cookie);
870
0
    if (NT_STATUS_IS_OK(tmp)) {
871
0
      struct timeval tv;
872
0
      NTTIME now;
873
874
0
      if (req != NULL) {
875
0
        tv = req->request_time;
876
0
      } else {
877
0
        tv = timeval_current();
878
0
      }
879
0
      now = timeval_to_nttime(&tv);
880
881
0
      data_blob_free(&fsp->op->global->backend_cookie);
882
0
      fsp->op->global->backend_cookie = new_cookie;
883
884
0
      fsp->op->compat = NULL;
885
0
      tmp = smbXsrv_open_close(fsp->op, now);
886
0
      if (!NT_STATUS_IS_OK(tmp)) {
887
0
        DEBUG(1, ("Failed to update smbXsrv_open "
888
0
            "record when disconnecting durable "
889
0
            "handle for file %s: %s - "
890
0
            "proceeding with normal close\n",
891
0
            fsp_str_dbg(fsp), nt_errstr(tmp)));
892
0
      }
893
0
    } else {
894
0
      DEBUG(1, ("Failed to disconnect durable handle for "
895
0
          "file %s: %s - proceeding with normal "
896
0
          "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
897
0
    }
898
0
    if (!NT_STATUS_IS_OK(tmp)) {
899
0
      is_durable = false;
900
0
    }
901
0
  }
902
903
0
  if (is_durable) {
904
    /*
905
     * This is the case where we successfully disconnected
906
     * a durable handle and closed the underlying file.
907
     * In all other cases, we proceed with a genuine close.
908
     */
909
0
    DEBUG(10, ("%s disconnected durable handle for file %s\n",
910
0
         conn->session_info->unix_info->unix_name,
911
0
         fsp_str_dbg(fsp)));
912
0
    scavenger_schedule_disconnected(fsp);
913
0
    return NT_STATUS_OK;
914
0
  }
915
916
0
  if (fsp->op != NULL) {
917
    /*
918
     * Make sure the handle is not marked as durable anymore
919
     */
920
0
    fsp->op->global->durable = false;
921
0
  }
922
923
0
  if (fsp->fsp_flags.modified) {
924
0
    notify_fname(conn,
925
0
           NOTIFY_ACTION_DIRLEASE_BREAK,
926
0
           0,
927
0
           fsp->fsp_name,
928
0
           fsp_get_smb2_lease(fsp));
929
0
  }
930
931
  /* If this is an old DOS or FCB open and we have multiple opens on
932
     the same handle we only have one share mode. Ensure we only remove
933
     the share mode on the last close. */
934
935
0
  tmp = close_remove_share_mode(fsp, close_type);
936
0
  status = ntstatus_keeperror(status, tmp);
937
938
  /*
939
   * Ensure pending modtime is set before closing underlying fd.
940
   */
941
942
0
  tmp = update_write_time_on_close(fsp);
943
0
  if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
944
    /*
945
     * Someone renamed the file or a parent directory containing
946
     * this file. We can't do anything about this, eat the error.
947
     */
948
0
    tmp = NT_STATUS_OK;
949
0
  }
950
0
  status = ntstatus_keeperror(status, tmp);
951
952
0
  tmp = fd_close(fsp);
953
0
  status = ntstatus_keeperror(status, tmp);
954
955
  /* check for magic scripts */
956
0
  if (close_type == NORMAL_CLOSE) {
957
0
    tmp = check_magic(fsp);
958
0
    status = ntstatus_keeperror(status, tmp);
959
0
  }
960
961
0
  DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
962
0
    conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
963
0
    conn->num_files_open - 1,
964
0
    nt_errstr(status) ));
965
966
0
  return status;
967
0
}
968
969
NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
970
0
{
971
0
  struct connection_struct *conn = fsp->conn;
972
0
  const char *dname = NULL;
973
0
  char *talloced = NULL;
974
0
  struct smb_Dir *dir_hnd = NULL;
975
0
  struct files_struct *dirfsp = NULL;
976
0
  int retval;
977
0
  NTSTATUS status = NT_STATUS_OK;
978
979
0
  status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
980
0
  if (!NT_STATUS_IS_OK(status)) {
981
0
    return status;
982
0
  }
983
984
0
  dirfsp = dir_hnd_fetch_fsp(dir_hnd);
985
986
0
  while ((dname = ReadDirName(dir_hnd, &talloced))) {
987
0
    struct smb_filename *atname = NULL;
988
0
    int unlink_flags = 0;
989
990
0
    if (ISDOT(dname) || ISDOTDOT(dname)) {
991
0
      TALLOC_FREE(talloced);
992
0
      continue;
993
0
    }
994
995
0
    atname = synthetic_smb_fname(talloc_tos(),
996
0
               dname,
997
0
               NULL,
998
0
               NULL,
999
0
               dirfsp->fsp_name->twrp,
1000
0
               dirfsp->fsp_name->flags);
1001
0
    TALLOC_FREE(talloced);
1002
0
    dname = NULL;
1003
1004
0
    if (atname == NULL) {
1005
0
      status = NT_STATUS_NO_MEMORY;
1006
0
      break;
1007
0
    }
1008
1009
0
    {
1010
0
      struct name_compare_entry *veto_list = conn->veto_list;
1011
1012
      /*
1013
       * Sneaky hack to be able to open veto files
1014
       * with openat_pathref_fsp
1015
       */
1016
1017
0
      conn->veto_list = NULL;
1018
0
      status = openat_pathref_fsp_lcomp(
1019
0
        dirfsp,
1020
0
        atname,
1021
0
        UCF_POSIX_PATHNAMES /* no ci fallback */);
1022
0
      conn->veto_list = veto_list;
1023
0
    }
1024
1025
0
    if (!NT_STATUS_IS_OK(status)) {
1026
0
      TALLOC_FREE(atname);
1027
0
      if (NT_STATUS_EQUAL(status,
1028
0
              NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1029
        /* race between readdir and unlink */
1030
0
        continue;
1031
0
      }
1032
0
      break;
1033
0
    }
1034
1035
0
    if (atname->st.st_ex_mode & S_IFDIR) {
1036
0
      status = recursive_rmdir_fsp(atname->fsp);
1037
0
      if (!NT_STATUS_IS_OK(status)) {
1038
0
        TALLOC_FREE(atname);
1039
0
        break;
1040
0
      }
1041
0
      unlink_flags = AT_REMOVEDIR;
1042
0
    }
1043
1044
0
    if (!is_visible_fsp(atname->fsp)) {
1045
0
      TALLOC_FREE(atname);
1046
0
      continue;
1047
0
    }
1048
1049
0
    retval = SMB_VFS_UNLINKAT(conn,
1050
0
            dirfsp,
1051
0
            atname,
1052
0
            unlink_flags);
1053
0
    if (retval != 0) {
1054
0
      status = map_nt_error_from_unix(errno);
1055
0
      TALLOC_FREE(atname);
1056
0
      break;
1057
0
    }
1058
1059
0
    TALLOC_FREE(atname);
1060
0
  }
1061
1062
0
  TALLOC_FREE(dir_hnd);
1063
0
  return status;
1064
0
}
1065
1066
/****************************************************************************
1067
 The internals of the rmdir code - called elsewhere.
1068
****************************************************************************/
1069
1070
static NTSTATUS rmdir_internals(struct files_struct *fsp,
1071
        struct files_struct *dirfsp,
1072
        struct smb_filename *at_fname)
1073
0
{
1074
0
  struct connection_struct *conn = fsp->conn;
1075
0
  struct smb_filename *smb_dname = fsp->fsp_name;
1076
0
  struct smb_Dir *dir_hnd = NULL;
1077
0
  struct stat_ex st = {};
1078
0
  int unlink_flags = 0;
1079
0
  NTSTATUS status;
1080
0
  int ret;
1081
1082
0
  SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1083
1084
  /*
1085
   * Todo: use SMB_VFS_STATX() once it's available.
1086
   */
1087
1088
  /* Might be a symlink. */
1089
0
  ret = SMB_VFS_LSTAT(conn, smb_dname);
1090
0
  if (ret != 0) {
1091
0
    return map_nt_error_from_unix(errno);
1092
0
  }
1093
1094
0
  if (S_ISLNK(st.st_ex_mode)) {
1095
    /* Is what it points to a directory ? */
1096
0
    ret = SMB_VFS_STAT(conn, smb_dname);
1097
0
    if (ret != 0) {
1098
0
      return map_nt_error_from_unix(errno);
1099
0
    }
1100
0
    if (!(S_ISDIR(st.st_ex_mode))) {
1101
0
      return NT_STATUS_NOT_A_DIRECTORY;
1102
0
    }
1103
0
  } else {
1104
0
    unlink_flags = AT_REMOVEDIR;
1105
0
  }
1106
1107
0
  ret = SMB_VFS_UNLINKAT(conn, dirfsp, at_fname, unlink_flags);
1108
0
  if (ret == 0) {
1109
0
    return NT_STATUS_OK;
1110
0
  }
1111
1112
0
  if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1113
0
    DBG_NOTICE("couldn't remove directory %s : %s\n",
1114
0
         smb_fname_str_dbg(smb_dname),
1115
0
         strerror(errno));
1116
0
    return map_nt_error_from_unix(errno);
1117
0
  }
1118
1119
  /*
1120
   * Here we know the initial directory unlink failed with
1121
   * ENOTEMPTY or EEXIST so we know there are objects within.
1122
   * If we don't have permission to delete files non
1123
   * visible to the client just fail the directory delete.
1124
   */
1125
1126
0
  if (!lp_delete_veto_files(SNUM(conn))) {
1127
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1128
0
    goto err;
1129
0
  }
1130
1131
  /*
1132
   * Check to see if the only things in this directory are
1133
   * files non-visible to the client. If not, fail the delete.
1134
   */
1135
1136
0
  status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
1137
0
  if (!NT_STATUS_IS_OK(status)) {
1138
    /*
1139
     * Note, we deliberately squash the error here
1140
     * to avoid leaking information about what we
1141
     * can't delete.
1142
     */
1143
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1144
0
    goto err;
1145
0
  }
1146
1147
0
  status = can_delete_directory_hnd(dir_hnd);
1148
0
  TALLOC_FREE(dir_hnd);
1149
1150
0
  if (!NT_STATUS_IS_OK(status)) {
1151
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1152
0
    goto err;
1153
0
  }
1154
1155
0
  status = recursive_rmdir_fsp(fsp);
1156
0
  if (!NT_STATUS_IS_OK(status)) {
1157
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1158
0
    goto err;
1159
0
  }
1160
1161
  /* Retry the rmdir */
1162
0
  ret = SMB_VFS_UNLINKAT(conn, dirfsp, at_fname, AT_REMOVEDIR);
1163
0
  if (ret != 0) {
1164
0
    status = map_nt_error_from_unix(errno);
1165
0
  }
1166
1167
0
  err:
1168
0
  if (!NT_STATUS_IS_OK(status)) {
1169
0
    DBG_NOTICE("couldn't remove directory %s : "
1170
0
       "%s\n", smb_fname_str_dbg(smb_dname),
1171
0
       nt_errstr(status));
1172
0
    return status;
1173
0
  }
1174
1175
0
  return status;
1176
0
}
1177
1178
/****************************************************************************
1179
 Close a directory opened by an NT SMB call.
1180
****************************************************************************/
1181
1182
static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1183
        enum file_close_type close_type)
1184
0
{
1185
0
  connection_struct *conn = fsp->conn;
1186
0
  struct close_share_mode_lock_state lck_state = {};
1187
0
  bool changed_user = false;
1188
0
  struct smb_filename *parent_fname = NULL;
1189
0
  struct smb_filename *base_fname = NULL;
1190
0
  NTSTATUS status = NT_STATUS_OK;
1191
0
  NTSTATUS status1 = NT_STATUS_OK;
1192
0
  NTSTATUS notify_status;
1193
0
  NTSTATUS ulstatus;
1194
1195
0
  SMB_ASSERT(fsp->fsp_flags.is_fsa);
1196
1197
0
  if (conn_using_smb2(fsp->conn->sconn)) {
1198
0
    notify_status = NT_STATUS_NOTIFY_CLEANUP;
1199
0
  } else {
1200
0
    notify_status = NT_STATUS_OK;
1201
0
  }
1202
1203
0
  assert_no_pending_aio(fsp, close_type);
1204
1205
  /*
1206
   * NT can set delete_on_close of the last open
1207
   * reference to a directory also.
1208
   */
1209
1210
0
  lck_state = (struct close_share_mode_lock_state) {
1211
0
    .fsp      = fsp,
1212
0
    .object_type    = "directory",
1213
0
    .close_type   = close_type,
1214
0
  };
1215
1216
0
  status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1217
0
               fsp->file_id,
1218
0
               close_share_mode_lock_prepare,
1219
0
               &lck_state);
1220
0
  if (!NT_STATUS_IS_OK(status)) {
1221
0
    DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1222
0
      fsp_str_dbg(fsp), nt_errstr(status));
1223
0
    log_stack_trace();
1224
0
    goto close_fd;
1225
0
  }
1226
1227
  /* Remove the oplock before potentially deleting the file. */
1228
0
  if (fsp->oplock_type != NO_OPLOCK) {
1229
0
    release_file_oplock(fsp);
1230
0
  }
1231
1232
  /*
1233
   * NT can set delete_on_close of the last open
1234
   * reference to a file.
1235
   */
1236
1237
0
  if (!lck_state.delete_object) {
1238
0
    status = NT_STATUS_OK;
1239
0
    goto done;
1240
0
  }
1241
1242
  /*
1243
   * Ok, we have to delete the directory
1244
   */
1245
0
  lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1246
1247
0
  if (lck_state.got_tokens &&
1248
0
      !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1249
0
  {
1250
    /* Become the user who requested the delete. */
1251
1252
0
    DBG_INFO("dir %s. Change user to uid %u\n",
1253
0
       fsp_str_dbg(fsp),
1254
0
       (unsigned int)lck_state.del_token->uid);
1255
1256
0
    if (!push_sec_ctx()) {
1257
0
      smb_panic("close_directory: failed to push sec_ctx.\n");
1258
0
    }
1259
1260
0
    set_sec_ctx(lck_state.del_token->uid,
1261
0
          lck_state.del_token->gid,
1262
0
          lck_state.del_token->ngroups,
1263
0
          lck_state.del_token->groups,
1264
0
          lck_state.del_nt_token);
1265
1266
0
    changed_user = true;
1267
0
  }
1268
1269
0
  status = parent_pathref(talloc_tos(),
1270
0
        conn->cwd_fsp,
1271
0
        fsp->fsp_name,
1272
0
        &parent_fname,
1273
0
        &base_fname);
1274
0
  if (!NT_STATUS_IS_OK(status)) {
1275
0
    DBG_DEBUG("parent_pathref(%s) failed: %s\n",
1276
0
        fsp_str_dbg(fsp), nt_errstr(status));
1277
0
    goto done;
1278
0
  }
1279
0
  if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1280
0
      && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1281
1282
0
    status = delete_all_streams(fsp,
1283
0
              parent_fname->fsp,
1284
0
              base_fname);
1285
0
    if (!NT_STATUS_IS_OK(status)) {
1286
0
      DEBUG(5, ("delete_all_streams failed: %s\n",
1287
0
          nt_errstr(status)));
1288
0
      goto done;
1289
0
    }
1290
0
  }
1291
1292
0
  status = rmdir_internals(fsp, parent_fname->fsp, base_fname);
1293
1294
0
  TALLOC_FREE(parent_fname);
1295
1296
0
  DBG_INFO("%s. Delete on close was set - "
1297
0
     "deleting directory returned %s.\n",
1298
0
     fsp_str_dbg(fsp),
1299
0
     nt_errstr(status));
1300
1301
  /*
1302
   * Ensure we remove any change notify requests that would
1303
   * now fail as the directory has been deleted.
1304
   */
1305
1306
0
  if (NT_STATUS_IS_OK(status)) {
1307
0
    notify_status = NT_STATUS_DELETE_PENDING;
1308
0
  }
1309
1310
0
done:
1311
0
  if (changed_user) {
1312
    /* unbecome user. */
1313
0
    pop_sec_ctx();
1314
0
  }
1315
1316
0
  ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1317
0
               lck_state.cleanup_fn,
1318
0
               &lck_state);
1319
0
  if (!NT_STATUS_IS_OK(ulstatus)) {
1320
0
    DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1321
0
      fsp_str_dbg(fsp), nt_errstr(ulstatus));
1322
0
    smb_panic("share_mode_entry_prepare_unlock() failed!");
1323
0
  }
1324
1325
0
  remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1326
1327
0
  if (lck_state.delete_object && NT_STATUS_IS_OK(status)) {
1328
0
    const struct smb2_lease *lease = fsp_get_smb2_lease(fsp);
1329
1330
0
    if (lease != NULL) {
1331
      /*
1332
       * If parent lease key of handle on which delete
1333
       * disposition was set does not match the parent lease
1334
       * key of last closed handle, break all leases on the
1335
       * parent directory.
1336
       */
1337
0
      if (!smb2_lease_key_equal(&lease->parent_lease_key,
1338
0
              &lck_state.parent_lease_key))
1339
0
      {
1340
0
        lease = NULL;
1341
0
      }
1342
0
    }
1343
0
    notify_fname(conn,
1344
0
           NOTIFY_ACTION_REMOVED |
1345
0
           NOTIFY_ACTION_DIRLEASE_BREAK,
1346
0
           FILE_NOTIFY_CHANGE_DIR_NAME,
1347
0
           fsp->fsp_name,
1348
0
           lease);
1349
0
  }
1350
1351
0
close_fd:
1352
0
  status1 = fd_close(fsp);
1353
1354
0
  if (!NT_STATUS_IS_OK(status1)) {
1355
0
    DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1356
0
        fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1357
0
        strerror(errno)));
1358
0
  }
1359
1360
0
  if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1361
0
    status = status1;
1362
0
  }
1363
0
  return status;
1364
0
}
1365
1366
/****************************************************************************
1367
 Rundown all SMB-related dependencies of a files struct
1368
****************************************************************************/
1369
1370
NTSTATUS close_file_smb(struct smb_request *req,
1371
      struct files_struct *fsp,
1372
      enum file_close_type close_type)
1373
0
{
1374
0
  NTSTATUS status;
1375
1376
  /*
1377
   * This fsp can never be an internal dirfsp. They must
1378
   * be explicitly closed by TALLOC_FREE of the dir handle.
1379
   */
1380
0
  SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1381
1382
  /*
1383
   * Never call directly on a base fsp
1384
   */
1385
0
  SMB_ASSERT(fsp->stream_fsp == NULL);
1386
1387
0
  if (fsp->fake_file_handle != NULL) {
1388
    /*
1389
     * Named pipes are opened as fake files and
1390
     * can have pending aio requests. Ensure
1391
     * we clear out all pending aio on force
1392
     * shutdown of named pipes also.
1393
     * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
1394
     */
1395
0
    assert_no_pending_aio(fsp, close_type);
1396
0
    status = close_fake_file(req, fsp);
1397
0
  } else if (fsp->print_file != NULL) {
1398
    /* FIXME: return spool errors */
1399
0
    print_spool_end(fsp, close_type);
1400
0
    fd_close(fsp);
1401
0
    status = NT_STATUS_OK;
1402
0
  } else if (!fsp->fsp_flags.is_fsa) {
1403
0
    if (close_type == NORMAL_CLOSE) {
1404
0
      DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1405
0
        "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1406
0
        fsp_str_dbg(fsp),
1407
0
        fsp->fsp_flags.is_fsa,
1408
0
        fsp->fsp_flags.is_pathref,
1409
0
        fsp->fsp_flags.is_directory);
1410
0
    }
1411
0
    SMB_ASSERT(close_type != NORMAL_CLOSE);
1412
0
    fd_close(fsp);
1413
0
    status = NT_STATUS_OK;
1414
0
  } else if (fsp->fsp_flags.is_directory) {
1415
0
    status = close_directory(req, fsp, close_type);
1416
0
  } else {
1417
0
    status = close_normal_file(req, fsp, close_type);
1418
0
  }
1419
1420
0
  if (fsp_is_alternate_stream(fsp)) {
1421
    /*
1422
     * fsp was a stream, its base_fsp can't be a stream
1423
     * as well
1424
     */
1425
0
    SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1426
1427
    /*
1428
     * There's a 1:1 relationship between fsp and a base_fsp
1429
     */
1430
0
    SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1431
1432
    /*
1433
     * Make base_fsp look standalone now
1434
     */
1435
0
    fsp->base_fsp->stream_fsp = NULL;
1436
1437
0
    close_file_free(req, &fsp->base_fsp, close_type);
1438
0
  }
1439
1440
0
  fsp_unbind_smb(req, fsp);
1441
1442
0
  return status;
1443
0
}
1444
1445
NTSTATUS close_file_free(struct smb_request *req,
1446
       struct files_struct **_fsp,
1447
       enum file_close_type close_type)
1448
0
{
1449
0
  struct files_struct *fsp = *_fsp;
1450
0
  NTSTATUS status;
1451
1452
0
  status = close_file_smb(req, fsp, close_type);
1453
1454
0
  file_free(req, fsp);
1455
0
        *_fsp = NULL;
1456
1457
0
  return status;
1458
0
}
1459
1460
/****************************************************************************
1461
 Deal with an (authorized) message to close a file given the share mode
1462
 entry.
1463
****************************************************************************/
1464
1465
void msg_close_file(struct messaging_context *msg_ctx,
1466
      void *private_data,
1467
      uint32_t msg_type,
1468
      struct server_id server_id,
1469
      DATA_BLOB *data)
1470
0
{
1471
0
  struct oplock_break_message msg;
1472
0
  enum ndr_err_code ndr_err;
1473
0
  files_struct *fsp = NULL;
1474
0
  struct smbd_server_connection *sconn =
1475
0
    talloc_get_type_abort(private_data,
1476
0
    struct smbd_server_connection);
1477
1478
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(
1479
0
    data,
1480
0
    &msg,
1481
0
    (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
1482
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1483
0
    DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
1484
0
        ndr_errstr(ndr_err));
1485
0
    return;
1486
0
  }
1487
1488
0
  fsp = file_find_dif(sconn, msg.id, msg.share_file_id);
1489
0
  if (!fsp) {
1490
0
    DEBUG(10,("msg_close_file: failed to find file.\n"));
1491
0
    return;
1492
0
  }
1493
0
  close_file_free(NULL, &fsp, NORMAL_CLOSE);
1494
0
}