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/>.
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. */
44 connection_struct
*conn
;
46 struct smb_filename
*dir_smb_fname
;
47 unsigned int file_number
;
49 files_struct
*fsp
; /* Back pointer to containing fsp, only
50 set from OpenDir_fsp(). */
54 struct dptr_struct
*next
, *prev
;
56 struct connection_struct
*conn
;
57 struct smb_Dir
*dir_hnd
;
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. */
65 char *last_name_sent
; /* for name-based trans2 resume */
69 struct smb_filename
*smb_fname
;
74 static NTSTATUS
OpenDir_fsp(
76 connection_struct
*conn
,
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
) {
96 sconn
->searches
.dptr_bmap
= bitmap_talloc(
97 sconn
, MAX_DIRECTORY_HANDLES
);
99 if (sconn
->searches
.dptr_bmap
== NULL
) {
106 /****************************************************************************
107 Get the struct dptr_struct for a dir index.
108 ****************************************************************************/
110 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
113 struct dptr_struct
*dptr
;
115 for (dptr
= sconn
->searches
.dirptrs
; dptr
!= NULL
; dptr
= dptr
->next
) {
116 if(dptr
->dnum
!= key
) {
119 DLIST_PROMOTE(sconn
->searches
.dirptrs
, dptr
);
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
);
133 return(dptr
->dir_hnd
->dir_smb_fname
->base_name
);
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
);
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
);
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
;
174 for(dptr
= sconn
->searches
.dirptrs
; dptr
; 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
,
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
;
209 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp
));
212 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
213 return NT_STATUS_INTERNAL_ERROR
;
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",
224 return NT_STATUS_ACCESS_DENIED
;
226 status
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
, &dir_hnd
);
227 if (!NT_STATUS_IS_OK(status
)) {
231 dptr
= talloc_zero(NULL
, struct dptr_struct
);
233 DEBUG(0,("talloc fail in dptr_create.\n"));
234 TALLOC_FREE(dir_hnd
);
235 return NT_STATUS_NO_MEMORY
;
239 dptr
->dir_hnd
= dir_hnd
;
240 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
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
;
249 dptr
->has_wild
= ms_has_wild(dptr
->wcard
);
254 if (sconn
->using_smb2
) {
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",
272 TALLOC_FREE(dir_hnd
);
273 return NT_STATUS_TOO_MANY_OPENED_FILES
;
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",
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
);
301 DBG_INFO("creating new dirptr [%d] for path [%s]\n",
302 dptr
->dnum
, fsp_str_dbg(fsp
));
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
) {
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",
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
)
375 bool dptr_get_priv(struct dptr_struct
*dptr
)
380 void dptr_set_priv(struct dptr_struct
*dptr
)
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
= {
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;
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
) {
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.
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
);
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
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
466 (!dir_hnd
->case_sensitive
&&
467 (dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
));
469 if (retry_scanning
) {
470 char *found_name
= NULL
;
473 status
= get_real_filename_at(dir_fsp
,
477 if (NT_STATUS_IS_OK(status
)) {
485 struct files_struct
*dir_hnd_fetch_fsp(struct smb_Dir
*dir_hnd
)
490 /****************************************************************************
491 Fetch the fsp associated with the dptr_num.
492 ****************************************************************************/
494 files_struct
*dptr_fetch_lanman2_fsp(struct smbd_server_connection
*sconn
,
497 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
);
501 DBG_NOTICE("fetching dirptr %d for path %s\n",
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
,
514 bool (*match_fn
)(TALLOC_CTX
*ctx
,
519 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
521 struct files_struct
*dirfsp
,
522 struct smb_filename
*atname
,
523 struct smb_filename
*smb_fname
,
528 struct smb_filename
**_smb_fname
,
531 connection_struct
*conn
= dirptr
->conn
;
532 struct smb_Dir
*dir_hnd
= dirptr
->dir_hnd
;
535 const char *dpath
= dir_hnd
->dir_smb_fname
->base_name
;
536 bool dirptr_path_is_dot
= ISDOT(dpath
);
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
;
549 pathlen
= strlen(dpath
);
550 slashlen
= ( dpath
[pathlen
-1] != '/') ? 1 : 0;
556 char *pathreal
= NULL
;
557 struct smb_filename
*atname
= NULL
;
558 struct smb_filename
*smb_fname
= NULL
;
560 bool check_dfs_symlink
= false;
561 bool get_dosmode
= get_dosmode_in
;
564 dname
= dptr_ReadDirName(ctx
, dirptr
);
566 DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
568 smb_fname_str_dbg(dir_hnd
->dir_smb_fname
),
570 dir_hnd
->file_number
,
571 dname
? dname
: "(finished)");
577 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
578 if (dont_descend
&& !isdots
) {
583 if (IS_VETO_PATH(conn
, dname
)) {
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
);
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(
609 pathlen
+ slashlen
+ talloc_get_size(dname
));
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
));
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(),
634 dir_hnd
->dir_smb_fname
->twrp
,
635 dir_hnd
->dir_smb_fname
->flags
);
636 TALLOC_FREE(pathreal
);
637 if (smb_fname
== NULL
) {
643 /* Create smb_fname with NULL stream_name. */
644 atname
= synthetic_smb_fname(talloc_tos(),
648 dir_hnd
->dir_smb_fname
->twrp
,
649 dir_hnd
->dir_smb_fname
->flags
);
650 if (atname
== NULL
) {
653 TALLOC_FREE(smb_fname
);
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
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
))
675 TALLOC_FREE(smb_fname
);
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
;
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
),
706 TALLOC_FREE(smb_fname
);
712 if (!is_visible_fsp(smb_fname
->fsp
)) {
714 TALLOC_FREE(smb_fname
);
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
) {
734 TALLOC_FREE(smb_fname
);
739 TALLOC_FREE(smb_fname
);
740 smb_fname
= tmp_smb_fname
;
741 mode
= FILE_ATTRIBUTE_DIRECTORY
;
754 TALLOC_FREE(smb_fname
);
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
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
);
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
);
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
,
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
,
816 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
818 mask
, smb_fname_str_dbg(smb_fname
),
823 *_smb_fname
= talloc_move(ctx
, &smb_fname
);
824 if (*_smb_fname
== NULL
) {
836 void smbd_dirptr_push_overflow(struct dptr_struct
*dirptr
,
838 struct smb_filename
**_smb_fname
,
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
,
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
)
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
|
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) {
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.
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 "
904 (unsigned int)access_mask
,
906 (unsigned int)rejected_share_access
);
910 status
= SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp
),
917 if (!NT_STATUS_IS_OK(status
)) {
918 DBG_DEBUG("Could not get acl "
925 status
= se_file_access_check(sd
,
926 get_current_nttok(fsp
->conn
),
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
,
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) {
962 if (fsp
->fsp_flags
.is_directory
) {
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) {
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
))
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.
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
&&
1025 (hide_new_files_timeout
== 0))
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
;
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
) {
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
));
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
));
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
));
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
) {
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
;
1107 /*******************************************************************
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
);
1120 NTSTATUS
OpenDir(TALLOC_CTX
*mem_ctx
,
1121 connection_struct
*conn
,
1122 const struct smb_filename
*smb_dname
,
1125 struct smb_Dir
**_dir_hnd
)
1127 struct files_struct
*fsp
= NULL
;
1128 struct smb_Dir
*dir_hnd
= NULL
;
1131 status
= open_internal_dirfsp(conn
,
1135 if (!NT_STATUS_IS_OK(status
)) {
1139 status
= OpenDir_fsp(mem_ctx
, conn
, fsp
, mask
, attr
, &dir_hnd
);
1140 if (!NT_STATUS_IS_OK(status
)) {
1145 * This overwrites the destructor set by OpenDir_fsp() but
1146 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
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
,
1159 struct smb_Dir
**_dir_hnd
)
1161 struct files_struct
*fsp
= NULL
;
1162 struct smb_Dir
*dir_hnd
= NULL
;
1165 status
= openat_internal_dir_from_pathref(dirfsp
, O_RDONLY
, &fsp
);
1166 if (!NT_STATUS_IS_OK(status
)) {
1170 status
= OpenDir_fsp(mem_ctx
, fsp
->conn
, fsp
, mask
, attr
, &dir_hnd
);
1171 if (!NT_STATUS_IS_OK(status
)) {
1176 * This overwrites the destructor set by OpenDir_fsp() but
1177 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
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
,
1196 struct smb_Dir
**_dir_hnd
)
1198 struct smb_Dir
*dir_hnd
= talloc_zero(mem_ctx
, struct smb_Dir
);
1202 return NT_STATUS_NO_MEMORY
;
1205 if (!fsp
->fsp_flags
.is_directory
) {
1206 status
= NT_STATUS_INVALID_HANDLE
;
1210 if (fsp_get_io_fd(fsp
) == -1) {
1211 status
= NT_STATUS_INVALID_HANDLE
;
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
;
1223 dir_hnd
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1224 if (dir_hnd
->dir
== NULL
) {
1225 status
= map_nt_error_from_unix(errno
);
1229 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
) {
1230 dir_hnd
->case_sensitive
= true;
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
;
1241 TALLOC_FREE(dir_hnd
);
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
)
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) {
1264 dir_hnd
->file_number
++;
1269 while ((n
= vfs_readdirname(conn
,
1273 /* Ignore . and .. - we've already returned them. */
1274 if (ISDOT(n
) || ISDOTDOT(n
)) {
1275 TALLOC_FREE(talloced
);
1278 *ptalloced
= talloced
;
1279 dir_hnd
->file_number
++;
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
{
1298 ssize_t dirpath_len
;
1299 int (*fn
)(struct file_id fid
, const struct share_mode_data
*data
,
1300 void *private_data
);
1304 static int files_below_forall_fn(struct file_id fid
,
1305 const struct share_mode_data
*data
,
1308 struct files_below_forall_state
*state
= private_data
;
1309 char tmpbuf
[PATH_MAX
];
1310 char *fullpath
, *to_free
;
1313 len
= full_path_tos(data
->servicepath
, data
->base_name
,
1314 tmpbuf
, sizeof(tmpbuf
),
1315 &fullpath
, &to_free
);
1319 if (state
->dirpath_len
>= len
) {
1321 * Filter files above dirpath
1325 if (fullpath
[state
->dirpath_len
] != '/') {
1327 * Filter file that don't have a path separator at the end of
1333 if (memcmp(state
->dirpath
, fullpath
, state
->dirpath_len
) != 0) {
1340 TALLOC_FREE(to_free
);
1341 return state
->fn(fid
, data
, state
->private_data
);
1344 TALLOC_FREE(to_free
);
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
),
1355 struct files_below_forall_state state
= {
1357 .private_data
= private_data
,
1360 char tmpbuf
[PATH_MAX
];
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) {
1371 ret
= share_mode_forall(files_below_forall_fn
, &state
);
1372 TALLOC_FREE(to_free
);
1376 struct have_file_open_below_state
{
1380 static int have_file_open_below_fn(struct file_id fid
,
1381 const struct share_mode_data
*data
,
1384 struct have_file_open_below_state
*state
= private_data
;
1385 state
->found_one
= true;
1389 bool have_file_open_below(connection_struct
*conn
,
1390 const struct smb_filename
*name
)
1392 struct have_file_open_below_state state
= {
1397 if (!VALID_STAT(name
->st
)) {
1400 if (!S_ISDIR(name
->st
.st_ex_mode
)) {
1404 ret
= files_below_forall(conn
, name
, have_file_open_below_fn
, &state
);
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
;
1425 talloc_tos(), conn
, fsp
->fsp_name
, NULL
, 0, &dir_hnd
);
1426 if (!NT_STATUS_IS_OK(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
;
1436 if (ISDOT(dname
) || (ISDOTDOT(dname
))) {
1437 TALLOC_FREE(talloced
);
1440 if (IS_VETO_PATH(conn
, dname
)) {
1441 TALLOC_FREE(talloced
);
1445 fullname
= talloc_asprintf(talloc_tos(),
1447 fsp
->fsp_name
->base_name
,
1449 if (fullname
== NULL
) {
1450 status
= NT_STATUS_NO_MEMORY
;
1454 smb_dname_full
= synthetic_smb_fname(talloc_tos(),
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
;
1467 ret
= SMB_VFS_LSTAT(conn
, smb_dname_full
);
1469 status
= map_nt_error_from_unix(errno
);
1470 TALLOC_FREE(talloced
);
1471 TALLOC_FREE(fullname
);
1472 TALLOC_FREE(smb_dname_full
);
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(),
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
;
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",
1503 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
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
)) {
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
);
1522 DBG_DEBUG("got symlink name %s - "
1523 "can't delete directory %s\n",
1526 TALLOC_FREE(talloced
);
1527 TALLOC_FREE(fullname
);
1528 TALLOC_FREE(smb_dname_full
);
1529 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1533 /* Not a symlink, get a pathref. */
1534 status
= synthetic_pathref(talloc_tos(),
1538 &smb_dname_full
->st
,
1539 fsp
->fsp_name
->twrp
,
1540 fsp
->fsp_name
->flags
,
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
);
1550 if (!is_visible_fsp(direntry_fname
->fsp
)) {
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
);
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
;
1573 TALLOC_FREE(talloced
);
1574 TALLOC_FREE(dir_hnd
);
1576 if (!NT_STATUS_IS_OK(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
;