Coverage Report

Created: 2026-06-07 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 (smb_fname_stream == NULL) {
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 = smb_file_time_omit();
736
0
  NTSTATUS status;
737
738
0
  if (is_omit_timespec(&fsp->close_write_time)) {
739
0
    return NT_STATUS_OK;
740
0
  }
741
742
  /* Ensure we have a valid stat struct for the source. */
743
0
  status = vfs_stat_fsp(fsp);
744
0
  if (!NT_STATUS_IS_OK(status)) {
745
0
    return status;
746
0
  }
747
748
0
  if (!VALID_STAT(fsp->fsp_name->st)) {
749
    /* if it doesn't seem to be a real file */
750
0
    return NT_STATUS_OK;
751
0
  }
752
753
0
  ft.mtime = fsp->close_write_time;
754
755
0
  status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
756
0
  if (!NT_STATUS_IS_OK(status)) {
757
0
    DEBUG(10,("update_write_time_on_close: smb_set_file_time "
758
0
      "on file %s returned %s\n",
759
0
      fsp_str_dbg(fsp),
760
0
      nt_errstr(status)));
761
0
    return status;
762
0
  }
763
764
0
  return status;
765
0
}
766
767
static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
768
0
{
769
0
  if (!NT_STATUS_IS_OK(s1)) {
770
0
    return s1;
771
0
  }
772
0
  return s2;
773
0
}
774
775
static void assert_no_pending_aio(struct files_struct *fsp,
776
          enum file_close_type close_type)
777
0
{
778
0
  struct smbXsrv_client *client = global_smbXsrv_client;
779
0
  size_t num_connections_alive;
780
0
  unsigned num_requests = fsp->num_aio_requests;
781
782
0
  if (num_requests == 0) {
783
0
    return;
784
0
  }
785
786
0
  num_connections_alive = smbXsrv_client_valid_connections(client);
787
788
0
  if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
789
    /*
790
     * fsp->aio_requests and the contents (fsp->aio_requests[x])
791
     * are both independently owned by fsp and are not in a
792
     * talloc hierarchy. This allows the fsp->aio_requests array to
793
     * be reallocated independently of the array contents so it can
794
     * grow on demand.
795
     *
796
     * This means we must ensure order of deallocation
797
     * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
798
     * contents first, as their destructors access the
799
     * fsp->aio_request array. If we don't deallocate them
800
     * first, when fsp is deallocated fsp->aio_requests
801
     * could have been deallocated *before* its contents
802
     * fsp->aio_requests[x], causing a crash.
803
     */
804
0
    while (fsp->num_aio_requests != 0) {
805
      /*
806
       * NB. We *MUST* use
807
       * talloc_free(fsp->aio_requests[0]),
808
       * and *NOT* TALLOC_FREE() here, as
809
       * TALLOC_FREE(fsp->aio_requests[0])
810
       * will overwrite any new contents of
811
       * fsp->aio_requests[0] that were
812
       * copied into it via the destructor
813
       * aio_del_req_from_fsp().
814
       *
815
       * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
816
       */
817
0
      talloc_free(fsp->aio_requests[0]);
818
0
    }
819
0
    return;
820
0
  }
821
822
0
  DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
823
0
  smb_panic("can not close with outstanding aio requests");
824
0
  return;
825
0
}
826
827
/****************************************************************************
828
 Close a file.
829
830
 close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
831
 printing and magic scripts are only run on normal close.
832
 delete on close is done on normal and shutdown close.
833
****************************************************************************/
834
835
static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
836
          enum file_close_type close_type)
837
0
{
838
0
  NTSTATUS status = NT_STATUS_OK;
839
0
  NTSTATUS tmp;
840
0
  connection_struct *conn = fsp->conn;
841
0
  bool is_durable = false;
842
843
0
  SMB_ASSERT(fsp->fsp_flags.is_fsa);
844
845
0
  assert_no_pending_aio(fsp, close_type);
846
847
0
  while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
848
0
    smbd_smb1_brl_finish_by_req(
849
0
      fsp->blocked_smb1_lock_reqs[0],
850
0
      NT_STATUS_RANGE_NOT_LOCKED);
851
0
  }
852
853
0
  if (fsp->op != NULL) {
854
0
    is_durable = fsp->op->global->durable;
855
0
  }
856
857
0
  if (close_type != SHUTDOWN_CLOSE) {
858
0
    is_durable = false;
859
0
  }
860
861
0
  if (is_durable) {
862
0
    DATA_BLOB new_cookie = data_blob_null;
863
864
0
    tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
865
0
          fsp->op->global->backend_cookie,
866
0
          fsp->op,
867
0
          &new_cookie);
868
0
    if (NT_STATUS_IS_OK(tmp)) {
869
0
      struct timeval tv;
870
0
      NTTIME now;
871
872
0
      if (req != NULL) {
873
0
        tv = req->request_time;
874
0
      } else {
875
0
        tv = timeval_current();
876
0
      }
877
0
      now = timeval_to_nttime(&tv);
878
879
0
      data_blob_free(&fsp->op->global->backend_cookie);
880
0
      fsp->op->global->backend_cookie = new_cookie;
881
882
0
      fsp->op->compat = NULL;
883
0
      tmp = smbXsrv_open_close(fsp->op, now);
884
0
      if (!NT_STATUS_IS_OK(tmp)) {
885
0
        DEBUG(1, ("Failed to update smbXsrv_open "
886
0
            "record when disconnecting durable "
887
0
            "handle for file %s: %s - "
888
0
            "proceeding with normal close\n",
889
0
            fsp_str_dbg(fsp), nt_errstr(tmp)));
890
0
      }
891
0
    } else {
892
0
      DEBUG(1, ("Failed to disconnect durable handle for "
893
0
          "file %s: %s - proceeding with normal "
894
0
          "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
895
0
    }
896
0
    if (!NT_STATUS_IS_OK(tmp)) {
897
0
      is_durable = false;
898
0
    }
899
0
  }
900
901
0
  if (is_durable) {
902
    /*
903
     * This is the case where we successfully disconnected
904
     * a durable handle and closed the underlying file.
905
     * In all other cases, we proceed with a genuine close.
906
     */
907
0
    DEBUG(10, ("%s disconnected durable handle for file %s\n",
908
0
         conn->session_info->unix_info->unix_name,
909
0
         fsp_str_dbg(fsp)));
910
0
    scavenger_schedule_disconnected(fsp);
911
0
    return NT_STATUS_OK;
912
0
  }
913
914
0
  if (fsp->op != NULL) {
915
    /*
916
     * Make sure the handle is not marked as durable anymore
917
     */
918
0
    fsp->op->global->durable = false;
919
0
  }
920
921
0
  if (fsp->fsp_flags.modified) {
922
0
    notify_fname(conn,
923
0
           NOTIFY_ACTION_DIRLEASE_BREAK,
924
0
           0,
925
0
           fsp->fsp_name,
926
0
           fsp_get_smb2_lease(fsp));
927
0
  }
928
929
  /* If this is an old DOS or FCB open and we have multiple opens on
930
     the same handle we only have one share mode. Ensure we only remove
931
     the share mode on the last close. */
932
933
0
  tmp = close_remove_share_mode(fsp, close_type);
934
0
  status = ntstatus_keeperror(status, tmp);
935
936
  /*
937
   * Ensure pending modtime is set before closing underlying fd.
938
   */
939
940
0
  tmp = update_write_time_on_close(fsp);
941
0
  if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
942
    /*
943
     * Someone renamed the file or a parent directory containing
944
     * this file. We can't do anything about this, eat the error.
945
     */
946
0
    tmp = NT_STATUS_OK;
947
0
  }
948
0
  status = ntstatus_keeperror(status, tmp);
949
950
0
  tmp = fd_close(fsp);
951
0
  status = ntstatus_keeperror(status, tmp);
952
953
  /* check for magic scripts */
954
0
  if (close_type == NORMAL_CLOSE) {
955
0
    tmp = check_magic(fsp);
956
0
    status = ntstatus_keeperror(status, tmp);
957
0
  }
958
959
0
  DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
960
0
    conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
961
0
    conn->num_files_open - 1,
962
0
    nt_errstr(status) ));
963
964
0
  return status;
965
0
}
966
967
NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
968
0
{
969
0
  struct connection_struct *conn = fsp->conn;
970
0
  const char *dname = NULL;
971
0
  char *talloced = NULL;
972
0
  struct smb_Dir *dir_hnd = NULL;
973
0
  struct files_struct *dirfsp = NULL;
974
0
  int retval;
975
0
  NTSTATUS status = NT_STATUS_OK;
976
977
0
  status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
978
0
  if (!NT_STATUS_IS_OK(status)) {
979
0
    return status;
980
0
  }
981
982
0
  dirfsp = dir_hnd_fetch_fsp(dir_hnd);
983
984
0
  while ((dname = ReadDirName(dir_hnd, &talloced))) {
985
0
    struct smb_filename *atname = NULL;
986
0
    int unlink_flags = 0;
987
988
0
    if (ISDOT(dname) || ISDOTDOT(dname)) {
989
0
      TALLOC_FREE(talloced);
990
0
      continue;
991
0
    }
992
993
0
    atname = synthetic_smb_fname(talloc_tos(),
994
0
               dname,
995
0
               NULL,
996
0
               NULL,
997
0
               dirfsp->fsp_name->twrp,
998
0
               dirfsp->fsp_name->flags);
999
0
    TALLOC_FREE(talloced);
1000
0
    dname = NULL;
1001
1002
0
    if (atname == NULL) {
1003
0
      status = NT_STATUS_NO_MEMORY;
1004
0
      break;
1005
0
    }
1006
1007
0
    {
1008
0
      struct name_compare_entry *veto_list = conn->veto_list;
1009
1010
      /*
1011
       * Sneaky hack to be able to open veto files
1012
       * with openat_pathref_fsp
1013
       */
1014
1015
0
      conn->veto_list = NULL;
1016
0
      status = openat_pathref_fsp_lcomp(
1017
0
        dirfsp,
1018
0
        atname,
1019
0
        UCF_POSIX_PATHNAMES /* no ci fallback */);
1020
0
      conn->veto_list = veto_list;
1021
0
    }
1022
1023
0
    if (!NT_STATUS_IS_OK(status)) {
1024
0
      TALLOC_FREE(atname);
1025
0
      if (NT_STATUS_EQUAL(status,
1026
0
              NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1027
        /* race between readdir and unlink */
1028
0
        continue;
1029
0
      }
1030
0
      break;
1031
0
    }
1032
1033
0
    if (atname->st.st_ex_mode & S_IFDIR) {
1034
0
      status = recursive_rmdir_fsp(atname->fsp);
1035
0
      if (!NT_STATUS_IS_OK(status)) {
1036
0
        TALLOC_FREE(atname);
1037
0
        break;
1038
0
      }
1039
0
      unlink_flags = AT_REMOVEDIR;
1040
0
    }
1041
1042
0
    if (!is_visible_fsp(atname->fsp)) {
1043
0
      TALLOC_FREE(atname);
1044
0
      continue;
1045
0
    }
1046
1047
0
    retval = SMB_VFS_UNLINKAT(conn,
1048
0
            dirfsp,
1049
0
            atname,
1050
0
            unlink_flags);
1051
0
    if (retval != 0) {
1052
0
      status = map_nt_error_from_unix(errno);
1053
0
      TALLOC_FREE(atname);
1054
0
      break;
1055
0
    }
1056
1057
0
    TALLOC_FREE(atname);
1058
0
  }
1059
1060
0
  TALLOC_FREE(dir_hnd);
1061
0
  return status;
1062
0
}
1063
1064
/****************************************************************************
1065
 The internals of the rmdir code - called elsewhere.
1066
****************************************************************************/
1067
1068
static NTSTATUS rmdir_internals(struct files_struct *fsp,
1069
        struct files_struct *dirfsp,
1070
        struct smb_filename *at_fname)
1071
0
{
1072
0
  struct connection_struct *conn = fsp->conn;
1073
0
  struct smb_filename *smb_dname = fsp->fsp_name;
1074
0
  struct smb_Dir *dir_hnd = NULL;
1075
0
  struct stat_ex st = {};
1076
0
  int unlink_flags = 0;
1077
0
  NTSTATUS status;
1078
0
  int ret;
1079
1080
0
  SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1081
1082
  /*
1083
   * Todo: use SMB_VFS_STATX() once it's available.
1084
   */
1085
1086
  /* Might be a symlink. */
1087
0
  ret = SMB_VFS_LSTAT(conn, smb_dname);
1088
0
  if (ret != 0) {
1089
0
    return map_nt_error_from_unix(errno);
1090
0
  }
1091
1092
0
  if (S_ISLNK(st.st_ex_mode)) {
1093
    /* Is what it points to a directory ? */
1094
0
    ret = SMB_VFS_STAT(conn, smb_dname);
1095
0
    if (ret != 0) {
1096
0
      return map_nt_error_from_unix(errno);
1097
0
    }
1098
0
    if (!(S_ISDIR(st.st_ex_mode))) {
1099
0
      return NT_STATUS_NOT_A_DIRECTORY;
1100
0
    }
1101
0
  } else {
1102
0
    unlink_flags = AT_REMOVEDIR;
1103
0
  }
1104
1105
0
  ret = SMB_VFS_UNLINKAT(conn, dirfsp, at_fname, unlink_flags);
1106
0
  if (ret == 0) {
1107
0
    return NT_STATUS_OK;
1108
0
  }
1109
1110
0
  if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1111
0
    DBG_NOTICE("couldn't remove directory %s : %s\n",
1112
0
         smb_fname_str_dbg(smb_dname),
1113
0
         strerror(errno));
1114
0
    return map_nt_error_from_unix(errno);
1115
0
  }
1116
1117
  /*
1118
   * Here we know the initial directory unlink failed with
1119
   * ENOTEMPTY or EEXIST so we know there are objects within.
1120
   * If we don't have permission to delete files non
1121
   * visible to the client just fail the directory delete.
1122
   */
1123
1124
0
  if (!lp_delete_veto_files(SNUM(conn))) {
1125
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1126
0
    goto err;
1127
0
  }
1128
1129
  /*
1130
   * Check to see if the only things in this directory are
1131
   * files non-visible to the client. If not, fail the delete.
1132
   */
1133
1134
0
  status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
1135
0
  if (!NT_STATUS_IS_OK(status)) {
1136
    /*
1137
     * Note, we deliberately squash the error here
1138
     * to avoid leaking information about what we
1139
     * can't delete.
1140
     */
1141
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1142
0
    goto err;
1143
0
  }
1144
1145
0
  status = can_delete_directory_hnd(dir_hnd);
1146
0
  TALLOC_FREE(dir_hnd);
1147
1148
0
  if (!NT_STATUS_IS_OK(status)) {
1149
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1150
0
    goto err;
1151
0
  }
1152
1153
0
  status = recursive_rmdir_fsp(fsp);
1154
0
  if (!NT_STATUS_IS_OK(status)) {
1155
0
    status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1156
0
    goto err;
1157
0
  }
1158
1159
  /* Retry the rmdir */
1160
0
  ret = SMB_VFS_UNLINKAT(conn, dirfsp, at_fname, AT_REMOVEDIR);
1161
0
  if (ret != 0) {
1162
0
    status = map_nt_error_from_unix(errno);
1163
0
  }
1164
1165
0
  err:
1166
0
  if (!NT_STATUS_IS_OK(status)) {
1167
0
    DBG_NOTICE("couldn't remove directory %s : "
1168
0
       "%s\n", smb_fname_str_dbg(smb_dname),
1169
0
       nt_errstr(status));
1170
0
    return status;
1171
0
  }
1172
1173
0
  return status;
1174
0
}
1175
1176
/****************************************************************************
1177
 Close a directory opened by an NT SMB call.
1178
****************************************************************************/
1179
1180
static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1181
        enum file_close_type close_type)
1182
0
{
1183
0
  connection_struct *conn = fsp->conn;
1184
0
  struct close_share_mode_lock_state lck_state = {};
1185
0
  bool changed_user = false;
1186
0
  struct smb_filename *parent_fname = NULL;
1187
0
  struct smb_filename *base_fname = NULL;
1188
0
  NTSTATUS status = NT_STATUS_OK;
1189
0
  NTSTATUS status1 = NT_STATUS_OK;
1190
0
  NTSTATUS notify_status;
1191
0
  NTSTATUS ulstatus;
1192
1193
0
  SMB_ASSERT(fsp->fsp_flags.is_fsa);
1194
1195
0
  if (conn_using_smb2(fsp->conn->sconn)) {
1196
0
    notify_status = NT_STATUS_NOTIFY_CLEANUP;
1197
0
  } else {
1198
0
    notify_status = NT_STATUS_OK;
1199
0
  }
1200
1201
0
  assert_no_pending_aio(fsp, close_type);
1202
1203
  /*
1204
   * NT can set delete_on_close of the last open
1205
   * reference to a directory also.
1206
   */
1207
1208
0
  lck_state = (struct close_share_mode_lock_state) {
1209
0
    .fsp      = fsp,
1210
0
    .object_type    = "directory",
1211
0
    .close_type   = close_type,
1212
0
  };
1213
1214
0
  status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1215
0
               fsp->file_id,
1216
0
               close_share_mode_lock_prepare,
1217
0
               &lck_state);
1218
0
  if (!NT_STATUS_IS_OK(status)) {
1219
0
    DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1220
0
      fsp_str_dbg(fsp), nt_errstr(status));
1221
0
    log_stack_trace();
1222
0
    goto close_fd;
1223
0
  }
1224
1225
  /* Remove the oplock before potentially deleting the file. */
1226
0
  if (fsp->oplock_type != NO_OPLOCK) {
1227
0
    release_file_oplock(fsp);
1228
0
  }
1229
1230
  /*
1231
   * NT can set delete_on_close of the last open
1232
   * reference to a file.
1233
   */
1234
1235
0
  if (!lck_state.delete_object) {
1236
0
    status = NT_STATUS_OK;
1237
0
    goto done;
1238
0
  }
1239
1240
  /*
1241
   * Ok, we have to delete the directory
1242
   */
1243
0
  lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1244
1245
0
  if (lck_state.got_tokens &&
1246
0
      !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1247
0
  {
1248
    /* Become the user who requested the delete. */
1249
1250
0
    DBG_INFO("dir %s. Change user to uid %u\n",
1251
0
       fsp_str_dbg(fsp),
1252
0
       (unsigned int)lck_state.del_token->uid);
1253
1254
0
    if (!push_sec_ctx()) {
1255
0
      smb_panic("close_directory: failed to push sec_ctx.\n");
1256
0
    }
1257
1258
0
    set_sec_ctx(lck_state.del_token->uid,
1259
0
          lck_state.del_token->gid,
1260
0
          lck_state.del_token->ngroups,
1261
0
          lck_state.del_token->groups,
1262
0
          lck_state.del_nt_token);
1263
1264
0
    changed_user = true;
1265
0
  }
1266
1267
0
  status = parent_pathref(talloc_tos(),
1268
0
        conn->cwd_fsp,
1269
0
        fsp->fsp_name,
1270
0
        &parent_fname,
1271
0
        &base_fname);
1272
0
  if (!NT_STATUS_IS_OK(status)) {
1273
0
    DBG_DEBUG("parent_pathref(%s) failed: %s\n",
1274
0
        fsp_str_dbg(fsp), nt_errstr(status));
1275
0
    goto done;
1276
0
  }
1277
0
  if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1278
0
      && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1279
1280
0
    status = delete_all_streams(fsp,
1281
0
              parent_fname->fsp,
1282
0
              base_fname);
1283
0
    if (!NT_STATUS_IS_OK(status)) {
1284
0
      DEBUG(5, ("delete_all_streams failed: %s\n",
1285
0
          nt_errstr(status)));
1286
0
      goto done;
1287
0
    }
1288
0
  }
1289
1290
0
  status = rmdir_internals(fsp, parent_fname->fsp, base_fname);
1291
1292
0
  TALLOC_FREE(parent_fname);
1293
1294
0
  DBG_INFO("%s. Delete on close was set - "
1295
0
     "deleting directory returned %s.\n",
1296
0
     fsp_str_dbg(fsp),
1297
0
     nt_errstr(status));
1298
1299
  /*
1300
   * Ensure we remove any change notify requests that would
1301
   * now fail as the directory has been deleted.
1302
   */
1303
1304
0
  if (NT_STATUS_IS_OK(status)) {
1305
0
    notify_status = NT_STATUS_DELETE_PENDING;
1306
0
  }
1307
1308
0
done:
1309
0
  if (changed_user) {
1310
    /* unbecome user. */
1311
0
    pop_sec_ctx();
1312
0
  }
1313
1314
0
  ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1315
0
               lck_state.cleanup_fn,
1316
0
               &lck_state);
1317
0
  if (!NT_STATUS_IS_OK(ulstatus)) {
1318
0
    DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1319
0
      fsp_str_dbg(fsp), nt_errstr(ulstatus));
1320
0
    smb_panic("share_mode_entry_prepare_unlock() failed!");
1321
0
  }
1322
1323
0
  remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1324
1325
0
  if (lck_state.delete_object && NT_STATUS_IS_OK(status)) {
1326
0
    const struct smb2_lease *lease = fsp_get_smb2_lease(fsp);
1327
1328
0
    if (lease != NULL) {
1329
      /*
1330
       * If parent lease key of handle on which delete
1331
       * disposition was set does not match the parent lease
1332
       * key of last closed handle, break all leases on the
1333
       * parent directory.
1334
       */
1335
0
      if (!smb2_lease_key_equal(&lease->parent_lease_key,
1336
0
              &lck_state.parent_lease_key))
1337
0
      {
1338
0
        lease = NULL;
1339
0
      }
1340
0
    }
1341
0
    notify_fname(conn,
1342
0
           NOTIFY_ACTION_REMOVED |
1343
0
           NOTIFY_ACTION_DIRLEASE_BREAK,
1344
0
           FILE_NOTIFY_CHANGE_DIR_NAME,
1345
0
           fsp->fsp_name,
1346
0
           lease);
1347
0
  }
1348
1349
0
close_fd:
1350
0
  status1 = fd_close(fsp);
1351
1352
0
  if (!NT_STATUS_IS_OK(status1)) {
1353
0
    DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1354
0
        fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1355
0
        strerror(errno)));
1356
0
  }
1357
1358
0
  if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1359
0
    status = status1;
1360
0
  }
1361
0
  return status;
1362
0
}
1363
1364
/****************************************************************************
1365
 Rundown all SMB-related dependencies of a files struct
1366
****************************************************************************/
1367
1368
NTSTATUS close_file_smb(struct smb_request *req,
1369
      struct files_struct *fsp,
1370
      enum file_close_type close_type)
1371
0
{
1372
0
  NTSTATUS status;
1373
1374
  /*
1375
   * This fsp can never be an internal dirfsp. They must
1376
   * be explicitly closed by TALLOC_FREE of the dir handle.
1377
   */
1378
0
  SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1379
1380
  /*
1381
   * Never call directly on a base fsp
1382
   */
1383
0
  SMB_ASSERT(fsp->stream_fsp == NULL);
1384
1385
0
  if (fsp->fake_file_handle != NULL) {
1386
    /*
1387
     * Named pipes are opened as fake files and
1388
     * can have pending aio requests. Ensure
1389
     * we clear out all pending aio on force
1390
     * shutdown of named pipes also.
1391
     * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
1392
     */
1393
0
    assert_no_pending_aio(fsp, close_type);
1394
0
    status = close_fake_file(req, fsp);
1395
0
  } else if (fsp->print_file != NULL) {
1396
    /* FIXME: return spool errors */
1397
0
    print_spool_end(fsp, close_type);
1398
0
    fd_close(fsp);
1399
0
    status = NT_STATUS_OK;
1400
0
  } else if (!fsp->fsp_flags.is_fsa) {
1401
0
    if (close_type == NORMAL_CLOSE) {
1402
0
      DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1403
0
        "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1404
0
        fsp_str_dbg(fsp),
1405
0
        fsp->fsp_flags.is_fsa,
1406
0
        fsp->fsp_flags.is_pathref,
1407
0
        fsp->fsp_flags.is_directory);
1408
0
    }
1409
0
    SMB_ASSERT(close_type != NORMAL_CLOSE);
1410
0
    fd_close(fsp);
1411
0
    status = NT_STATUS_OK;
1412
0
  } else if (fsp->fsp_flags.is_directory) {
1413
0
    status = close_directory(req, fsp, close_type);
1414
0
  } else {
1415
0
    status = close_normal_file(req, fsp, close_type);
1416
0
  }
1417
1418
0
  if (fsp_is_alternate_stream(fsp)) {
1419
    /*
1420
     * fsp was a stream, its base_fsp can't be a stream
1421
     * as well
1422
     */
1423
0
    SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1424
1425
    /*
1426
     * There's a 1:1 relationship between fsp and a base_fsp
1427
     */
1428
0
    SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1429
1430
    /*
1431
     * Make base_fsp look standalone now
1432
     */
1433
0
    fsp->base_fsp->stream_fsp = NULL;
1434
1435
0
    close_file_free(req, &fsp->base_fsp, close_type);
1436
0
  }
1437
1438
0
  fsp_unbind_smb(req, fsp);
1439
1440
0
  return status;
1441
0
}
1442
1443
NTSTATUS close_file_free(struct smb_request *req,
1444
       struct files_struct **_fsp,
1445
       enum file_close_type close_type)
1446
0
{
1447
0
  struct files_struct *fsp = *_fsp;
1448
0
  NTSTATUS status;
1449
1450
0
  status = close_file_smb(req, fsp, close_type);
1451
1452
0
  file_free(req, fsp);
1453
0
        *_fsp = NULL;
1454
1455
0
  return status;
1456
0
}
1457
1458
/****************************************************************************
1459
 Deal with an (authorized) message to close a file given the share mode
1460
 entry.
1461
****************************************************************************/
1462
1463
void msg_close_file(struct messaging_context *msg_ctx,
1464
      void *private_data,
1465
      uint32_t msg_type,
1466
      struct server_id server_id,
1467
      DATA_BLOB *data)
1468
0
{
1469
0
  struct oplock_break_message msg;
1470
0
  enum ndr_err_code ndr_err;
1471
0
  files_struct *fsp = NULL;
1472
0
  struct smbd_server_connection *sconn =
1473
0
    talloc_get_type_abort(private_data,
1474
0
    struct smbd_server_connection);
1475
1476
0
  ndr_err = ndr_pull_struct_blob_all_noalloc(
1477
0
    data,
1478
0
    &msg,
1479
0
    (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
1480
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1481
0
    DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
1482
0
        ndr_errstr(ndr_err));
1483
0
    return;
1484
0
  }
1485
1486
0
  fsp = file_find_dif(sconn, msg.id, msg.share_file_id);
1487
0
  if (!fsp) {
1488
0
    DEBUG(10,("msg_close_file: failed to find file.\n"));
1489
0
    return;
1490
0
  }
1491
0
  close_file_free(NULL, &fsp, NORMAL_CLOSE);
1492
0
}