Line data Source code
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 354848 : static NTSTATUS check_magic(struct files_struct *fsp)
44 : {
45 576 : int ret;
46 576 : const struct loadparm_substitution *lp_sub =
47 354848 : loadparm_s3_global_substitution();
48 354848 : const char *magic_output = NULL;
49 576 : SMB_STRUCT_STAT st;
50 576 : int tmp_fd, outfd;
51 354848 : TALLOC_CTX *ctx = NULL;
52 576 : const char *p;
53 354848 : struct connection_struct *conn = fsp->conn;
54 354848 : char *fname = NULL;
55 576 : NTSTATUS status;
56 :
57 354848 : if (!*lp_magic_script(talloc_tos(), lp_sub, SNUM(conn))) {
58 354848 : return NT_STATUS_OK;
59 : }
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 : } else {
70 0 : p++;
71 : }
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 : }
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 : } else {
81 0 : magic_output = talloc_asprintf(ctx,
82 : "%s.out",
83 : fname);
84 : }
85 0 : if (!magic_output) {
86 0 : status = NT_STATUS_NO_MEMORY;
87 0 : goto out;
88 : }
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 : }
96 :
97 0 : if (chmod(fname, 0755) == -1) {
98 0 : status = map_nt_error_from_unix(errno);
99 0 : goto out;
100 : }
101 0 : ret = smbrun(p, &tmp_fd, NULL);
102 0 : DEBUG(3,("Invoking magic command %s gave %d\n",
103 : 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 : }
110 0 : status = NT_STATUS_UNSUCCESSFUL;
111 0 : goto out;
112 : }
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 : }
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 : }
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 : }
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 : }
141 :
142 0 : status = NT_STATUS_OK;
143 :
144 0 : out:
145 0 : TALLOC_FREE(ctx);
146 0 : return status;
147 : }
148 :
149 : /****************************************************************************
150 : Delete all streams
151 : ****************************************************************************/
152 :
153 149384 : NTSTATUS delete_all_streams(connection_struct *conn,
154 : const struct smb_filename *smb_fname)
155 : {
156 149384 : struct stream_struct *stream_info = NULL;
157 381 : unsigned int i;
158 149384 : unsigned int num_streams = 0;
159 149384 : TALLOC_CTX *frame = talloc_stackframe();
160 381 : NTSTATUS status;
161 :
162 149384 : status = vfs_fstreaminfo(smb_fname->fsp, talloc_tos(),
163 : &num_streams, &stream_info);
164 :
165 149384 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
166 0 : DEBUG(10, ("no streams around\n"));
167 0 : TALLOC_FREE(frame);
168 0 : return NT_STATUS_OK;
169 : }
170 :
171 149384 : if (!NT_STATUS_IS_OK(status)) {
172 0 : DEBUG(10, ("vfs_fstreaminfo failed: %s\n",
173 : nt_errstr(status)));
174 0 : goto fail;
175 : }
176 :
177 149384 : DEBUG(10, ("delete_all_streams found %d streams\n",
178 : num_streams));
179 :
180 149384 : if (num_streams == 0) {
181 10592 : TALLOC_FREE(frame);
182 10592 : return NT_STATUS_OK;
183 : }
184 :
185 278190 : for (i=0; i<num_streams; i++) {
186 318 : int res;
187 318 : struct smb_filename *smb_fname_stream;
188 :
189 139398 : if (strequal(stream_info[i].name, "::$DATA")) {
190 138737 : continue;
191 : }
192 :
193 661 : status = synthetic_pathref(talloc_tos(),
194 : conn->cwd_fsp,
195 661 : smb_fname->base_name,
196 661 : stream_info[i].name,
197 : NULL,
198 661 : smb_fname->twrp,
199 661 : (smb_fname->flags &
200 : ~SMB_FILENAME_POSIX_PATH),
201 : &smb_fname_stream);
202 661 : if (!NT_STATUS_IS_OK(status)) {
203 0 : DEBUG(0, ("talloc_aprintf failed\n"));
204 0 : status = NT_STATUS_NO_MEMORY;
205 0 : goto fail;
206 : }
207 :
208 661 : res = SMB_VFS_UNLINKAT(conn,
209 : conn->cwd_fsp,
210 : smb_fname_stream,
211 : 0);
212 :
213 661 : if (res == -1) {
214 0 : status = map_nt_error_from_unix(errno);
215 0 : DEBUG(10, ("Could not delete stream %s: %s\n",
216 : smb_fname_str_dbg(smb_fname_stream),
217 : strerror(errno)));
218 0 : TALLOC_FREE(smb_fname_stream);
219 0 : break;
220 : }
221 661 : TALLOC_FREE(smb_fname_stream);
222 : }
223 :
224 138792 : fail:
225 138792 : TALLOC_FREE(frame);
226 138792 : return status;
227 : }
228 :
229 : struct has_other_nonposix_opens_state {
230 : files_struct *fsp;
231 : bool found_another;
232 : };
233 :
234 171105 : static bool has_other_nonposix_opens_fn(
235 : struct share_mode_entry *e,
236 : bool *modified,
237 : void *private_data)
238 : {
239 171105 : struct has_other_nonposix_opens_state *state = private_data;
240 171105 : struct files_struct *fsp = state->fsp;
241 :
242 171105 : if (e->name_hash != fsp->name_hash) {
243 4 : return false;
244 : }
245 171101 : if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
246 1598 : return false;
247 : }
248 169503 : if (e->share_file_id == fh_get_gen_id(fsp->fh)) {
249 169247 : struct server_id self = messaging_server_id(
250 169247 : fsp->conn->sconn->msg_ctx);
251 169247 : if (server_id_equal(&self, &e->pid)) {
252 169246 : return false;
253 : }
254 : }
255 257 : if (share_entry_stale_pid(e)) {
256 0 : return false;
257 : }
258 :
259 257 : state->found_another = true;
260 257 : return true;
261 : }
262 :
263 170918 : bool has_other_nonposix_opens(struct share_mode_lock *lck,
264 : struct files_struct *fsp)
265 : {
266 170918 : struct has_other_nonposix_opens_state state = { .fsp = fsp };
267 350 : bool ok;
268 :
269 170918 : ok = share_mode_forall_entries(
270 : lck, has_other_nonposix_opens_fn, &state);
271 170918 : if (!ok) {
272 0 : return false;
273 : }
274 170918 : return state.found_another;
275 : }
276 :
277 : struct close_share_mode_lock_state {
278 : struct share_mode_entry_prepare_state prepare_state;
279 : const char *object_type;
280 : struct files_struct *fsp;
281 : enum file_close_type close_type;
282 : bool delete_object;
283 : bool got_tokens;
284 : const struct security_unix_token *del_token;
285 : const struct security_token *del_nt_token;
286 : bool reset_delete_on_close;
287 : share_mode_entry_prepare_unlock_fn_t cleanup_fn;
288 : };
289 :
290 440827 : static void close_share_mode_lock_prepare(struct share_mode_lock *lck,
291 : bool *keep_locked,
292 : void *private_data)
293 : {
294 440827 : struct close_share_mode_lock_state *state =
295 : (struct close_share_mode_lock_state *)private_data;
296 440827 : struct files_struct *fsp = state->fsp;
297 938 : bool normal_close;
298 938 : bool ok;
299 :
300 : /*
301 : * By default drop the g_lock again if we leave the
302 : * tdb chainlock.
303 : */
304 440827 : *keep_locked = false;
305 :
306 440827 : if (fsp->oplock_type != NO_OPLOCK) {
307 2524 : ok = remove_share_oplock(lck, fsp);
308 2524 : if (!ok) {
309 0 : struct file_id_buf buf;
310 :
311 0 : DBG_ERR("failed to remove share oplock for "
312 : "%s %s, %s, %s\n",
313 : state->object_type,
314 : fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
315 : file_id_str_buf(fsp->file_id, &buf));
316 : }
317 : }
318 :
319 440827 : if (fsp->fsp_flags.write_time_forced) {
320 967 : NTTIME mtime = share_mode_changed_write_time(lck);
321 967 : struct timespec ts = nt_time_to_full_timespec(mtime);
322 :
323 967 : DBG_DEBUG("write time forced for %s %s\n",
324 : state->object_type, fsp_str_dbg(fsp));
325 967 : set_close_write_time(fsp, ts);
326 439860 : } else if (fsp->fsp_flags.update_write_time_on_close) {
327 : /* Someone had a pending write. */
328 100 : if (is_omit_timespec(&fsp->close_write_time)) {
329 69 : DBG_DEBUG("update to current time for %s %s\n",
330 : state->object_type, fsp_str_dbg(fsp));
331 : /* Update to current time due to "normal" write. */
332 69 : set_close_write_time(fsp, timespec_current());
333 : } else {
334 31 : DBG_DEBUG("write time pending for %s %s\n",
335 : state->object_type, fsp_str_dbg(fsp));
336 : /* Update to time set on close call. */
337 31 : set_close_write_time(fsp, fsp->close_write_time);
338 : }
339 : }
340 :
341 440967 : if (fsp->fsp_flags.initial_delete_on_close &&
342 137074 : !is_delete_on_close_set(lck, fsp->name_hash)) {
343 : /* Initial delete on close was set and no one else
344 : * wrote a real delete on close. */
345 :
346 137067 : fsp->fsp_flags.delete_on_close = true;
347 137067 : set_delete_on_close_lck(fsp, lck,
348 137067 : fsp->conn->session_info->security_token,
349 137067 : fsp->conn->session_info->unix_token);
350 : }
351 :
352 611497 : state->delete_object = is_delete_on_close_set(lck, fsp->name_hash) &&
353 170670 : !has_other_nonposix_opens(lck, fsp);
354 :
355 : /*
356 : * NT can set delete_on_close of the last open
357 : * reference to a file.
358 : */
359 :
360 440827 : normal_close = (state->close_type == NORMAL_CLOSE || state->close_type == SHUTDOWN_CLOSE);
361 440827 : if (!normal_close) {
362 : /*
363 : * Never try to delete the file/directory for ERROR_CLOSE
364 : */
365 2607 : state->delete_object = false;
366 : }
367 :
368 440827 : if (!state->delete_object) {
369 270406 : ok = del_share_mode(lck, fsp);
370 270406 : if (!ok) {
371 0 : DBG_ERR("Could not delete share entry for %s %s\n",
372 : state->object_type, fsp_str_dbg(fsp));
373 : }
374 270406 : return;
375 : }
376 :
377 : /*
378 : * We're going to remove the file/directory
379 : * so keep the g_lock after the tdb chainlock
380 : * is left, so we hold the share_mode_lock
381 : * also during the deletion
382 : */
383 170421 : *keep_locked = true;
384 :
385 170421 : state->got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
386 : &state->del_nt_token, &state->del_token);
387 170421 : if (state->close_type != ERROR_CLOSE) {
388 170421 : SMB_ASSERT(state->got_tokens);
389 : }
390 : }
391 :
392 170421 : static void close_share_mode_lock_cleanup(struct share_mode_lock *lck,
393 : void *private_data)
394 : {
395 170421 : struct close_share_mode_lock_state *state =
396 : (struct close_share_mode_lock_state *)private_data;
397 170421 : struct files_struct *fsp = state->fsp;
398 336 : bool ok;
399 :
400 170421 : if (state->reset_delete_on_close) {
401 159282 : reset_delete_on_close_lck(fsp, lck);
402 : }
403 :
404 170421 : ok = del_share_mode(lck, fsp);
405 170421 : if (!ok) {
406 0 : DBG_ERR("Could not delete share entry for %s %s\n",
407 : state->object_type, fsp_str_dbg(fsp));
408 : }
409 170421 : }
410 :
411 : /****************************************************************************
412 : Deal with removing a share mode on last close.
413 : ****************************************************************************/
414 :
415 358072 : static NTSTATUS close_remove_share_mode(files_struct *fsp,
416 : enum file_close_type close_type)
417 : {
418 358072 : connection_struct *conn = fsp->conn;
419 358072 : struct close_share_mode_lock_state lck_state = {};
420 358072 : bool changed_user = false;
421 358072 : NTSTATUS status = NT_STATUS_OK;
422 592 : NTSTATUS tmp_status;
423 592 : NTSTATUS ulstatus;
424 592 : struct file_id id;
425 358072 : struct smb_filename *parent_fname = NULL;
426 358072 : struct smb_filename *base_fname = NULL;
427 592 : int ret;
428 :
429 : /* Ensure any pending write time updates are done. */
430 358072 : if (fsp->update_write_time_event) {
431 5203 : fsp_flush_write_time_update(fsp);
432 : }
433 :
434 : /*
435 : * Lock the share entries, and determine if we should delete
436 : * on close. If so delete whilst the lock is still in effect.
437 : * This prevents race conditions with the file being created. JRA.
438 : */
439 :
440 358072 : lck_state = (struct close_share_mode_lock_state) {
441 : .fsp = fsp,
442 : .object_type = "file",
443 : .close_type = close_type,
444 : };
445 :
446 358072 : status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
447 : fsp->file_id,
448 : close_share_mode_lock_prepare,
449 592 : &lck_state);
450 358072 : if (!NT_STATUS_IS_OK(status)) {
451 0 : DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
452 : fsp_str_dbg(fsp), nt_errstr(status));
453 0 : return status;
454 : }
455 :
456 : /* Remove the oplock before potentially deleting the file. */
457 358072 : if (fsp->oplock_type != NO_OPLOCK) {
458 2524 : release_file_oplock(fsp);
459 : }
460 :
461 : /*
462 : * NT can set delete_on_close of the last open
463 : * reference to a file.
464 : */
465 :
466 358072 : if (!lck_state.delete_object) {
467 198786 : status = NT_STATUS_OK;
468 198786 : goto done;
469 : }
470 :
471 : /*
472 : * Ok, we have to delete the file
473 : */
474 159286 : lck_state.cleanup_fn = close_share_mode_lock_cleanup;
475 :
476 159286 : DBG_INFO("%s. Delete on close was set - deleting file.\n",
477 : fsp_str_dbg(fsp));
478 :
479 : /*
480 : * Don't try to update the write time when we delete the file
481 : */
482 159286 : fsp->fsp_flags.update_write_time_on_close = false;
483 :
484 159558 : if (lck_state.got_tokens &&
485 159286 : !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
486 : {
487 : /* Become the user who requested the delete. */
488 :
489 214 : DBG_INFO("file %s. Change user to uid %u\n",
490 : fsp_str_dbg(fsp),
491 : (unsigned int)lck_state.del_token->uid);
492 :
493 214 : if (!push_sec_ctx()) {
494 0 : smb_panic("close_remove_share_mode: file %s. failed to push "
495 : "sec_ctx.\n");
496 : }
497 :
498 214 : set_sec_ctx(lck_state.del_token->uid,
499 214 : lck_state.del_token->gid,
500 214 : lck_state.del_token->ngroups,
501 214 : lck_state.del_token->groups,
502 : lck_state.del_nt_token);
503 :
504 214 : changed_user = true;
505 : }
506 :
507 : /* We can only delete the file if the name we have is still valid and
508 : hasn't been renamed. */
509 :
510 159286 : tmp_status = vfs_stat_fsp(fsp);
511 159286 : if (!NT_STATUS_IS_OK(tmp_status)) {
512 0 : DBG_INFO("file %s. Delete on close "
513 : "was set and stat failed with error %s\n",
514 : fsp_str_dbg(fsp),
515 : nt_errstr(tmp_status));
516 : /*
517 : * Don't save the errno here, we ignore this error
518 : */
519 0 : goto done;
520 : }
521 :
522 159286 : id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
523 :
524 159286 : if (!file_id_equal(&fsp->file_id, &id)) {
525 0 : struct file_id_buf ftmp1, ftmp2;
526 4 : DBG_INFO("file %s. Delete on close "
527 : "was set and dev and/or inode does not match\n",
528 : fsp_str_dbg(fsp));
529 4 : DBG_INFO("file %s. stored file_id %s, stat file_id %s\n",
530 : fsp_str_dbg(fsp),
531 : file_id_str_buf(fsp->file_id, &ftmp1),
532 : file_id_str_buf(id, &ftmp2));
533 : /*
534 : * Don't save the errno here, we ignore this error
535 : */
536 4 : goto done;
537 : }
538 :
539 159282 : if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
540 138505 : && !fsp_is_alternate_stream(fsp)) {
541 :
542 138047 : status = delete_all_streams(conn, fsp->fsp_name);
543 :
544 138047 : if (!NT_STATUS_IS_OK(status)) {
545 0 : DEBUG(5, ("delete_all_streams failed: %s\n",
546 : nt_errstr(status)));
547 0 : goto done;
548 : }
549 : }
550 :
551 159282 : if (fsp->fsp_flags.kernel_share_modes_taken) {
552 : /*
553 : * A file system sharemode could block the unlink;
554 : * remove filesystem sharemodes first.
555 : */
556 0 : ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
557 0 : if (ret == -1) {
558 0 : DBG_INFO("Removing file system sharemode for %s "
559 : "failed: %s\n",
560 : fsp_str_dbg(fsp), strerror(errno));
561 : }
562 :
563 0 : fsp->fsp_flags.kernel_share_modes_taken = false;
564 : }
565 :
566 159282 : status = parent_pathref(talloc_tos(),
567 : conn->cwd_fsp,
568 159282 : fsp->fsp_name,
569 : &parent_fname,
570 : &base_fname);
571 159282 : if (!NT_STATUS_IS_OK(status)) {
572 0 : goto done;
573 : }
574 :
575 159282 : ret = SMB_VFS_UNLINKAT(conn,
576 : parent_fname->fsp,
577 : base_fname,
578 : 0);
579 159282 : TALLOC_FREE(parent_fname);
580 159282 : base_fname = NULL;
581 159282 : if (ret != 0) {
582 : /*
583 : * This call can potentially fail as another smbd may
584 : * have had the file open with delete on close set and
585 : * deleted it when its last reference to this file
586 : * went away. Hence we log this but not at debug level
587 : * zero.
588 : */
589 :
590 0 : DBG_INFO("file %s. Delete on close "
591 : "was set and unlink failed with error %s\n",
592 : fsp_str_dbg(fsp),
593 : strerror(errno));
594 :
595 0 : status = map_nt_error_from_unix(errno);
596 : }
597 :
598 : /* As we now have POSIX opens which can unlink
599 : * with other open files we may have taken
600 : * this code path with more than one share mode
601 : * entry - ensure we only delete once by resetting
602 : * the delete on close flag. JRA.
603 : */
604 :
605 159282 : fsp->fsp_flags.delete_on_close = false;
606 159282 : fsp->fsp_flags.fstat_before_close = false;
607 159282 : lck_state.reset_delete_on_close = true;
608 :
609 357752 : done:
610 :
611 358072 : if (changed_user) {
612 : /* unbecome user. */
613 214 : pop_sec_ctx();
614 : }
615 :
616 358072 : if (fsp->fsp_flags.kernel_share_modes_taken) {
617 : /* remove filesystem sharemodes */
618 0 : ret = SMB_VFS_FILESYSTEM_SHAREMODE(fsp, 0, 0);
619 0 : if (ret == -1) {
620 0 : DBG_INFO("Removing file system sharemode for "
621 : "%s failed: %s\n",
622 : fsp_str_dbg(fsp), strerror(errno));
623 : }
624 : }
625 :
626 358072 : ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
627 : lck_state.cleanup_fn,
628 592 : &lck_state);
629 358072 : if (!NT_STATUS_IS_OK(ulstatus)) {
630 0 : DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
631 : fsp_str_dbg(fsp), nt_errstr(ulstatus));
632 0 : smb_panic("share_mode_entry_prepare_unlock() failed!");
633 : }
634 :
635 358072 : if (lck_state.delete_object) {
636 159286 : notify_fname(conn, NOTIFY_ACTION_REMOVED,
637 : FILE_NOTIFY_CHANGE_FILE_NAME,
638 159286 : fsp->fsp_name->base_name);
639 : }
640 :
641 358072 : return status;
642 : }
643 :
644 32151 : void set_close_write_time(struct files_struct *fsp, struct timespec ts)
645 : {
646 32151 : DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
647 :
648 32151 : if (is_omit_timespec(&ts)) {
649 30765 : return;
650 : }
651 1098 : fsp->fsp_flags.write_time_forced = false;
652 1098 : fsp->fsp_flags.update_write_time_on_close = true;
653 1098 : fsp->close_write_time = ts;
654 : }
655 :
656 25 : static void update_write_time_on_close_share_mode_fn(struct share_mode_lock *lck,
657 : void *private_data)
658 : {
659 1 : struct files_struct *fsp =
660 25 : talloc_get_type_abort(private_data,
661 : struct files_struct);
662 25 : NTTIME share_mtime = share_mode_changed_write_time(lck);
663 :
664 : /*
665 : * On close if we're changing the real file time we
666 : * must update it in the open file db too.
667 : */
668 25 : share_mode_set_old_write_time(lck, fsp->close_write_time);
669 :
670 : /*
671 : * Close write times overwrite sticky write times
672 : * so we must replace any sticky write time here.
673 : */
674 25 : if (!null_nttime(share_mtime)) {
675 16 : share_mode_set_changed_write_time(lck, fsp->close_write_time);
676 : }
677 25 : }
678 :
679 358185 : static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
680 : {
681 593 : struct smb_file_time ft;
682 593 : NTSTATUS status;
683 :
684 358185 : init_smb_file_time(&ft);
685 :
686 358185 : if (!(fsp->fsp_flags.update_write_time_on_close)) {
687 357133 : return NT_STATUS_OK;
688 : }
689 :
690 1052 : if (is_omit_timespec(&fsp->close_write_time)) {
691 5 : fsp->close_write_time = timespec_current();
692 : }
693 :
694 : /* Ensure we have a valid stat struct for the source. */
695 1052 : status = vfs_stat_fsp(fsp);
696 1052 : if (!NT_STATUS_IS_OK(status)) {
697 0 : return status;
698 : }
699 :
700 1052 : if (!VALID_STAT(fsp->fsp_name->st)) {
701 : /* if it doesn't seem to be a real file */
702 0 : return NT_STATUS_OK;
703 : }
704 :
705 : /*
706 : * We're being called after close_remove_share_mode() inside
707 : * close_normal_file() so it's quite normal to not have an
708 : * existing share. So just ignore the result of
709 : * share_mode_do_locked_vfs_denied()...
710 : */
711 1052 : share_mode_do_locked_vfs_denied(fsp->file_id,
712 : update_write_time_on_close_share_mode_fn,
713 : fsp);
714 :
715 1052 : ft.mtime = fsp->close_write_time;
716 : /* As this is a close based update, we are not directly changing the
717 : file attributes from a client call, but indirectly from a write. */
718 1052 : status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
719 1052 : if (!NT_STATUS_IS_OK(status)) {
720 0 : DEBUG(10,("update_write_time_on_close: smb_set_file_time "
721 : "on file %s returned %s\n",
722 : fsp_str_dbg(fsp),
723 : nt_errstr(status)));
724 0 : return status;
725 : }
726 :
727 1052 : return status;
728 : }
729 :
730 1428698 : static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
731 : {
732 1428698 : if (!NT_STATUS_IS_OK(s1)) {
733 0 : return s1;
734 : }
735 1428698 : return s2;
736 : }
737 :
738 458548 : static void assert_no_pending_aio(struct files_struct *fsp,
739 : enum file_close_type close_type)
740 : {
741 458548 : struct smbXsrv_client *client = global_smbXsrv_client;
742 1559 : size_t num_connections_alive;
743 458548 : unsigned num_requests = fsp->num_aio_requests;
744 :
745 458548 : if (num_requests == 0) {
746 456987 : return;
747 : }
748 :
749 2 : num_connections_alive = smbXsrv_client_valid_connections(client);
750 :
751 2 : if (close_type == SHUTDOWN_CLOSE && num_connections_alive == 0) {
752 : /*
753 : * fsp->aio_requests and the contents (fsp->aio_requests[x])
754 : * are both independently owned by fsp and are not in a
755 : * talloc hierarchy. This allows the fsp->aio_requests array to
756 : * be reallocated independently of the array contents so it can
757 : * grow on demand.
758 : *
759 : * This means we must ensure order of deallocation
760 : * on a SHUTDOWN_CLOSE by deallocating the fsp->aio_requests[x]
761 : * contents first, as their destructors access the
762 : * fsp->aio_request array. If we don't deallocate them
763 : * first, when fsp is deallocated fsp->aio_requests
764 : * could have been deallocated *before* its contents
765 : * fsp->aio_requests[x], causing a crash.
766 : */
767 6 : while (fsp->num_aio_requests != 0) {
768 : /*
769 : * NB. We *MUST* use
770 : * talloc_free(fsp->aio_requests[0]),
771 : * and *NOT* TALLOC_FREE() here, as
772 : * TALLOC_FREE(fsp->aio_requests[0])
773 : * will overwrite any new contents of
774 : * fsp->aio_requests[0] that were
775 : * copied into it via the destructor
776 : * aio_del_req_from_fsp().
777 : *
778 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14515
779 : */
780 4 : talloc_free(fsp->aio_requests[0]);
781 : }
782 2 : return;
783 : }
784 :
785 0 : DBG_ERR("fsp->num_aio_requests=%u\n", num_requests);
786 0 : smb_panic("can not close with outstanding aio requests");
787 1559 : return;
788 : }
789 :
790 : /****************************************************************************
791 : Close a file.
792 :
793 : close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
794 : printing and magic scripts are only run on normal close.
795 : delete on close is done on normal and shutdown close.
796 : ****************************************************************************/
797 :
798 358345 : static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
799 : enum file_close_type close_type)
800 : {
801 358345 : NTSTATUS status = NT_STATUS_OK;
802 593 : NTSTATUS tmp;
803 358345 : connection_struct *conn = fsp->conn;
804 358345 : bool is_durable = false;
805 :
806 358345 : SMB_ASSERT(fsp->fsp_flags.is_fsa);
807 :
808 358345 : assert_no_pending_aio(fsp, close_type);
809 :
810 358393 : while (talloc_array_length(fsp->blocked_smb1_lock_reqs) != 0) {
811 48 : smbd_smb1_brl_finish_by_req(
812 48 : fsp->blocked_smb1_lock_reqs[0],
813 48 : NT_STATUS_RANGE_NOT_LOCKED);
814 : }
815 :
816 : /*
817 : * If we're flushing on a close we can get a write
818 : * error here, we must remember this.
819 : */
820 :
821 358345 : if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
822 350496 : is_durable = fsp->op->global->durable;
823 : }
824 :
825 358345 : if (close_type != SHUTDOWN_CLOSE) {
826 356833 : is_durable = false;
827 : }
828 :
829 357769 : if (is_durable) {
830 168 : DATA_BLOB new_cookie = data_blob_null;
831 :
832 168 : tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
833 : fsp->op->global->backend_cookie,
834 : fsp->op,
835 : &new_cookie);
836 168 : if (NT_STATUS_IS_OK(tmp)) {
837 0 : struct timeval tv;
838 0 : NTTIME now;
839 :
840 160 : if (req != NULL) {
841 28 : tv = req->request_time;
842 : } else {
843 132 : tv = timeval_current();
844 : }
845 160 : now = timeval_to_nttime(&tv);
846 :
847 160 : data_blob_free(&fsp->op->global->backend_cookie);
848 160 : fsp->op->global->backend_cookie = new_cookie;
849 :
850 160 : fsp->op->compat = NULL;
851 160 : tmp = smbXsrv_open_close(fsp->op, now);
852 160 : if (!NT_STATUS_IS_OK(tmp)) {
853 0 : DEBUG(1, ("Failed to update smbXsrv_open "
854 : "record when disconnecting durable "
855 : "handle for file %s: %s - "
856 : "proceeding with normal close\n",
857 : fsp_str_dbg(fsp), nt_errstr(tmp)));
858 : }
859 160 : scavenger_schedule_disconnected(fsp);
860 : } else {
861 8 : DEBUG(1, ("Failed to disconnect durable handle for "
862 : "file %s: %s - proceeding with normal "
863 : "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
864 : }
865 168 : if (!NT_STATUS_IS_OK(tmp)) {
866 8 : is_durable = false;
867 : }
868 : }
869 :
870 358345 : if (is_durable) {
871 : /*
872 : * This is the case where we successfully disconnected
873 : * a durable handle and closed the underlying file.
874 : * In all other cases, we proceed with a genuine close.
875 : */
876 160 : DEBUG(10, ("%s disconnected durable handle for file %s\n",
877 : conn->session_info->unix_info->unix_name,
878 : fsp_str_dbg(fsp)));
879 160 : return NT_STATUS_OK;
880 : }
881 :
882 358185 : if (fsp->op != NULL) {
883 : /*
884 : * Make sure the handle is not marked as durable anymore
885 : */
886 350336 : fsp->op->global->durable = false;
887 : }
888 :
889 : /* If this is an old DOS or FCB open and we have multiple opens on
890 : the same handle we only have one share mode. Ensure we only remove
891 : the share mode on the last close. */
892 :
893 358185 : if (fh_get_refcount(fsp->fh) == 1) {
894 : /* Should we return on error here... ? */
895 358072 : tmp = close_remove_share_mode(fsp, close_type);
896 358072 : status = ntstatus_keeperror(status, tmp);
897 : }
898 :
899 358185 : locking_close_file(fsp, close_type);
900 :
901 : /*
902 : * Ensure pending modtime is set before closing underlying fd.
903 : */
904 :
905 358185 : tmp = update_write_time_on_close(fsp);
906 358185 : if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
907 : /*
908 : * Someone renamed the file or a parent directory containing
909 : * this file. We can't do anything about this, eat the error.
910 : */
911 0 : tmp = NT_STATUS_OK;
912 : }
913 358185 : status = ntstatus_keeperror(status, tmp);
914 :
915 358185 : tmp = fd_close(fsp);
916 358185 : status = ntstatus_keeperror(status, tmp);
917 :
918 : /* check for magic scripts */
919 358185 : if (close_type == NORMAL_CLOSE) {
920 354848 : tmp = check_magic(fsp);
921 354848 : status = ntstatus_keeperror(status, tmp);
922 : }
923 :
924 358185 : DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
925 : conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
926 : conn->num_files_open - 1,
927 : nt_errstr(status) ));
928 :
929 358185 : return status;
930 : }
931 : /****************************************************************************
932 : Function used by reply_rmdir to delete an entire directory
933 : tree recursively. Return True on ok, False on fail.
934 : ****************************************************************************/
935 :
936 0 : NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
937 : connection_struct *conn,
938 : struct smb_filename *smb_dname)
939 : {
940 0 : const char *dname = NULL;
941 0 : char *talloced = NULL;
942 0 : struct smb_Dir *dir_hnd = NULL;
943 0 : struct files_struct *dirfsp = NULL;
944 0 : int retval;
945 0 : NTSTATUS status = NT_STATUS_OK;
946 :
947 0 : SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
948 :
949 0 : status = OpenDir(talloc_tos(),
950 : conn,
951 : smb_dname,
952 : NULL,
953 : 0,
954 : &dir_hnd);
955 0 : if (!NT_STATUS_IS_OK(status)) {
956 0 : return status;
957 : }
958 :
959 0 : dirfsp = dir_hnd_fetch_fsp(dir_hnd);
960 :
961 0 : while ((dname = ReadDirName(dir_hnd, &talloced))) {
962 0 : struct smb_filename *atname = NULL;
963 0 : struct smb_filename *smb_dname_full = NULL;
964 0 : char *fullname = NULL;
965 0 : bool do_break = true;
966 0 : int unlink_flags = 0;
967 :
968 0 : if (ISDOT(dname) || ISDOTDOT(dname)) {
969 0 : TALLOC_FREE(talloced);
970 0 : continue;
971 : }
972 :
973 : /* Construct the full name. */
974 0 : fullname = talloc_asprintf(ctx,
975 : "%s/%s",
976 : smb_dname->base_name,
977 : dname);
978 0 : if (!fullname) {
979 0 : status = NT_STATUS_NO_MEMORY;
980 0 : goto err_break;
981 : }
982 :
983 0 : smb_dname_full = synthetic_smb_fname(talloc_tos(),
984 : fullname,
985 : NULL,
986 : NULL,
987 : smb_dname->twrp,
988 : smb_dname->flags);
989 0 : if (smb_dname_full == NULL) {
990 0 : status = NT_STATUS_NO_MEMORY;
991 0 : goto err_break;
992 : }
993 :
994 0 : if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
995 0 : status = map_nt_error_from_unix(errno);
996 0 : goto err_break;
997 : }
998 :
999 0 : if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1000 0 : status = recursive_rmdir(ctx, conn, smb_dname_full);
1001 0 : if (!NT_STATUS_IS_OK(status)) {
1002 0 : goto err_break;
1003 : }
1004 0 : unlink_flags = AT_REMOVEDIR;
1005 : }
1006 :
1007 0 : status = synthetic_pathref(talloc_tos(),
1008 : dirfsp,
1009 : dname,
1010 : NULL,
1011 0 : &smb_dname_full->st,
1012 : smb_dname_full->twrp,
1013 : smb_dname_full->flags,
1014 : &atname);
1015 0 : if (!NT_STATUS_IS_OK(status)) {
1016 0 : goto err_break;
1017 : }
1018 :
1019 0 : if (!is_visible_fsp(atname->fsp)) {
1020 0 : TALLOC_FREE(smb_dname_full);
1021 0 : TALLOC_FREE(fullname);
1022 0 : TALLOC_FREE(talloced);
1023 0 : TALLOC_FREE(atname);
1024 0 : continue;
1025 : }
1026 :
1027 0 : retval = SMB_VFS_UNLINKAT(conn,
1028 : dirfsp,
1029 : atname,
1030 : unlink_flags);
1031 0 : if (retval != 0) {
1032 0 : status = map_nt_error_from_unix(errno);
1033 0 : goto err_break;
1034 : }
1035 :
1036 : /* Successful iteration. */
1037 0 : do_break = false;
1038 :
1039 0 : err_break:
1040 0 : TALLOC_FREE(smb_dname_full);
1041 0 : TALLOC_FREE(fullname);
1042 0 : TALLOC_FREE(talloced);
1043 0 : TALLOC_FREE(atname);
1044 0 : if (do_break) {
1045 0 : break;
1046 : }
1047 : }
1048 0 : TALLOC_FREE(dir_hnd);
1049 0 : return status;
1050 : }
1051 :
1052 : /****************************************************************************
1053 : The internals of the rmdir code - called elsewhere.
1054 : ****************************************************************************/
1055 :
1056 11135 : static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
1057 : {
1058 11135 : struct connection_struct *conn = fsp->conn;
1059 11135 : struct smb_filename *smb_dname = fsp->fsp_name;
1060 11135 : struct smb_filename *parent_fname = NULL;
1061 11135 : struct smb_filename *at_fname = NULL;
1062 11135 : const char *dname = NULL;
1063 11135 : char *talloced = NULL;
1064 11135 : struct smb_Dir *dir_hnd = NULL;
1065 11135 : struct files_struct *dirfsp = NULL;
1066 11135 : int unlink_flags = 0;
1067 64 : NTSTATUS status;
1068 64 : int ret;
1069 :
1070 11135 : SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
1071 :
1072 11135 : status = parent_pathref(talloc_tos(),
1073 : conn->cwd_fsp,
1074 11135 : fsp->fsp_name,
1075 : &parent_fname,
1076 : &at_fname);
1077 11135 : if (!NT_STATUS_IS_OK(status)) {
1078 0 : return status;
1079 : }
1080 :
1081 : /*
1082 : * Todo: use SMB_VFS_STATX() once it's available.
1083 : */
1084 :
1085 : /* Might be a symlink. */
1086 11135 : ret = SMB_VFS_LSTAT(conn, smb_dname);
1087 11135 : if (ret != 0) {
1088 0 : TALLOC_FREE(parent_fname);
1089 0 : return map_nt_error_from_unix(errno);
1090 : }
1091 :
1092 11135 : if (S_ISLNK(smb_dname->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 : TALLOC_FREE(parent_fname);
1097 0 : return map_nt_error_from_unix(errno);
1098 : }
1099 0 : if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
1100 0 : TALLOC_FREE(parent_fname);
1101 0 : return NT_STATUS_NOT_A_DIRECTORY;
1102 : }
1103 : } else {
1104 11071 : unlink_flags = AT_REMOVEDIR;
1105 : }
1106 :
1107 11135 : ret = SMB_VFS_UNLINKAT(conn,
1108 : parent_fname->fsp,
1109 : at_fname,
1110 : unlink_flags);
1111 11135 : if (ret == 0) {
1112 11127 : TALLOC_FREE(parent_fname);
1113 11127 : notify_fname(conn, NOTIFY_ACTION_REMOVED,
1114 : FILE_NOTIFY_CHANGE_DIR_NAME,
1115 11127 : smb_dname->base_name);
1116 11127 : return NT_STATUS_OK;
1117 : }
1118 :
1119 8 : if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
1120 0 : DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
1121 : "%s\n", smb_fname_str_dbg(smb_dname),
1122 : strerror(errno)));
1123 0 : TALLOC_FREE(parent_fname);
1124 0 : return map_nt_error_from_unix(errno);
1125 : }
1126 :
1127 : /*
1128 : * Here we know the initial directory unlink failed with
1129 : * ENOTEMPTY or EEXIST so we know there are objects within.
1130 : * If we don't have permission to delete files non
1131 : * visible to the client just fail the directory delete.
1132 : */
1133 :
1134 8 : if (!lp_delete_veto_files(SNUM(conn))) {
1135 2 : status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1136 2 : goto err;
1137 : }
1138 :
1139 : /*
1140 : * Check to see if the only thing in this directory are
1141 : * files non-visible to the client. If not, fail the delete.
1142 : */
1143 :
1144 6 : status = OpenDir(talloc_tos(),
1145 : conn,
1146 : smb_dname,
1147 : NULL,
1148 : 0,
1149 : &dir_hnd);
1150 6 : if (!NT_STATUS_IS_OK(status)) {
1151 : /*
1152 : * Note, we deliberately squash the error here
1153 : * to avoid leaking information about what we
1154 : * can't delete.
1155 : */
1156 0 : status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1157 0 : goto err;
1158 : }
1159 :
1160 6 : dirfsp = dir_hnd_fetch_fsp(dir_hnd);
1161 :
1162 22 : while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1163 18 : struct smb_filename *smb_dname_full = NULL;
1164 18 : struct smb_filename *direntry_fname = NULL;
1165 18 : char *fullname = NULL;
1166 0 : int retval;
1167 :
1168 18 : if (ISDOT(dname) || ISDOTDOT(dname)) {
1169 12 : TALLOC_FREE(talloced);
1170 16 : continue;
1171 : }
1172 6 : if (IS_VETO_PATH(conn, dname)) {
1173 2 : TALLOC_FREE(talloced);
1174 2 : continue;
1175 : }
1176 :
1177 4 : fullname = talloc_asprintf(talloc_tos(),
1178 : "%s/%s",
1179 : smb_dname->base_name,
1180 : dname);
1181 :
1182 4 : if (fullname == NULL) {
1183 0 : TALLOC_FREE(talloced);
1184 0 : status = NT_STATUS_NO_MEMORY;
1185 0 : goto err;
1186 : }
1187 :
1188 4 : smb_dname_full = synthetic_smb_fname(talloc_tos(),
1189 : fullname,
1190 : NULL,
1191 : NULL,
1192 : smb_dname->twrp,
1193 : smb_dname->flags);
1194 4 : if (smb_dname_full == NULL) {
1195 0 : TALLOC_FREE(talloced);
1196 0 : TALLOC_FREE(fullname);
1197 0 : status = NT_STATUS_NO_MEMORY;
1198 0 : goto err;
1199 : }
1200 :
1201 4 : retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1202 4 : if (retval != 0) {
1203 0 : status = map_nt_error_from_unix(errno);
1204 0 : TALLOC_FREE(talloced);
1205 0 : TALLOC_FREE(fullname);
1206 0 : TALLOC_FREE(smb_dname_full);
1207 0 : goto err;
1208 : }
1209 :
1210 4 : if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1211 : /* Could it be an msdfs link ? */
1212 4 : if (lp_host_msdfs() &&
1213 2 : lp_msdfs_root(SNUM(conn))) {
1214 0 : struct smb_filename *smb_atname;
1215 0 : smb_atname = synthetic_smb_fname(talloc_tos(),
1216 : dname,
1217 : NULL,
1218 0 : &smb_dname_full->st,
1219 0 : fsp->fsp_name->twrp,
1220 0 : fsp->fsp_name->flags);
1221 0 : if (smb_atname == NULL) {
1222 0 : TALLOC_FREE(talloced);
1223 0 : TALLOC_FREE(fullname);
1224 0 : TALLOC_FREE(smb_dname_full);
1225 0 : status = NT_STATUS_NO_MEMORY;
1226 0 : goto err;
1227 : }
1228 0 : if (is_msdfs_link(fsp, smb_atname)) {
1229 0 : TALLOC_FREE(talloced);
1230 0 : TALLOC_FREE(fullname);
1231 0 : TALLOC_FREE(smb_dname_full);
1232 0 : TALLOC_FREE(smb_atname);
1233 0 : DBG_DEBUG("got msdfs link name %s "
1234 : "- can't delete directory %s\n",
1235 : dname,
1236 : fsp_str_dbg(fsp));
1237 0 : status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1238 0 : goto err;
1239 : }
1240 0 : TALLOC_FREE(smb_atname);
1241 : }
1242 :
1243 : /* Not a DFS link - could it be a dangling symlink ? */
1244 2 : retval = SMB_VFS_STAT(conn, smb_dname_full);
1245 2 : if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
1246 : /*
1247 : * Dangling symlink.
1248 : * Allow delete as "delete veto files = yes"
1249 : */
1250 2 : TALLOC_FREE(talloced);
1251 2 : TALLOC_FREE(fullname);
1252 2 : TALLOC_FREE(smb_dname_full);
1253 2 : continue;
1254 : }
1255 :
1256 0 : DBG_DEBUG("got symlink name %s - "
1257 : "can't delete directory %s\n",
1258 : dname,
1259 : fsp_str_dbg(fsp));
1260 0 : TALLOC_FREE(talloced);
1261 0 : TALLOC_FREE(fullname);
1262 0 : TALLOC_FREE(smb_dname_full);
1263 0 : status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1264 0 : goto err;
1265 : }
1266 :
1267 : /* Not a symlink, get a pathref. */
1268 2 : status = synthetic_pathref(talloc_tos(),
1269 : dirfsp,
1270 : dname,
1271 : NULL,
1272 2 : &smb_dname_full->st,
1273 : smb_dname->twrp,
1274 : smb_dname->flags,
1275 : &direntry_fname);
1276 2 : if (!NT_STATUS_IS_OK(status)) {
1277 0 : TALLOC_FREE(talloced);
1278 0 : TALLOC_FREE(fullname);
1279 0 : TALLOC_FREE(smb_dname_full);
1280 0 : goto err;
1281 : }
1282 :
1283 2 : if (!is_visible_fsp(direntry_fname->fsp)) {
1284 0 : TALLOC_FREE(talloced);
1285 0 : TALLOC_FREE(fullname);
1286 0 : TALLOC_FREE(smb_dname_full);
1287 0 : TALLOC_FREE(direntry_fname);
1288 0 : continue;
1289 : }
1290 :
1291 : /*
1292 : * We found a client visible name.
1293 : * We cannot delete this directory.
1294 : */
1295 2 : DBG_DEBUG("got name %s - "
1296 : "can't delete directory %s\n",
1297 : dname,
1298 : fsp_str_dbg(fsp));
1299 2 : TALLOC_FREE(talloced);
1300 2 : TALLOC_FREE(fullname);
1301 2 : TALLOC_FREE(smb_dname_full);
1302 2 : TALLOC_FREE(direntry_fname);
1303 2 : status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1304 2 : goto err;
1305 : }
1306 :
1307 : /* Do a recursive delete. */
1308 4 : RewindDir(dir_hnd);
1309 :
1310 16 : while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
1311 12 : struct smb_filename *direntry_fname = NULL;
1312 12 : struct smb_filename *smb_dname_full = NULL;
1313 12 : char *fullname = NULL;
1314 12 : bool do_break = true;
1315 0 : int retval;
1316 :
1317 12 : if (ISDOT(dname) || ISDOTDOT(dname)) {
1318 8 : TALLOC_FREE(talloced);
1319 8 : continue;
1320 : }
1321 :
1322 4 : fullname = talloc_asprintf(ctx,
1323 : "%s/%s",
1324 : smb_dname->base_name,
1325 : dname);
1326 :
1327 4 : if (fullname == NULL) {
1328 0 : status = NT_STATUS_NO_MEMORY;
1329 0 : goto err_break;
1330 : }
1331 :
1332 4 : smb_dname_full = synthetic_smb_fname(talloc_tos(),
1333 : fullname,
1334 : NULL,
1335 : NULL,
1336 : smb_dname->twrp,
1337 : smb_dname->flags);
1338 4 : if (smb_dname_full == NULL) {
1339 0 : status = NT_STATUS_NO_MEMORY;
1340 0 : goto err_break;
1341 : }
1342 :
1343 : /*
1344 : * Todo: use SMB_VFS_STATX() once that's available.
1345 : */
1346 :
1347 4 : retval = SMB_VFS_LSTAT(conn, smb_dname_full);
1348 4 : if (retval != 0) {
1349 0 : status = map_nt_error_from_unix(errno);
1350 0 : goto err_break;
1351 : }
1352 :
1353 : /*
1354 : * We are only dealing with VETO'ed objects
1355 : * here. If it's a symlink, just delete the
1356 : * link without caring what it is pointing
1357 : * to.
1358 : */
1359 4 : if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1360 2 : direntry_fname = synthetic_smb_fname(talloc_tos(),
1361 : dname,
1362 : NULL,
1363 2 : &smb_dname_full->st,
1364 : smb_dname->twrp,
1365 : smb_dname->flags);
1366 2 : if (direntry_fname == NULL) {
1367 0 : status = NT_STATUS_NO_MEMORY;
1368 0 : goto err_break;
1369 : }
1370 : } else {
1371 2 : status = synthetic_pathref(talloc_tos(),
1372 : dirfsp,
1373 : dname,
1374 : NULL,
1375 2 : &smb_dname_full->st,
1376 : smb_dname->twrp,
1377 : smb_dname->flags,
1378 : &direntry_fname);
1379 2 : if (!NT_STATUS_IS_OK(status)) {
1380 0 : goto err_break;
1381 : }
1382 :
1383 2 : if (!is_visible_fsp(direntry_fname->fsp)) {
1384 0 : TALLOC_FREE(fullname);
1385 0 : TALLOC_FREE(smb_dname_full);
1386 0 : TALLOC_FREE(talloced);
1387 0 : TALLOC_FREE(direntry_fname);
1388 0 : continue;
1389 : }
1390 : }
1391 :
1392 4 : unlink_flags = 0;
1393 :
1394 4 : if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
1395 0 : status = recursive_rmdir(ctx, conn, smb_dname_full);
1396 0 : if (!NT_STATUS_IS_OK(status)) {
1397 0 : goto err_break;
1398 : }
1399 0 : unlink_flags = AT_REMOVEDIR;
1400 : }
1401 :
1402 4 : retval = SMB_VFS_UNLINKAT(conn,
1403 : dirfsp,
1404 : direntry_fname,
1405 : unlink_flags);
1406 4 : if (retval != 0) {
1407 0 : status = map_nt_error_from_unix(errno);
1408 0 : goto err_break;
1409 : }
1410 :
1411 : /* Successful iteration. */
1412 4 : do_break = false;
1413 :
1414 4 : err_break:
1415 4 : TALLOC_FREE(fullname);
1416 4 : TALLOC_FREE(smb_dname_full);
1417 4 : TALLOC_FREE(talloced);
1418 4 : TALLOC_FREE(direntry_fname);
1419 4 : if (do_break) {
1420 0 : break;
1421 : }
1422 : }
1423 :
1424 : /* If we get here, we know NT_STATUS_IS_OK(status) */
1425 4 : SMB_ASSERT(NT_STATUS_IS_OK(status));
1426 :
1427 : /* Retry the rmdir */
1428 4 : ret = SMB_VFS_UNLINKAT(conn,
1429 : parent_fname->fsp,
1430 : at_fname,
1431 : AT_REMOVEDIR);
1432 4 : if (ret != 0) {
1433 0 : status = map_nt_error_from_unix(errno);
1434 : }
1435 :
1436 4 : err:
1437 :
1438 8 : TALLOC_FREE(dir_hnd);
1439 8 : TALLOC_FREE(parent_fname);
1440 :
1441 8 : if (!NT_STATUS_IS_OK(status)) {
1442 4 : DBG_NOTICE("couldn't remove directory %s : "
1443 : "%s\n", smb_fname_str_dbg(smb_dname),
1444 : nt_errstr(status));
1445 4 : return status;
1446 : }
1447 :
1448 4 : notify_fname(conn, NOTIFY_ACTION_REMOVED,
1449 : FILE_NOTIFY_CHANGE_DIR_NAME,
1450 4 : smb_dname->base_name);
1451 :
1452 4 : return status;
1453 : }
1454 :
1455 : /****************************************************************************
1456 : Close a directory opened by an NT SMB call.
1457 : ****************************************************************************/
1458 :
1459 82755 : static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
1460 : enum file_close_type close_type)
1461 : {
1462 82755 : connection_struct *conn = fsp->conn;
1463 82755 : struct close_share_mode_lock_state lck_state = {};
1464 82755 : bool changed_user = false;
1465 82755 : NTSTATUS status = NT_STATUS_OK;
1466 82755 : NTSTATUS status1 = NT_STATUS_OK;
1467 346 : NTSTATUS notify_status;
1468 346 : NTSTATUS ulstatus;
1469 :
1470 82755 : SMB_ASSERT(fsp->fsp_flags.is_fsa);
1471 :
1472 82755 : if (conn_using_smb2(fsp->conn->sconn)) {
1473 58850 : notify_status = NT_STATUS_NOTIFY_CLEANUP;
1474 : } else {
1475 23905 : notify_status = NT_STATUS_OK;
1476 : }
1477 :
1478 82755 : assert_no_pending_aio(fsp, close_type);
1479 :
1480 : /*
1481 : * NT can set delete_on_close of the last open
1482 : * reference to a directory also.
1483 : */
1484 :
1485 82755 : lck_state = (struct close_share_mode_lock_state) {
1486 : .fsp = fsp,
1487 : .object_type = "directory",
1488 : .close_type = close_type,
1489 : };
1490 :
1491 82755 : status = share_mode_entry_prepare_lock_del(&lck_state.prepare_state,
1492 : fsp->file_id,
1493 : close_share_mode_lock_prepare,
1494 346 : &lck_state);
1495 82755 : if (!NT_STATUS_IS_OK(status)) {
1496 0 : DBG_ERR("share_mode_entry_prepare_lock_del() failed for %s - %s\n",
1497 : fsp_str_dbg(fsp), nt_errstr(status));
1498 0 : return status;
1499 : }
1500 :
1501 : /*
1502 : * We don't have directory leases yet, so assert it in order
1503 : * to skip release_file_oplock().
1504 : */
1505 82755 : SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
1506 :
1507 : /*
1508 : * NT can set delete_on_close of the last open
1509 : * reference to a file.
1510 : */
1511 :
1512 82755 : if (!lck_state.delete_object) {
1513 71620 : status = NT_STATUS_OK;
1514 71620 : goto done;
1515 : }
1516 :
1517 : /*
1518 : * Ok, we have to delete the directory
1519 : */
1520 11135 : lck_state.cleanup_fn = close_share_mode_lock_cleanup;
1521 :
1522 11199 : if (lck_state.got_tokens &&
1523 11135 : !unix_token_equal(lck_state.del_token, get_current_utok(conn)))
1524 : {
1525 : /* Become the user who requested the delete. */
1526 :
1527 11 : DBG_INFO("dir %s. Change user to uid %u\n",
1528 : fsp_str_dbg(fsp),
1529 : (unsigned int)lck_state.del_token->uid);
1530 :
1531 11 : if (!push_sec_ctx()) {
1532 0 : smb_panic("close_directory: failed to push sec_ctx.\n");
1533 : }
1534 :
1535 11 : set_sec_ctx(lck_state.del_token->uid,
1536 11 : lck_state.del_token->gid,
1537 11 : lck_state.del_token->ngroups,
1538 11 : lck_state.del_token->groups,
1539 : lck_state.del_nt_token);
1540 :
1541 11 : changed_user = true;
1542 : }
1543 :
1544 11135 : if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
1545 10588 : && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
1546 :
1547 10588 : status = delete_all_streams(fsp->conn, fsp->fsp_name);
1548 10588 : if (!NT_STATUS_IS_OK(status)) {
1549 0 : DEBUG(5, ("delete_all_streams failed: %s\n",
1550 : nt_errstr(status)));
1551 0 : goto done;
1552 : }
1553 : }
1554 :
1555 11135 : status = rmdir_internals(talloc_tos(), fsp);
1556 :
1557 11135 : DEBUG(5,("close_directory: %s. Delete on close was set - "
1558 : "deleting directory returned %s.\n",
1559 : fsp_str_dbg(fsp), nt_errstr(status)));
1560 :
1561 : /*
1562 : * Ensure we remove any change notify requests that would
1563 : * now fail as the directory has been deleted.
1564 : */
1565 :
1566 11135 : if (NT_STATUS_IS_OK(status)) {
1567 11131 : notify_status = NT_STATUS_DELETE_PENDING;
1568 : }
1569 :
1570 4 : done:
1571 82755 : if (changed_user) {
1572 : /* unbecome user. */
1573 11 : pop_sec_ctx();
1574 : }
1575 :
1576 82755 : ulstatus = share_mode_entry_prepare_unlock(&lck_state.prepare_state,
1577 : lck_state.cleanup_fn,
1578 346 : &lck_state);
1579 82755 : if (!NT_STATUS_IS_OK(ulstatus)) {
1580 0 : DBG_ERR("share_mode_entry_prepare_unlock() failed for %s - %s\n",
1581 : fsp_str_dbg(fsp), nt_errstr(ulstatus));
1582 0 : smb_panic("share_mode_entry_prepare_unlock() failed!");
1583 : }
1584 :
1585 82755 : remove_pending_change_notify_requests_by_fid(fsp, notify_status);
1586 :
1587 82755 : status1 = fd_close(fsp);
1588 :
1589 82755 : if (!NT_STATUS_IS_OK(status1)) {
1590 0 : DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
1591 : fsp_str_dbg(fsp), fsp_get_pathref_fd(fsp), errno,
1592 : strerror(errno)));
1593 : }
1594 :
1595 82755 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
1596 0 : status = status1;
1597 : }
1598 82755 : return status;
1599 : }
1600 :
1601 : /****************************************************************************
1602 : Rundown all SMB-related dependencies of a files struct
1603 : ****************************************************************************/
1604 :
1605 584552 : NTSTATUS close_file_smb(struct smb_request *req,
1606 : struct files_struct *fsp,
1607 : enum file_close_type close_type)
1608 : {
1609 2121 : NTSTATUS status;
1610 :
1611 : /*
1612 : * This fsp can never be an internal dirfsp. They must
1613 : * be explicitly closed by TALLOC_FREE of the dir handle.
1614 : */
1615 584552 : SMB_ASSERT(!fsp->fsp_flags.is_dirfsp);
1616 :
1617 : /*
1618 : * Never call directly on a base fsp
1619 : */
1620 584552 : SMB_ASSERT(fsp->stream_fsp == NULL);
1621 :
1622 584552 : if (fsp->fake_file_handle != NULL) {
1623 : /*
1624 : * Named pipes are opened as fake files and
1625 : * can have pending aio requests. Ensure
1626 : * we clear out all pending aio on force
1627 : * shutdown of named pipes also.
1628 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
1629 : */
1630 17448 : assert_no_pending_aio(fsp, close_type);
1631 17448 : status = close_fake_file(req, fsp);
1632 567104 : } else if (fsp->print_file != NULL) {
1633 : /* FIXME: return spool errors */
1634 28 : print_spool_end(fsp, close_type);
1635 28 : fd_close(fsp);
1636 28 : status = NT_STATUS_OK;
1637 567076 : } else if (!fsp->fsp_flags.is_fsa) {
1638 125976 : if (close_type == NORMAL_CLOSE) {
1639 0 : DBG_ERR("unexpected NORMAL_CLOSE for [%s] "
1640 : "is_fsa[%u] is_pathref[%u] is_directory[%u]\n",
1641 : fsp_str_dbg(fsp),
1642 : fsp->fsp_flags.is_fsa,
1643 : fsp->fsp_flags.is_pathref,
1644 : fsp->fsp_flags.is_directory);
1645 : }
1646 125976 : SMB_ASSERT(close_type != NORMAL_CLOSE);
1647 125976 : fd_close(fsp);
1648 125976 : status = NT_STATUS_OK;
1649 441100 : } else if (fsp->fsp_flags.is_directory) {
1650 82755 : status = close_directory(req, fsp, close_type);
1651 : } else {
1652 358345 : status = close_normal_file(req, fsp, close_type);
1653 : }
1654 :
1655 584552 : if (fsp_is_alternate_stream(fsp)) {
1656 : /*
1657 : * fsp was a stream, its base_fsp can't be a stream
1658 : * as well
1659 : */
1660 7202 : SMB_ASSERT(!fsp_is_alternate_stream(fsp->base_fsp));
1661 :
1662 : /*
1663 : * There's a 1:1 relationship between fsp and a base_fsp
1664 : */
1665 7202 : SMB_ASSERT(fsp->base_fsp->stream_fsp == fsp);
1666 :
1667 : /*
1668 : * Make base_fsp look standalone now
1669 : */
1670 7202 : fsp->base_fsp->stream_fsp = NULL;
1671 :
1672 7202 : close_file_free(req, &fsp->base_fsp, close_type);
1673 : }
1674 :
1675 584552 : fsp_unbind_smb(req, fsp);
1676 :
1677 584552 : return status;
1678 : }
1679 :
1680 99196 : NTSTATUS close_file_free(struct smb_request *req,
1681 : struct files_struct **_fsp,
1682 : enum file_close_type close_type)
1683 : {
1684 99196 : struct files_struct *fsp = *_fsp;
1685 1043 : NTSTATUS status;
1686 :
1687 99196 : status = close_file_smb(req, fsp, close_type);
1688 :
1689 99196 : file_free(req, fsp);
1690 99196 : *_fsp = NULL;
1691 :
1692 99196 : return status;
1693 : }
1694 :
1695 : /****************************************************************************
1696 : Deal with an (authorized) message to close a file given the share mode
1697 : entry.
1698 : ****************************************************************************/
1699 :
1700 0 : void msg_close_file(struct messaging_context *msg_ctx,
1701 : void *private_data,
1702 : uint32_t msg_type,
1703 : struct server_id server_id,
1704 : DATA_BLOB *data)
1705 : {
1706 0 : struct oplock_break_message msg;
1707 0 : enum ndr_err_code ndr_err;
1708 0 : files_struct *fsp = NULL;
1709 0 : struct smbd_server_connection *sconn =
1710 0 : talloc_get_type_abort(private_data,
1711 : struct smbd_server_connection);
1712 :
1713 0 : ndr_err = ndr_pull_struct_blob_all_noalloc(
1714 : data,
1715 : &msg,
1716 : (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
1717 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1718 0 : DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
1719 : ndr_errstr(ndr_err));
1720 0 : return;
1721 : }
1722 :
1723 0 : fsp = file_find_dif(sconn, msg.id, msg.share_file_id);
1724 0 : if (!fsp) {
1725 0 : DEBUG(10,("msg_close_file: failed to find file.\n"));
1726 0 : return;
1727 : }
1728 0 : close_file_free(NULL, &fsp, NORMAL_CLOSE);
1729 : }
|