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