s4:auth: Set ‘authoritative’ even if there is an error
[Samba.git] / source3 / smbd / dir.c
blob8c5943bf88b2add4bb6a01072bf1c59b06029856
1 /*
2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "locking/share_mode_lock.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "libcli/security/security.h"
27 #include "lib/util/bitmap.h"
28 #include "../lib/util/memcache.h"
29 #include "../librpc/gen_ndr/open_files.h"
30 #include "lib/util/string_wrappers.h"
33 This module implements directory related functions for Samba.
36 /* "Special" directory offsets. */
37 #define END_OF_DIRECTORY_OFFSET ((long)-1)
38 #define START_OF_DIRECTORY_OFFSET ((long)0)
39 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
41 /* Make directory handle internals available. */
43 struct smb_Dir {
44 connection_struct *conn;
45 DIR *dir;
46 struct smb_filename *dir_smb_fname;
47 unsigned int file_number;
48 bool case_sensitive;
49 files_struct *fsp; /* Back pointer to containing fsp, only
50 set from OpenDir_fsp(). */
53 struct dptr_struct {
54 struct dptr_struct *next, *prev;
55 int dnum;
56 struct connection_struct *conn;
57 struct smb_Dir *dir_hnd;
58 char *wcard;
59 uint32_t attr;
60 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
61 bool did_stat; /* Optimisation for non-wcard searches. */
62 bool priv; /* Directory handle opened with privilege. */
63 uint32_t counter;
65 char *last_name_sent; /* for name-based trans2 resume */
67 struct {
68 char *fname;
69 struct smb_filename *smb_fname;
70 uint32_t mode;
71 } overflow;
74 static NTSTATUS OpenDir_fsp(
75 TALLOC_CTX *mem_ctx,
76 connection_struct *conn,
77 files_struct *fsp,
78 const char *mask,
79 uint32_t attr,
80 struct smb_Dir **_dir_hnd);
82 static int smb_Dir_destructor(struct smb_Dir *dir_hnd);
84 #define INVALID_DPTR_KEY (-3)
86 /****************************************************************************
87 Initialise the dir bitmap.
88 ****************************************************************************/
90 bool init_dptrs(struct smbd_server_connection *sconn)
92 if (sconn->searches.dptr_bmap) {
93 return true;
96 sconn->searches.dptr_bmap = bitmap_talloc(
97 sconn, MAX_DIRECTORY_HANDLES);
99 if (sconn->searches.dptr_bmap == NULL) {
100 return false;
103 return true;
106 /****************************************************************************
107 Get the struct dptr_struct for a dir index.
108 ****************************************************************************/
110 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
111 int key)
113 struct dptr_struct *dptr;
115 for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
116 if(dptr->dnum != key) {
117 continue;
119 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
120 return dptr;
122 return(NULL);
125 /****************************************************************************
126 Get the dir path for a dir index.
127 ****************************************************************************/
129 const char *dptr_path(struct smbd_server_connection *sconn, int key)
131 struct dptr_struct *dptr = dptr_get(sconn, key);
132 if (dptr)
133 return(dptr->dir_hnd->dir_smb_fname->base_name);
134 return(NULL);
137 /****************************************************************************
138 Get the dir wcard for a dir index.
139 ****************************************************************************/
141 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
143 struct dptr_struct *dptr = dptr_get(sconn, key);
144 if (dptr)
145 return(dptr->wcard);
146 return(NULL);
149 /****************************************************************************
150 Get the dir attrib for a dir index.
151 ****************************************************************************/
153 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
155 struct dptr_struct *dptr = dptr_get(sconn, key);
156 if (dptr)
157 return(dptr->attr);
158 return(0);
161 /****************************************************************************
162 Close all dptrs for a cnum.
163 ****************************************************************************/
165 void dptr_closecnum(connection_struct *conn)
167 struct dptr_struct *dptr, *next;
168 struct smbd_server_connection *sconn = conn->sconn;
170 if (sconn == NULL) {
171 return;
174 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
175 next = dptr->next;
176 if (dptr->conn == conn) {
178 * Need to make a copy, "dptr" will be gone
179 * after close_file_free() returns
181 struct files_struct *fsp = dptr->dir_hnd->fsp;
182 close_file_free(NULL, &fsp, NORMAL_CLOSE);
187 /****************************************************************************
188 Create a new dir ptr. If the flag old_handle is true then we must allocate
189 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
190 one byte long. If old_handle is false we allocate from the range
191 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
192 a directory handle is never zero.
193 wcard must not be zero.
194 ****************************************************************************/
196 NTSTATUS dptr_create(connection_struct *conn,
197 struct smb_request *req,
198 files_struct *fsp,
199 bool old_handle,
200 const char *wcard,
201 uint32_t attr,
202 struct dptr_struct **dptr_ret)
204 struct smbd_server_connection *sconn = conn->sconn;
205 struct dptr_struct *dptr = NULL;
206 struct smb_Dir *dir_hnd = NULL;
207 NTSTATUS status;
209 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp));
211 if (sconn == NULL) {
212 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
213 return NT_STATUS_INTERNAL_ERROR;
216 if (!wcard) {
217 return NT_STATUS_INVALID_PARAMETER;
220 if (!(fsp->access_mask & SEC_DIR_LIST)) {
221 DBG_INFO("dptr_create: directory %s "
222 "not open for LIST access\n",
223 fsp_str_dbg(fsp));
224 return NT_STATUS_ACCESS_DENIED;
226 status = OpenDir_fsp(NULL, conn, fsp, wcard, attr, &dir_hnd);
227 if (!NT_STATUS_IS_OK(status)) {
228 return status;
231 dptr = talloc_zero(NULL, struct dptr_struct);
232 if(!dptr) {
233 DEBUG(0,("talloc fail in dptr_create.\n"));
234 TALLOC_FREE(dir_hnd);
235 return NT_STATUS_NO_MEMORY;
238 dptr->conn = conn;
239 dptr->dir_hnd = dir_hnd;
240 dptr->wcard = talloc_strdup(dptr, wcard);
241 if (!dptr->wcard) {
242 TALLOC_FREE(dptr);
243 TALLOC_FREE(dir_hnd);
244 return NT_STATUS_NO_MEMORY;
246 if ((req != NULL && req->posix_pathnames) || ISDOT(wcard)) {
247 dptr->has_wild = True;
248 } else {
249 dptr->has_wild = ms_has_wild(dptr->wcard);
252 dptr->attr = attr;
254 if (sconn->using_smb2) {
255 goto done;
258 if(old_handle) {
261 * This is an old-style SMBsearch request. Ensure the
262 * value we return will fit in the range 1-255.
265 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
267 if(dptr->dnum == -1 || dptr->dnum > 254) {
268 DBG_ERR("returned %d: Error - all old "
269 "dirptrs in use ?\n",
270 dptr->dnum);
271 TALLOC_FREE(dptr);
272 TALLOC_FREE(dir_hnd);
273 return NT_STATUS_TOO_MANY_OPENED_FILES;
275 } else {
278 * This is a new-style trans2 request. Allocate from
279 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
282 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
284 if(dptr->dnum == -1 || dptr->dnum < 255) {
285 DBG_ERR("returned %d: Error - all new "
286 "dirptrs in use ?\n",
287 dptr->dnum);
288 TALLOC_FREE(dptr);
289 TALLOC_FREE(dir_hnd);
290 return NT_STATUS_TOO_MANY_OPENED_FILES;
294 bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
296 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
298 DLIST_ADD(sconn->searches.dirptrs, dptr);
300 done:
301 DBG_INFO("creating new dirptr [%d] for path [%s]\n",
302 dptr->dnum, fsp_str_dbg(fsp));
304 *dptr_ret = dptr;
306 return NT_STATUS_OK;
310 /****************************************************************************
311 Wrapper functions to access the lower level directory handles.
312 ****************************************************************************/
314 void dptr_CloseDir(files_struct *fsp)
316 struct smbd_server_connection *sconn = NULL;
318 if (fsp->dptr == NULL) {
319 return;
321 sconn = fsp->dptr->conn->sconn;
324 * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
325 * now handles all resource deallocation.
328 DBG_INFO("closing dptr key %d\n", fsp->dptr->dnum);
330 if (sconn != NULL && !sconn->using_smb2) {
331 DLIST_REMOVE(sconn->searches.dirptrs, fsp->dptr);
334 * Free the dnum in the bitmap. Remember the dnum value is
335 * always biased by one with respect to the bitmap.
338 if (!bitmap_query(sconn->searches.dptr_bmap,
339 fsp->dptr->dnum - 1))
341 DBG_ERR("closing dnum = %d and bitmap not set !\n",
342 fsp->dptr->dnum);
345 bitmap_clear(sconn->searches.dptr_bmap, fsp->dptr->dnum - 1);
348 TALLOC_FREE(fsp->dptr->dir_hnd);
349 TALLOC_FREE(fsp->dptr);
352 void dptr_RewindDir(struct dptr_struct *dptr)
354 RewindDir(dptr->dir_hnd);
355 dptr->did_stat = false;
356 TALLOC_FREE(dptr->overflow.fname);
357 TALLOC_FREE(dptr->overflow.smb_fname);
360 unsigned int dptr_FileNumber(struct dptr_struct *dptr)
362 return dptr->dir_hnd->file_number;
365 bool dptr_has_wild(struct dptr_struct *dptr)
367 return dptr->has_wild;
370 int dptr_dnum(struct dptr_struct *dptr)
372 return dptr->dnum;
375 bool dptr_get_priv(struct dptr_struct *dptr)
377 return dptr->priv;
380 void dptr_set_priv(struct dptr_struct *dptr)
382 dptr->priv = true;
385 bool dptr_case_sensitive(struct dptr_struct *dptr)
387 return dptr->dir_hnd->case_sensitive;
390 /****************************************************************************
391 Return the next visible file name, skipping veto'd and invisible files.
392 ****************************************************************************/
394 char *dptr_ReadDirName(TALLOC_CTX *ctx, struct dptr_struct *dptr)
396 struct stat_ex st = {
397 .st_ex_nlink = 0,
399 struct smb_Dir *dir_hnd = dptr->dir_hnd;
400 struct files_struct *dir_fsp = dir_hnd->fsp;
401 struct smb_filename *dir_name = dir_fsp->fsp_name;
402 struct smb_filename smb_fname_base;
403 bool retry_scanning = false;
404 int ret;
405 int flags = 0;
407 if (dptr->has_wild) {
408 const char *name_temp = NULL;
409 char *talloced = NULL;
410 name_temp = ReadDirName(dir_hnd, &talloced);
411 if (name_temp == NULL) {
412 return NULL;
414 if (talloced != NULL) {
415 return talloc_move(ctx, &talloced);
417 return talloc_strdup(ctx, name_temp);
420 if (dptr->did_stat) {
422 * No wildcard, this is not a real directory traverse
423 * but a "stat" call behind a query_directory. We've
424 * been here, nothing else to look at.
426 return NULL;
428 dptr->did_stat = true;
430 /* Create an smb_filename with stream_name == NULL. */
431 smb_fname_base = (struct smb_filename){
432 .base_name = dptr->wcard,
433 .flags = dir_name->flags,
434 .twrp = dir_name->twrp,
437 if (dir_name->flags & SMB_FILENAME_POSIX_PATH) {
438 flags |= AT_SYMLINK_NOFOLLOW;
441 ret = SMB_VFS_FSTATAT(dptr->conn, dir_fsp, &smb_fname_base, &st, flags);
442 if (ret == 0) {
443 return talloc_strdup(ctx, dptr->wcard);
447 * If we get any other error than ENOENT or ENOTDIR
448 * then the file exists, we just can't stat it.
450 if (errno != ENOENT && errno != ENOTDIR) {
451 return talloc_strdup(ctx, dptr->wcard);
455 * A scan will find the long version of a mangled name as
456 * wildcard.
458 retry_scanning |= mangle_is_mangled(dptr->wcard, dptr->conn->params);
461 * Also retry scanning if the client requested case
462 * insensitive semantics and the file system does not provide
463 * it.
465 retry_scanning |=
466 (!dir_hnd->case_sensitive &&
467 (dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH));
469 if (retry_scanning) {
470 char *found_name = NULL;
471 NTSTATUS status;
473 status = get_real_filename_at(dir_fsp,
474 dptr->wcard,
475 ctx,
476 &found_name);
477 if (NT_STATUS_IS_OK(status)) {
478 return found_name;
482 return NULL;
485 struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd)
487 return dir_hnd->fsp;
490 /****************************************************************************
491 Fetch the fsp associated with the dptr_num.
492 ****************************************************************************/
494 files_struct *dptr_fetch_lanman2_fsp(struct smbd_server_connection *sconn,
495 int dptr_num)
497 struct dptr_struct *dptr = dptr_get(sconn, dptr_num);
498 if (dptr == NULL) {
499 return NULL;
501 DBG_NOTICE("fetching dirptr %d for path %s\n",
502 dptr_num,
503 dptr->dir_hnd->dir_smb_fname->base_name);
504 return dptr->dir_hnd->fsp;
507 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
508 struct dptr_struct *dirptr,
509 const char *mask,
510 uint32_t dirtype,
511 bool dont_descend,
512 bool ask_sharemode,
513 bool get_dosmode_in,
514 bool (*match_fn)(TALLOC_CTX *ctx,
515 void *private_data,
516 const char *dname,
517 const char *mask,
518 char **_fname),
519 bool (*mode_fn)(TALLOC_CTX *ctx,
520 void *private_data,
521 struct files_struct *dirfsp,
522 struct smb_filename *atname,
523 struct smb_filename *smb_fname,
524 bool get_dosmode,
525 uint32_t *_mode),
526 void *private_data,
527 char **_fname,
528 struct smb_filename **_smb_fname,
529 uint32_t *_mode)
531 connection_struct *conn = dirptr->conn;
532 struct smb_Dir *dir_hnd = dirptr->dir_hnd;
533 size_t slashlen;
534 size_t pathlen;
535 const char *dpath = dir_hnd->dir_smb_fname->base_name;
536 bool dirptr_path_is_dot = ISDOT(dpath);
537 NTSTATUS status;
539 *_smb_fname = NULL;
540 *_mode = 0;
542 if (dirptr->overflow.smb_fname != NULL) {
543 *_fname = talloc_move(ctx, &dirptr->overflow.fname);
544 *_smb_fname = talloc_move(ctx, &dirptr->overflow.smb_fname);
545 *_mode = dirptr->overflow.mode;
546 return true;
549 pathlen = strlen(dpath);
550 slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
552 while (true) {
553 char *dname = NULL;
554 bool isdots;
555 char *fname = NULL;
556 char *pathreal = NULL;
557 struct smb_filename *atname = NULL;
558 struct smb_filename *smb_fname = NULL;
559 uint32_t mode = 0;
560 bool check_dfs_symlink = false;
561 bool get_dosmode = get_dosmode_in;
562 bool ok;
564 dname = dptr_ReadDirName(ctx, dirptr);
566 DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
567 "dname [%s]\n",
568 smb_fname_str_dbg(dir_hnd->dir_smb_fname),
569 dirptr,
570 dir_hnd->file_number,
571 dname ? dname : "(finished)");
573 if (dname == NULL) {
574 return false;
577 isdots = (ISDOT(dname) || ISDOTDOT(dname));
578 if (dont_descend && !isdots) {
579 TALLOC_FREE(dname);
580 continue;
583 if (IS_VETO_PATH(conn, dname)) {
584 TALLOC_FREE(dname);
585 continue;
589 * fname may get mangled, dname is never mangled.
590 * Whenever we're accessing the filesystem we use
591 * pathreal which is composed from dname.
594 ok = match_fn(ctx, private_data, dname, mask, &fname);
595 if (!ok) {
596 TALLOC_FREE(dname);
597 continue;
601 * This used to be
602 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
603 * needslash?"/":"", dname);
604 * but this was measurably slower than doing the memcpy.
607 pathreal = talloc_array(
608 ctx, char,
609 pathlen + slashlen + talloc_get_size(dname));
610 if (!pathreal) {
611 TALLOC_FREE(dname);
612 TALLOC_FREE(fname);
613 return false;
617 * We don't want to pass ./xxx to modules below us so don't
618 * add the path if it is just . by itself.
620 if (dirptr_path_is_dot) {
621 memcpy(pathreal, dname, talloc_get_size(dname));
622 } else {
623 memcpy(pathreal, dpath, pathlen);
624 pathreal[pathlen] = '/';
625 memcpy(pathreal + slashlen + pathlen, dname,
626 talloc_get_size(dname));
629 /* Create smb_fname with NULL stream_name. */
630 smb_fname = synthetic_smb_fname(talloc_tos(),
631 pathreal,
632 NULL,
633 NULL,
634 dir_hnd->dir_smb_fname->twrp,
635 dir_hnd->dir_smb_fname->flags);
636 TALLOC_FREE(pathreal);
637 if (smb_fname == NULL) {
638 TALLOC_FREE(dname);
639 TALLOC_FREE(fname);
640 return false;
643 /* Create smb_fname with NULL stream_name. */
644 atname = synthetic_smb_fname(talloc_tos(),
645 dname,
646 NULL,
647 NULL,
648 dir_hnd->dir_smb_fname->twrp,
649 dir_hnd->dir_smb_fname->flags);
650 if (atname == NULL) {
651 TALLOC_FREE(dname);
652 TALLOC_FREE(fname);
653 TALLOC_FREE(smb_fname);
654 return false;
658 * openat_pathref_fsp() will return
659 * NT_STATUS_OBJECT_NAME_NOT_FOUND in non-POSIX context when
660 * hitting a dangling symlink. It may be a DFS symlink, this is
661 * checked below by the mode_fn() call, so we have to allow this
662 * here.
664 * NT_STATUS_STOPPED_ON_SYMLINK is returned in POSIX context
665 * when hitting a symlink and ensures we always return directory
666 * entries that are symlinks in POSIX context.
668 status = openat_pathref_fsp(dir_hnd->fsp, atname);
669 if (!NT_STATUS_IS_OK(status) &&
670 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
672 TALLOC_FREE(atname);
673 TALLOC_FREE(dname);
674 TALLOC_FREE(fname);
675 TALLOC_FREE(smb_fname);
676 continue;
679 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
680 if (!(atname->flags & SMB_FILENAME_POSIX_PATH)) {
681 check_dfs_symlink = true;
684 * Check if it's a symlink. We only want to return this
685 * if it's a DFS symlink or in POSIX mode. Disable
686 * getting dosmode in the mode_fn() and prime the mode
687 * as FILE_ATTRIBUTE_NORMAL.
689 mode = FILE_ATTRIBUTE_NORMAL;
690 get_dosmode = false;
694 * openat_pathref_fsp() filled atname->st, but from
695 * now on we're working with smb_fname. Keep the stat
696 * info for mode_fn's use.
698 smb_fname->st = atname->st;
700 status = move_smb_fname_fsp_link(smb_fname, atname);
701 if (!NT_STATUS_IS_OK(status)) {
702 DBG_WARNING("Failed to move pathref for [%s]: %s\n",
703 smb_fname_str_dbg(smb_fname),
704 nt_errstr(status));
705 TALLOC_FREE(atname);
706 TALLOC_FREE(smb_fname);
707 TALLOC_FREE(dname);
708 TALLOC_FREE(fname);
709 continue;
712 if (!is_visible_fsp(smb_fname->fsp)) {
713 TALLOC_FREE(atname);
714 TALLOC_FREE(smb_fname);
715 TALLOC_FREE(dname);
716 TALLOC_FREE(fname);
717 continue;
721 * Don't leak metadata about the containing
722 * directory of the share.
724 if (dirptr_path_is_dot && ISDOTDOT(dname)) {
726 * Making a copy here, then freeing
727 * the original will close the smb_fname->fsp.
729 struct smb_filename *tmp_smb_fname =
730 cp_smb_filename(ctx, smb_fname);
732 if (tmp_smb_fname == NULL) {
733 TALLOC_FREE(atname);
734 TALLOC_FREE(smb_fname);
735 TALLOC_FREE(dname);
736 TALLOC_FREE(fname);
737 return false;
739 TALLOC_FREE(smb_fname);
740 smb_fname = tmp_smb_fname;
741 mode = FILE_ATTRIBUTE_DIRECTORY;
742 get_dosmode = false;
745 ok = mode_fn(ctx,
746 private_data,
747 dir_hnd->fsp,
748 atname,
749 smb_fname,
750 get_dosmode,
751 &mode);
752 if (!ok) {
753 TALLOC_FREE(atname);
754 TALLOC_FREE(smb_fname);
755 TALLOC_FREE(dname);
756 TALLOC_FREE(fname);
757 continue;
760 TALLOC_FREE(atname);
763 * Don't leak INO/DEV/User SID/Group SID about the containing
764 * directory of the share. This MUST happen AFTER the call to
765 * mode_fn().
767 if (dirptr_path_is_dot && ISDOTDOT(dname)) {
768 /* Ensure posix fileid and sids are hidden
770 smb_fname->st.st_ex_ino = 0;
771 smb_fname->st.st_ex_dev = 0;
772 smb_fname->st.st_ex_uid = -1;
773 smb_fname->st.st_ex_gid = -1;
777 * The only valid cases where we return the directory entry if
778 * it's a symlink are:
780 * 1. POSIX context, always return it, or
782 * 2. a DFS symlink where the mode_fn() call above has verified
783 * this and set mode to FILE_ATTRIBUTE_REPARSE_POINT.
785 if (check_dfs_symlink &&
786 !(mode & FILE_ATTRIBUTE_REPARSE_POINT))
788 TALLOC_FREE(smb_fname);
789 TALLOC_FREE(dname);
790 TALLOC_FREE(fname);
791 continue;
794 if (!dir_check_ftype(mode, dirtype)) {
795 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
796 fname, (unsigned int)mode, (unsigned int)dirtype));
797 TALLOC_FREE(smb_fname);
798 TALLOC_FREE(dname);
799 TALLOC_FREE(fname);
800 continue;
803 if (ask_sharemode && !S_ISDIR(smb_fname->st.st_ex_mode)) {
804 struct timespec write_time_ts;
805 struct file_id fileid;
807 fileid = vfs_file_id_from_sbuf(conn,
808 &smb_fname->st);
809 get_file_infos(fileid, 0, NULL, &write_time_ts);
810 if (!is_omit_timespec(&write_time_ts)) {
811 update_stat_ex_mtime(&smb_fname->st,
812 write_time_ts);
816 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
817 "fname=%s (%s)\n",
818 mask, smb_fname_str_dbg(smb_fname),
819 dname, fname));
821 TALLOC_FREE(dname);
823 *_smb_fname = talloc_move(ctx, &smb_fname);
824 if (*_smb_fname == NULL) {
825 return false;
827 *_fname = fname;
828 *_mode = mode;
830 return true;
833 return false;
836 void smbd_dirptr_push_overflow(struct dptr_struct *dirptr,
837 char **_fname,
838 struct smb_filename **_smb_fname,
839 uint32_t mode)
841 SMB_ASSERT(dirptr->overflow.fname == NULL);
842 SMB_ASSERT(dirptr->overflow.smb_fname == NULL);
844 dirptr->overflow.fname = talloc_move(dirptr, _fname);
845 dirptr->overflow.smb_fname = talloc_move(dirptr, _smb_fname);
846 dirptr->overflow.mode = mode;
849 void smbd_dirptr_set_last_name_sent(struct dptr_struct *dirptr,
850 char **_fname)
852 TALLOC_FREE(dirptr->last_name_sent);
853 dirptr->last_name_sent = talloc_move(dirptr, _fname);
856 char *smbd_dirptr_get_last_name_sent(struct dptr_struct *dirptr)
858 return dirptr->last_name_sent;
861 /*******************************************************************
862 Check to see if a user can read an fsp . This is only approximate,
863 it is used as part of the "hide unreadable" option. Don't
864 use it for anything security sensitive.
865 ********************************************************************/
867 static bool user_can_read_fsp(struct files_struct *fsp)
869 NTSTATUS status;
870 uint32_t rejected_share_access = 0;
871 uint32_t rejected_mask = 0;
872 struct security_descriptor *sd = NULL;
873 uint32_t access_mask = FILE_READ_DATA|
874 FILE_READ_EA|
875 FILE_READ_ATTRIBUTES|
876 SEC_STD_READ_CONTROL;
879 * Never hide files from the root user.
880 * We use (uid_t)0 here not sec_initial_uid()
881 * as make test uses a single user context.
884 if (get_current_uid(fsp->conn) == (uid_t)0) {
885 return true;
889 * We can't directly use smbd_check_access_rights_fsp()
890 * here, as this implicitly grants FILE_READ_ATTRIBUTES
891 * which the Windows access-based-enumeration code
892 * explicitly checks for on the file security descriptor.
893 * See bug:
895 * https://bugzilla.samba.org/show_bug.cgi?id=10252
897 * and the smb2.acl2.ACCESSBASED test for details.
900 rejected_share_access = access_mask & ~(fsp->conn->share_access);
901 if (rejected_share_access) {
902 DBG_DEBUG("rejected share access 0x%x "
903 "on %s (0x%x)\n",
904 (unsigned int)access_mask,
905 fsp_str_dbg(fsp),
906 (unsigned int)rejected_share_access);
907 return false;
910 status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp),
911 (SECINFO_OWNER |
912 SECINFO_GROUP |
913 SECINFO_DACL),
914 talloc_tos(),
915 &sd);
917 if (!NT_STATUS_IS_OK(status)) {
918 DBG_DEBUG("Could not get acl "
919 "on %s: %s\n",
920 fsp_str_dbg(fsp),
921 nt_errstr(status));
922 return false;
925 status = se_file_access_check(sd,
926 get_current_nttok(fsp->conn),
927 false,
928 access_mask,
929 &rejected_mask);
931 TALLOC_FREE(sd);
933 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
934 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
935 (unsigned int)rejected_mask,
936 fsp_str_dbg(fsp));
937 return false;
939 return true;
942 /*******************************************************************
943 Check to see if a user can write to an fsp.
944 Always return true for directories.
945 This is only approximate,
946 it is used as part of the "hide unwriteable" option. Don't
947 use it for anything security sensitive.
948 ********************************************************************/
950 static bool user_can_write_fsp(struct files_struct *fsp)
953 * Never hide files from the root user.
954 * We use (uid_t)0 here not sec_initial_uid()
955 * as make test uses a single user context.
958 if (get_current_uid(fsp->conn) == (uid_t)0) {
959 return true;
962 if (fsp->fsp_flags.is_directory) {
963 return true;
966 return can_write_to_fsp(fsp);
969 /*******************************************************************
970 Is a file a "special" type ?
971 ********************************************************************/
973 static bool file_is_special(connection_struct *conn,
974 const struct smb_filename *smb_fname)
977 * Never hide files from the root user.
978 * We use (uid_t)0 here not sec_initial_uid()
979 * as make test uses a single user context.
982 if (get_current_uid(conn) == (uid_t)0) {
983 return False;
986 SMB_ASSERT(VALID_STAT(smb_fname->st));
988 if (S_ISREG(smb_fname->st.st_ex_mode) ||
989 S_ISDIR(smb_fname->st.st_ex_mode) ||
990 S_ISLNK(smb_fname->st.st_ex_mode))
991 return False;
993 return True;
996 /*******************************************************************
997 Should the file be seen by the client?
998 ********************************************************************/
1000 bool is_visible_fsp(struct files_struct *fsp)
1002 bool hide_unreadable = false;
1003 bool hide_unwriteable = false;
1004 bool hide_special = false;
1005 int hide_new_files_timeout = 0;
1006 const char *last_component = NULL;
1009 * If the file does not exist, there's no point checking
1010 * the configuration options. We succeed, on the basis that the
1011 * checks *might* have passed if the file was present.
1013 if (fsp == NULL) {
1014 return true;
1017 hide_unreadable = lp_hide_unreadable(SNUM(fsp->conn));
1018 hide_unwriteable = lp_hide_unwriteable_files(SNUM(fsp->conn));
1019 hide_special = lp_hide_special_files(SNUM(fsp->conn));
1020 hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(fsp->conn));
1022 if (!hide_unreadable &&
1023 !hide_unwriteable &&
1024 !hide_special &&
1025 (hide_new_files_timeout == 0))
1027 return true;
1030 fsp = metadata_fsp(fsp);
1032 /* Get the last component of the base name. */
1033 last_component = strrchr_m(fsp->fsp_name->base_name, '/');
1034 if (!last_component) {
1035 last_component = fsp->fsp_name->base_name;
1036 } else {
1037 last_component++; /* Go past '/' */
1040 if (ISDOT(last_component) || ISDOTDOT(last_component)) {
1041 return true; /* . and .. are always visible. */
1044 if (fsp_get_pathref_fd(fsp) == -1) {
1046 * Symlink in POSIX mode or MS-DFS.
1047 * We've checked veto files so the
1048 * only thing we can check is the
1049 * hide_new_files_timeout.
1051 if ((hide_new_files_timeout != 0) &&
1052 !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1053 double age = timespec_elapsed(
1054 &fsp->fsp_name->st.st_ex_mtime);
1056 if (age < (double)hide_new_files_timeout) {
1057 return false;
1060 return true;
1063 /* Honour _hide unreadable_ option */
1064 if (hide_unreadable && !user_can_read_fsp(fsp)) {
1065 DBG_DEBUG("file %s is unreadable.\n", fsp_str_dbg(fsp));
1066 return false;
1069 /* Honour _hide unwriteable_ option */
1070 if (hide_unwriteable && !user_can_write_fsp(fsp)) {
1071 DBG_DEBUG("file %s is unwritable.\n", fsp_str_dbg(fsp));
1072 return false;
1075 /* Honour _hide_special_ option */
1076 if (hide_special && file_is_special(fsp->conn, fsp->fsp_name)) {
1077 DBG_DEBUG("file %s is special.\n", fsp_str_dbg(fsp));
1078 return false;
1081 if ((hide_new_files_timeout != 0) &&
1082 !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1083 double age = timespec_elapsed(&fsp->fsp_name->st.st_ex_mtime);
1085 if (age < (double)hide_new_files_timeout) {
1086 return false;
1090 return true;
1093 static int smb_Dir_destructor(struct smb_Dir *dir_hnd)
1095 files_struct *fsp = dir_hnd->fsp;
1097 SMB_VFS_CLOSEDIR(dir_hnd->conn, dir_hnd->dir);
1098 fsp_set_fd(fsp, -1);
1099 if (fsp->dptr != NULL) {
1100 SMB_ASSERT(fsp->dptr->dir_hnd == dir_hnd);
1101 fsp->dptr->dir_hnd = NULL;
1103 dir_hnd->fsp = NULL;
1104 return 0;
1107 /*******************************************************************
1108 Open a directory.
1109 ********************************************************************/
1111 static int smb_Dir_OpenDir_destructor(struct smb_Dir *dir_hnd)
1113 files_struct *fsp = dir_hnd->fsp;
1115 smb_Dir_destructor(dir_hnd);
1116 file_free(NULL, fsp);
1117 return 0;
1120 NTSTATUS OpenDir(TALLOC_CTX *mem_ctx,
1121 connection_struct *conn,
1122 const struct smb_filename *smb_dname,
1123 const char *mask,
1124 uint32_t attr,
1125 struct smb_Dir **_dir_hnd)
1127 struct files_struct *fsp = NULL;
1128 struct smb_Dir *dir_hnd = NULL;
1129 NTSTATUS status;
1131 status = open_internal_dirfsp(conn,
1132 smb_dname,
1133 O_RDONLY,
1134 &fsp);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 return status;
1139 status = OpenDir_fsp(mem_ctx, conn, fsp, mask, attr, &dir_hnd);
1140 if (!NT_STATUS_IS_OK(status)) {
1141 return status;
1145 * This overwrites the destructor set by OpenDir_fsp() but
1146 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1147 * destructor.
1149 talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1151 *_dir_hnd = dir_hnd;
1152 return NT_STATUS_OK;
1155 NTSTATUS OpenDir_from_pathref(TALLOC_CTX *mem_ctx,
1156 struct files_struct *dirfsp,
1157 const char *mask,
1158 uint32_t attr,
1159 struct smb_Dir **_dir_hnd)
1161 struct files_struct *fsp = NULL;
1162 struct smb_Dir *dir_hnd = NULL;
1163 NTSTATUS status;
1165 status = openat_internal_dir_from_pathref(dirfsp, O_RDONLY, &fsp);
1166 if (!NT_STATUS_IS_OK(status)) {
1167 return status;
1170 status = OpenDir_fsp(mem_ctx, fsp->conn, fsp, mask, attr, &dir_hnd);
1171 if (!NT_STATUS_IS_OK(status)) {
1172 return status;
1176 * This overwrites the destructor set by OpenDir_fsp() but
1177 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1178 * destructor.
1180 talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1182 *_dir_hnd = dir_hnd;
1183 return NT_STATUS_OK;
1186 /*******************************************************************
1187 Open a directory from an fsp.
1188 ********************************************************************/
1190 static NTSTATUS OpenDir_fsp(
1191 TALLOC_CTX *mem_ctx,
1192 connection_struct *conn,
1193 files_struct *fsp,
1194 const char *mask,
1195 uint32_t attr,
1196 struct smb_Dir **_dir_hnd)
1198 struct smb_Dir *dir_hnd = talloc_zero(mem_ctx, struct smb_Dir);
1199 NTSTATUS status;
1201 if (!dir_hnd) {
1202 return NT_STATUS_NO_MEMORY;
1205 if (!fsp->fsp_flags.is_directory) {
1206 status = NT_STATUS_INVALID_HANDLE;
1207 goto fail;
1210 if (fsp_get_io_fd(fsp) == -1) {
1211 status = NT_STATUS_INVALID_HANDLE;
1212 goto fail;
1215 dir_hnd->conn = conn;
1217 dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, fsp->fsp_name);
1218 if (!dir_hnd->dir_smb_fname) {
1219 status = NT_STATUS_NO_MEMORY;
1220 goto fail;
1223 dir_hnd->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1224 if (dir_hnd->dir == NULL) {
1225 status = map_nt_error_from_unix(errno);
1226 goto fail;
1228 dir_hnd->fsp = fsp;
1229 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1230 dir_hnd->case_sensitive = true;
1231 } else {
1232 dir_hnd->case_sensitive = conn->case_sensitive;
1235 talloc_set_destructor(dir_hnd, smb_Dir_destructor);
1237 *_dir_hnd = dir_hnd;
1238 return NT_STATUS_OK;
1240 fail:
1241 TALLOC_FREE(dir_hnd);
1242 return status;
1246 /*******************************************************************
1247 Read from a directory.
1248 Return directory entry, current offset, and optional stat information.
1249 Don't check for veto or invisible files.
1250 ********************************************************************/
1252 const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
1254 const char *n;
1255 char *talloced = NULL;
1256 connection_struct *conn = dir_hnd->conn;
1258 if (dir_hnd->file_number < 2) {
1259 if (dir_hnd->file_number == 0) {
1260 n = ".";
1261 } else {
1262 n = "..";
1264 dir_hnd->file_number++;
1265 *ptalloced = NULL;
1266 return n;
1269 while ((n = vfs_readdirname(conn,
1270 dir_hnd->fsp,
1271 dir_hnd->dir,
1272 &talloced))) {
1273 /* Ignore . and .. - we've already returned them. */
1274 if (ISDOT(n) || ISDOTDOT(n)) {
1275 TALLOC_FREE(talloced);
1276 continue;
1278 *ptalloced = talloced;
1279 dir_hnd->file_number++;
1280 return n;
1282 *ptalloced = NULL;
1283 return NULL;
1286 /*******************************************************************
1287 Rewind to the start.
1288 ********************************************************************/
1290 void RewindDir(struct smb_Dir *dir_hnd)
1292 SMB_VFS_REWINDDIR(dir_hnd->conn, dir_hnd->dir);
1293 dir_hnd->file_number = 0;
1296 struct files_below_forall_state {
1297 char *dirpath;
1298 ssize_t dirpath_len;
1299 int (*fn)(struct file_id fid, const struct share_mode_data *data,
1300 void *private_data);
1301 void *private_data;
1304 static int files_below_forall_fn(struct file_id fid,
1305 const struct share_mode_data *data,
1306 void *private_data)
1308 struct files_below_forall_state *state = private_data;
1309 char tmpbuf[PATH_MAX];
1310 char *fullpath, *to_free;
1311 ssize_t len;
1313 len = full_path_tos(data->servicepath, data->base_name,
1314 tmpbuf, sizeof(tmpbuf),
1315 &fullpath, &to_free);
1316 if (len == -1) {
1317 return 0;
1319 if (state->dirpath_len >= len) {
1321 * Filter files above dirpath
1323 goto out;
1325 if (fullpath[state->dirpath_len] != '/') {
1327 * Filter file that don't have a path separator at the end of
1328 * dirpath's length
1330 goto out;
1333 if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
1335 * Not a parent
1337 goto out;
1340 TALLOC_FREE(to_free);
1341 return state->fn(fid, data, state->private_data);
1343 out:
1344 TALLOC_FREE(to_free);
1345 return 0;
1348 static int files_below_forall(connection_struct *conn,
1349 const struct smb_filename *dir_name,
1350 int (*fn)(struct file_id fid,
1351 const struct share_mode_data *data,
1352 void *private_data),
1353 void *private_data)
1355 struct files_below_forall_state state = {
1356 .fn = fn,
1357 .private_data = private_data,
1359 int ret;
1360 char tmpbuf[PATH_MAX];
1361 char *to_free;
1363 state.dirpath_len = full_path_tos(conn->connectpath,
1364 dir_name->base_name,
1365 tmpbuf, sizeof(tmpbuf),
1366 &state.dirpath, &to_free);
1367 if (state.dirpath_len == -1) {
1368 return -1;
1371 ret = share_mode_forall(files_below_forall_fn, &state);
1372 TALLOC_FREE(to_free);
1373 return ret;
1376 struct have_file_open_below_state {
1377 bool found_one;
1380 static int have_file_open_below_fn(struct file_id fid,
1381 const struct share_mode_data *data,
1382 void *private_data)
1384 struct have_file_open_below_state *state = private_data;
1385 state->found_one = true;
1386 return 1;
1389 bool have_file_open_below(connection_struct *conn,
1390 const struct smb_filename *name)
1392 struct have_file_open_below_state state = {
1393 .found_one = false,
1395 int ret;
1397 if (!VALID_STAT(name->st)) {
1398 return false;
1400 if (!S_ISDIR(name->st.st_ex_mode)) {
1401 return false;
1404 ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
1405 if (ret == -1) {
1406 return false;
1409 return state.found_one;
1412 /*****************************************************************
1413 Is this directory empty ?
1414 *****************************************************************/
1416 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
1418 NTSTATUS status = NT_STATUS_OK;
1419 const char *dname = NULL;
1420 char *talloced = NULL;
1421 struct connection_struct *conn = fsp->conn;
1422 struct smb_Dir *dir_hnd = NULL;
1424 status = OpenDir(
1425 talloc_tos(), conn, fsp->fsp_name, NULL, 0, &dir_hnd);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 return status;
1430 while ((dname = ReadDirName(dir_hnd, &talloced))) {
1431 struct smb_filename *smb_dname_full = NULL;
1432 struct smb_filename *direntry_fname = NULL;
1433 char *fullname = NULL;
1434 int ret;
1436 if (ISDOT(dname) || (ISDOTDOT(dname))) {
1437 TALLOC_FREE(talloced);
1438 continue;
1440 if (IS_VETO_PATH(conn, dname)) {
1441 TALLOC_FREE(talloced);
1442 continue;
1445 fullname = talloc_asprintf(talloc_tos(),
1446 "%s/%s",
1447 fsp->fsp_name->base_name,
1448 dname);
1449 if (fullname == NULL) {
1450 status = NT_STATUS_NO_MEMORY;
1451 break;
1454 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1455 fullname,
1456 NULL,
1457 NULL,
1458 fsp->fsp_name->twrp,
1459 fsp->fsp_name->flags);
1460 if (smb_dname_full == NULL) {
1461 TALLOC_FREE(talloced);
1462 TALLOC_FREE(fullname);
1463 status = NT_STATUS_NO_MEMORY;
1464 break;
1467 ret = SMB_VFS_LSTAT(conn, smb_dname_full);
1468 if (ret != 0) {
1469 status = map_nt_error_from_unix(errno);
1470 TALLOC_FREE(talloced);
1471 TALLOC_FREE(fullname);
1472 TALLOC_FREE(smb_dname_full);
1473 break;
1476 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1477 /* Could it be an msdfs link ? */
1478 if (lp_host_msdfs() &&
1479 lp_msdfs_root(SNUM(conn))) {
1480 struct smb_filename *smb_dname;
1481 smb_dname = synthetic_smb_fname(talloc_tos(),
1482 dname,
1483 NULL,
1484 &smb_dname_full->st,
1485 fsp->fsp_name->twrp,
1486 fsp->fsp_name->flags);
1487 if (smb_dname == NULL) {
1488 TALLOC_FREE(talloced);
1489 TALLOC_FREE(fullname);
1490 TALLOC_FREE(smb_dname_full);
1491 status = NT_STATUS_NO_MEMORY;
1492 break;
1494 if (is_msdfs_link(fsp, smb_dname)) {
1495 TALLOC_FREE(talloced);
1496 TALLOC_FREE(fullname);
1497 TALLOC_FREE(smb_dname_full);
1498 TALLOC_FREE(smb_dname);
1499 DBG_DEBUG("got msdfs link name %s "
1500 "- can't delete directory %s\n",
1501 dname,
1502 fsp_str_dbg(fsp));
1503 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1504 break;
1506 TALLOC_FREE(smb_dname);
1508 /* Not a DFS link - could it be a dangling symlink ? */
1509 ret = SMB_VFS_STAT(conn, smb_dname_full);
1510 if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
1512 * Dangling symlink.
1513 * Allow if "delete veto files = yes"
1515 if (lp_delete_veto_files(SNUM(conn))) {
1516 TALLOC_FREE(talloced);
1517 TALLOC_FREE(fullname);
1518 TALLOC_FREE(smb_dname_full);
1519 continue;
1522 DBG_DEBUG("got symlink name %s - "
1523 "can't delete directory %s\n",
1524 dname,
1525 fsp_str_dbg(fsp));
1526 TALLOC_FREE(talloced);
1527 TALLOC_FREE(fullname);
1528 TALLOC_FREE(smb_dname_full);
1529 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1530 break;
1533 /* Not a symlink, get a pathref. */
1534 status = synthetic_pathref(talloc_tos(),
1535 fsp,
1536 dname,
1537 NULL,
1538 &smb_dname_full->st,
1539 fsp->fsp_name->twrp,
1540 fsp->fsp_name->flags,
1541 &direntry_fname);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 status = map_nt_error_from_unix(errno);
1544 TALLOC_FREE(talloced);
1545 TALLOC_FREE(fullname);
1546 TALLOC_FREE(smb_dname_full);
1547 break;
1550 if (!is_visible_fsp(direntry_fname->fsp)) {
1552 * Hidden file.
1553 * Allow if "delete veto files = yes"
1555 if (lp_delete_veto_files(SNUM(conn))) {
1556 TALLOC_FREE(talloced);
1557 TALLOC_FREE(fullname);
1558 TALLOC_FREE(smb_dname_full);
1559 TALLOC_FREE(direntry_fname);
1560 continue;
1564 TALLOC_FREE(talloced);
1565 TALLOC_FREE(fullname);
1566 TALLOC_FREE(smb_dname_full);
1567 TALLOC_FREE(direntry_fname);
1569 DBG_DEBUG("got name %s - can't delete\n", dname);
1570 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1571 break;
1573 TALLOC_FREE(talloced);
1574 TALLOC_FREE(dir_hnd);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 return status;
1580 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
1581 lp_strict_rename(SNUM(conn)) &&
1582 have_file_open_below(fsp->conn, fsp->fsp_name))
1584 return NT_STATUS_ACCESS_DENIED;
1587 return NT_STATUS_OK;