pyldb: avoid segfault when adding an element with no name
[nivanova/samba-autobuild/.git] / source3 / smbd / dir.c
1 /*
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2007
6
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.
11
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.
16
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/>.
19 */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "libcli/security/security.h"
26 #include "lib/util/bitmap.h"
27 #include "../lib/util/memcache.h"
28 #include "../librpc/gen_ndr/open_files.h"
29
30 /*
31    This module implements directory related functions for Samba.
32 */
33
34 /* "Special" directory offsets. */
35 #define END_OF_DIRECTORY_OFFSET ((long)-1)
36 #define START_OF_DIRECTORY_OFFSET ((long)0)
37 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
38
39 /* "Special" directory offsets in 32-bit wire format. */
40 #define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
41 #define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
42 #define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
43
44 /* Make directory handle internals available. */
45
46 struct name_cache_entry {
47         char *name;
48         long offset;
49 };
50
51 struct smb_Dir {
52         connection_struct *conn;
53         DIR *dir;
54         long offset;
55         struct smb_filename *dir_smb_fname;
56         size_t name_cache_size;
57         struct name_cache_entry *name_cache;
58         unsigned int name_cache_index;
59         unsigned int file_number;
60         files_struct *fsp; /* Back pointer to containing fsp, only
61                               set from OpenDir_fsp(). */
62 };
63
64 struct dptr_struct {
65         struct dptr_struct *next, *prev;
66         int dnum;
67         uint16_t spid;
68         struct connection_struct *conn;
69         struct smb_Dir *dir_hnd;
70         bool expect_close;
71         char *wcard;
72         uint32_t attr;
73         struct smb_filename *smb_dname;
74         bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
75         bool did_stat; /* Optimisation for non-wcard searches. */
76         bool priv;     /* Directory handle opened with privilege. */
77         uint32_t counter;
78         struct memcache *dptr_cache;
79 };
80
81 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
82                         files_struct *fsp,
83                         const char *mask,
84                         uint32_t attr);
85
86 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset);
87
88 #define INVALID_DPTR_KEY (-3)
89
90 /****************************************************************************
91  Initialise the dir bitmap.
92 ****************************************************************************/
93
94 bool init_dptrs(struct smbd_server_connection *sconn)
95 {
96         if (sconn->searches.dptr_bmap) {
97                 return true;
98         }
99
100         sconn->searches.dptr_bmap = bitmap_talloc(
101                 sconn, MAX_DIRECTORY_HANDLES);
102
103         if (sconn->searches.dptr_bmap == NULL) {
104                 return false;
105         }
106
107         return true;
108 }
109
110 /****************************************************************************
111  Idle a dptr - the directory is closed but the control info is kept.
112 ****************************************************************************/
113
114 static void dptr_idle(struct dptr_struct *dptr)
115 {
116         if (dptr->dir_hnd) {
117                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
118                 TALLOC_FREE(dptr->dir_hnd);
119                 TALLOC_FREE(dptr->dptr_cache);
120                 dptr->counter = 0;
121         }
122 }
123
124 /****************************************************************************
125  Idle the oldest dptr.
126 ****************************************************************************/
127
128 static void dptr_idleoldest(struct smbd_server_connection *sconn)
129 {
130         struct dptr_struct *dptr;
131
132         /*
133          * Go to the end of the list.
134          */
135         dptr = DLIST_TAIL(sconn->searches.dirptrs);
136
137         if(!dptr) {
138                 DEBUG(0,("No dptrs available to idle ?\n"));
139                 return;
140         }
141
142         /*
143          * Idle the oldest pointer.
144          */
145
146         for(; dptr; dptr = DLIST_PREV(dptr)) {
147                 if (dptr->dir_hnd) {
148                         dptr_idle(dptr);
149                         return;
150                 }
151         }
152 }
153
154 /****************************************************************************
155  Get the struct dptr_struct for a dir index.
156 ****************************************************************************/
157
158 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
159                                     int key, bool forclose)
160 {
161         struct dptr_struct *dptr;
162         const int dirhandles_open = sconn->searches.dirhandles_open;
163
164         for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
165                 if(dptr->dnum != key) {
166                         continue;
167                 }
168
169                 if (!forclose && (dptr->dir_hnd == NULL)) {
170                         if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
171                                 dptr_idleoldest(sconn);
172                         }
173                         DBG_INFO("Reopening dptr key %d\n",key);
174
175                         dptr->dir_hnd = OpenDir(NULL,
176                                                 dptr->conn,
177                                                 dptr->smb_dname,
178                                                 dptr->wcard,
179                                                 dptr->attr);
180
181                         if (dptr->dir_hnd == NULL) {
182                                 DBG_INFO("Failed to open %s (%s)\n",
183                                       dptr->smb_dname->base_name,
184                                       strerror(errno));
185                                 return NULL;
186                         }
187                 }
188                 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
189                 return dptr;
190         }
191         return(NULL);
192 }
193
194 /****************************************************************************
195  Get the dir path for a dir index.
196 ****************************************************************************/
197
198 const char *dptr_path(struct smbd_server_connection *sconn, int key)
199 {
200         struct dptr_struct *dptr = dptr_get(sconn, key, false);
201         if (dptr)
202                 return(dptr->smb_dname->base_name);
203         return(NULL);
204 }
205
206 /****************************************************************************
207  Get the dir wcard for a dir index.
208 ****************************************************************************/
209
210 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
211 {
212         struct dptr_struct *dptr = dptr_get(sconn, key, false);
213         if (dptr)
214                 return(dptr->wcard);
215         return(NULL);
216 }
217
218 /****************************************************************************
219  Get the dir attrib for a dir index.
220 ****************************************************************************/
221
222 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
223 {
224         struct dptr_struct *dptr = dptr_get(sconn, key, false);
225         if (dptr)
226                 return(dptr->attr);
227         return(0);
228 }
229
230 /****************************************************************************
231  Close a dptr (internal func).
232 ****************************************************************************/
233
234 static void dptr_close_internal(struct dptr_struct *dptr)
235 {
236         struct smbd_server_connection *sconn = dptr->conn->sconn;
237
238         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
239
240         if (sconn == NULL) {
241                 goto done;
242         }
243
244         if (sconn->using_smb2) {
245                 goto done;
246         }
247
248         DLIST_REMOVE(sconn->searches.dirptrs, dptr);
249
250         /*
251          * Free the dnum in the bitmap. Remember the dnum value is always 
252          * biased by one with respect to the bitmap.
253          */
254
255         if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
256                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
257                         dptr->dnum ));
258         }
259
260         bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
261
262 done:
263         TALLOC_FREE(dptr->dir_hnd);
264         TALLOC_FREE(dptr);
265 }
266
267 /****************************************************************************
268  Close a dptr given a key.
269 ****************************************************************************/
270
271 void dptr_close(struct smbd_server_connection *sconn, int *key)
272 {
273         struct dptr_struct *dptr;
274
275         if(*key == INVALID_DPTR_KEY)
276                 return;
277
278         /* OS/2 seems to use -1 to indicate "close all directories" */
279         if (*key == -1) {
280                 struct dptr_struct *next;
281                 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
282                         next = dptr->next;
283                         dptr_close_internal(dptr);
284                 }
285                 *key = INVALID_DPTR_KEY;
286                 return;
287         }
288
289         dptr = dptr_get(sconn, *key, true);
290
291         if (!dptr) {
292                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
293                 return;
294         }
295
296         dptr_close_internal(dptr);
297
298         *key = INVALID_DPTR_KEY;
299 }
300
301 /****************************************************************************
302  Close all dptrs for a cnum.
303 ****************************************************************************/
304
305 void dptr_closecnum(connection_struct *conn)
306 {
307         struct dptr_struct *dptr, *next;
308         struct smbd_server_connection *sconn = conn->sconn;
309
310         if (sconn == NULL) {
311                 return;
312         }
313
314         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
315                 next = dptr->next;
316                 if (dptr->conn == conn) {
317                         dptr_close_internal(dptr);
318                 }
319         }
320 }
321
322 /****************************************************************************
323  Idle all dptrs for a cnum.
324 ****************************************************************************/
325
326 void dptr_idlecnum(connection_struct *conn)
327 {
328         struct dptr_struct *dptr;
329         struct smbd_server_connection *sconn = conn->sconn;
330
331         if (sconn == NULL) {
332                 return;
333         }
334
335         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
336                 if (dptr->conn == conn && dptr->dir_hnd) {
337                         dptr_idle(dptr);
338                 }
339         }
340 }
341
342 /****************************************************************************
343  Close a dptr that matches a given path, only if it matches the spid also.
344 ****************************************************************************/
345
346 void dptr_closepath(struct smbd_server_connection *sconn,
347                     char *path,uint16_t spid)
348 {
349         struct dptr_struct *dptr, *next;
350         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
351                 next = dptr->next;
352                 if (spid == dptr->spid &&
353                                 strequal(dptr->smb_dname->base_name,path)) {
354                         dptr_close_internal(dptr);
355                 }
356         }
357 }
358
359 /****************************************************************************
360  Try and close the oldest handle not marked for
361  expect close in the hope that the client has
362  finished with that one.
363 ****************************************************************************/
364
365 static void dptr_close_oldest(struct smbd_server_connection *sconn,
366                               bool old)
367 {
368         struct dptr_struct *dptr;
369
370         /*
371          * Go to the end of the list.
372          */
373         for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
374                 ;
375
376         if(!dptr) {
377                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
378                 return;
379         }
380
381         /*
382          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
383          * does not have expect_close set. If 'old' is false, close
384          * one of the new dnum handles.
385          */
386
387         for(; dptr; dptr = DLIST_PREV(dptr)) {
388                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
389                         (!old && (dptr->dnum > 255))) {
390                                 dptr_close_internal(dptr);
391                                 return;
392                 }
393         }
394 }
395
396 /****************************************************************************
397  Safely do an OpenDir as root, ensuring we're in the right place.
398 ****************************************************************************/
399
400 static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
401                                         struct smb_request *req,
402                                         const struct smb_filename *smb_dname,
403                                         const char *wcard,
404                                         uint32_t attr)
405 {
406         struct smb_Dir *dir_hnd = NULL;
407         struct smb_filename *smb_fname_cwd = NULL;
408         struct smb_filename *saved_dir_fname = vfs_GetWd(talloc_tos(), conn);
409         struct privilege_paths *priv_paths = req->priv_paths;
410         int ret;
411
412         if (saved_dir_fname == NULL) {
413                 return NULL;
414         }
415
416         if (vfs_ChDir(conn, smb_dname) == -1) {
417                 return NULL;
418         }
419
420         /* Now check the stat value is the same. */
421         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
422                                         ".",
423                                         NULL,
424                                         NULL,
425                                         smb_dname->flags);
426         if (smb_fname_cwd == NULL) {
427                 goto out;
428         }
429         ret = SMB_VFS_STAT(conn, smb_fname_cwd);
430         if (ret != 0) {
431                 goto out;
432         }
433
434         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
435                 DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
436                         "and %s\n",
437                         smb_dname->base_name,
438                         smb_fname_str_dbg(&priv_paths->parent_name)));
439                 goto out;
440         }
441
442         dir_hnd = OpenDir(NULL, conn, smb_fname_cwd, wcard, attr);
443
444   out:
445
446         vfs_ChDir(conn, saved_dir_fname);
447         TALLOC_FREE(saved_dir_fname);
448         return dir_hnd;
449 }
450
451 /****************************************************************************
452  Create a new dir ptr. If the flag old_handle is true then we must allocate
453  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
454  one byte long. If old_handle is false we allocate from the range
455  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
456  a directory handle is never zero.
457  wcard must not be zero.
458 ****************************************************************************/
459
460 NTSTATUS dptr_create(connection_struct *conn,
461                 struct smb_request *req,
462                 files_struct *fsp,
463                 const struct smb_filename *smb_dname,
464                 bool old_handle,
465                 bool expect_close,
466                 uint16_t spid,
467                 const char *wcard,
468                 bool wcard_has_wild,
469                 uint32_t attr,
470                 struct dptr_struct **dptr_ret)
471 {
472         struct smbd_server_connection *sconn = conn->sconn;
473         struct dptr_struct *dptr = NULL;
474         struct smb_Dir *dir_hnd;
475
476         if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
477                 smb_dname = fsp->fsp_name;
478         }
479
480         DEBUG(5,("dptr_create dir=%s\n", smb_dname->base_name));
481
482         if (sconn == NULL) {
483                 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
484                 return NT_STATUS_INTERNAL_ERROR;
485         }
486
487         if (!wcard) {
488                 return NT_STATUS_INVALID_PARAMETER;
489         }
490
491         if (fsp) {
492                 if (!(fsp->access_mask & SEC_DIR_LIST)) {
493                         DEBUG(5,("dptr_create: directory %s "
494                                 "not open for LIST access\n",
495                                 smb_dname->base_name));
496                         return NT_STATUS_ACCESS_DENIED;
497                 }
498                 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
499         } else {
500                 int ret;
501                 bool backup_intent = (req && req->priv_paths);
502                 NTSTATUS status;
503                 struct smb_filename *smb_dname_cp =
504                         cp_smb_filename(talloc_tos(), smb_dname);
505
506                 if (smb_dname_cp == NULL) {
507                         return NT_STATUS_NO_MEMORY;
508                 }
509
510                 if (req != NULL && req->posix_pathnames) {
511                         ret = SMB_VFS_LSTAT(conn, smb_dname_cp);
512                 } else {
513                         ret = SMB_VFS_STAT(conn, smb_dname_cp);
514                 }
515                 if (ret == -1) {
516                         status = map_nt_error_from_unix(errno);
517                         TALLOC_FREE(smb_dname_cp);
518                         return status;
519                 }
520                 if (!S_ISDIR(smb_dname_cp->st.st_ex_mode)) {
521                         TALLOC_FREE(smb_dname_cp);
522                         return NT_STATUS_NOT_A_DIRECTORY;
523                 }
524                 status = smbd_check_access_rights(conn,
525                                                 smb_dname_cp,
526                                                 backup_intent,
527                                                 SEC_DIR_LIST);
528                 if (!NT_STATUS_IS_OK(status)) {
529                         TALLOC_FREE(smb_dname_cp);
530                         return status;
531                 }
532                 if (backup_intent) {
533                         dir_hnd = open_dir_with_privilege(conn,
534                                                 req,
535                                                 smb_dname_cp,
536                                                 wcard,
537                                                 attr);
538                 } else {
539                         dir_hnd = OpenDir(NULL,
540                                         conn,
541                                         smb_dname_cp,
542                                         wcard,
543                                         attr);
544                 }
545                 TALLOC_FREE(smb_dname_cp);
546         }
547
548         if (!dir_hnd) {
549                 return map_nt_error_from_unix(errno);
550         }
551
552         if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
553                 dptr_idleoldest(sconn);
554         }
555
556         dptr = talloc_zero(NULL, struct dptr_struct);
557         if(!dptr) {
558                 DEBUG(0,("talloc fail in dptr_create.\n"));
559                 TALLOC_FREE(dir_hnd);
560                 return NT_STATUS_NO_MEMORY;
561         }
562
563         dptr->smb_dname = cp_smb_filename(dptr, smb_dname);
564         if (!dptr->smb_dname) {
565                 TALLOC_FREE(dptr);
566                 TALLOC_FREE(dir_hnd);
567                 return NT_STATUS_NO_MEMORY;
568         }
569         dptr->conn = conn;
570         dptr->dir_hnd = dir_hnd;
571         dptr->spid = spid;
572         dptr->expect_close = expect_close;
573         dptr->wcard = talloc_strdup(dptr, wcard);
574         if (!dptr->wcard) {
575                 TALLOC_FREE(dptr);
576                 TALLOC_FREE(dir_hnd);
577                 return NT_STATUS_NO_MEMORY;
578         }
579         if ((req != NULL && req->posix_pathnames) ||
580                         (wcard[0] == '.' && wcard[1] == 0)) {
581                 dptr->has_wild = True;
582         } else {
583                 dptr->has_wild = wcard_has_wild;
584         }
585
586         dptr->attr = attr;
587
588         if (sconn->using_smb2) {
589                 goto done;
590         }
591
592         if(old_handle) {
593
594                 /*
595                  * This is an old-style SMBsearch request. Ensure the
596                  * value we return will fit in the range 1-255.
597                  */
598
599                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
600
601                 if(dptr->dnum == -1 || dptr->dnum > 254) {
602
603                         /*
604                          * Try and close the oldest handle not marked for
605                          * expect close in the hope that the client has
606                          * finished with that one.
607                          */
608
609                         dptr_close_oldest(sconn, true);
610
611                         /* Now try again... */
612                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
613                         if(dptr->dnum == -1 || dptr->dnum > 254) {
614                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
615                                 TALLOC_FREE(dptr);
616                                 TALLOC_FREE(dir_hnd);
617                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
618                         }
619                 }
620         } else {
621
622                 /*
623                  * This is a new-style trans2 request. Allocate from
624                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
625                  */
626
627                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
628
629                 if(dptr->dnum == -1 || dptr->dnum < 255) {
630
631                         /*
632                          * Try and close the oldest handle close in the hope that
633                          * the client has finished with that one. This will only
634                          * happen in the case of the Win98 client bug where it leaks
635                          * directory handles.
636                          */
637
638                         dptr_close_oldest(sconn, false);
639
640                         /* Now try again... */
641                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
642
643                         if(dptr->dnum == -1 || dptr->dnum < 255) {
644                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
645                                 TALLOC_FREE(dptr);
646                                 TALLOC_FREE(dir_hnd);
647                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
648                         }
649                 }
650         }
651
652         bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
653
654         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
655
656         DLIST_ADD(sconn->searches.dirptrs, dptr);
657
658 done:
659         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
660                 dptr->dnum,
661                 dptr->smb_dname->base_name,
662                 expect_close));
663
664         *dptr_ret = dptr;
665
666         return NT_STATUS_OK;
667 }
668
669
670 /****************************************************************************
671  Wrapper functions to access the lower level directory handles.
672 ****************************************************************************/
673
674 void dptr_CloseDir(files_struct *fsp)
675 {
676         if (fsp->dptr) {
677                 /*
678                  * The destructor for the struct smb_Dir
679                  * (fsp->dptr->dir_hnd) now handles
680                  * all resource deallocation.
681                  */
682                 dptr_close_internal(fsp->dptr);
683                 fsp->dptr = NULL;
684         }
685 }
686
687 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
688 {
689         SeekDir(dptr->dir_hnd, offset);
690 }
691
692 long dptr_TellDir(struct dptr_struct *dptr)
693 {
694         return TellDir(dptr->dir_hnd);
695 }
696
697 bool dptr_has_wild(struct dptr_struct *dptr)
698 {
699         return dptr->has_wild;
700 }
701
702 int dptr_dnum(struct dptr_struct *dptr)
703 {
704         return dptr->dnum;
705 }
706
707 bool dptr_get_priv(struct dptr_struct *dptr)
708 {
709         return dptr->priv;
710 }
711
712 void dptr_set_priv(struct dptr_struct *dptr)
713 {
714         dptr->priv = true;
715 }
716
717 /****************************************************************************
718  Return the next visible file name, skipping veto'd and invisible files.
719 ****************************************************************************/
720
721 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
722                                            long *poffset, SMB_STRUCT_STAT *pst,
723                                            char **ptalloced)
724 {
725         /* Normal search for the next file. */
726         const char *name;
727         char *talloced = NULL;
728
729         while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
730                != NULL) {
731                 if (is_visible_file(dptr->conn,
732                                 dptr->smb_dname->base_name,
733                                 name,
734                                 pst,
735                                 true)) {
736                         *ptalloced = talloced;
737                         return name;
738                 }
739                 TALLOC_FREE(talloced);
740         }
741         return NULL;
742 }
743
744 /****************************************************************************
745  Return the next visible file name, skipping veto'd and invisible files.
746 ****************************************************************************/
747
748 static char *dptr_ReadDirName(TALLOC_CTX *ctx,
749                               struct dptr_struct *dptr,
750                               long *poffset,
751                               SMB_STRUCT_STAT *pst)
752 {
753         struct smb_filename smb_fname_base;
754         char *name = NULL;
755         const char *name_temp = NULL;
756         char *talloced = NULL;
757         char *pathreal = NULL;
758         char *found_name = NULL;
759         int ret;
760
761         SET_STAT_INVALID(*pst);
762
763         if (dptr->has_wild || dptr->did_stat) {
764                 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
765                                                     &talloced);
766                 if (name_temp == NULL) {
767                         return NULL;
768                 }
769                 if (talloced != NULL) {
770                         return talloc_move(ctx, &talloced);
771                 }
772                 return talloc_strdup(ctx, name_temp);
773         }
774
775         /* If poffset is -1 then we know we returned this name before and we
776          * have no wildcards. We're at the end of the directory. */
777         if (*poffset == END_OF_DIRECTORY_OFFSET) {
778                 return NULL;
779         }
780
781         /* We know the stored wcard contains no wildcard characters.
782          * See if we can match with a stat call. If we can't, then set
783          * did_stat to true to ensure we only do this once and keep
784          * searching. */
785
786         dptr->did_stat = true;
787
788         /* First check if it should be visible. */
789         if (!is_visible_file(dptr->conn,
790                         dptr->smb_dname->base_name,
791                         dptr->wcard,
792                         pst,
793                         true)) {
794                 /* This only returns false if the file was found, but
795                    is explicitly not visible. Set us to end of
796                    directory, but return NULL as we know we can't ever
797                    find it. */
798                 goto ret;
799         }
800
801         if (VALID_STAT(*pst)) {
802                 name = talloc_strdup(ctx, dptr->wcard);
803                 goto ret;
804         }
805
806         pathreal = talloc_asprintf(ctx,
807                                 "%s/%s",
808                                 dptr->smb_dname->base_name,
809                                 dptr->wcard);
810         if (!pathreal)
811                 return NULL;
812
813         /* Create an smb_filename with stream_name == NULL. */
814         smb_fname_base = (struct smb_filename) { .base_name = pathreal };
815
816         if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
817                 *pst = smb_fname_base.st;
818                 name = talloc_strdup(ctx, dptr->wcard);
819                 goto clean;
820         } else {
821                 /* If we get any other error than ENOENT or ENOTDIR
822                    then the file exists we just can't stat it. */
823                 if (errno != ENOENT && errno != ENOTDIR) {
824                         name = talloc_strdup(ctx, dptr->wcard);
825                         goto clean;
826                 }
827         }
828
829         /* Stat failed. We know this is authoratiative if we are
830          * providing case sensitive semantics or the underlying
831          * filesystem is case sensitive.
832          */
833         if (dptr->conn->case_sensitive ||
834             !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
835         {
836                 goto clean;
837         }
838
839         /*
840          * Try case-insensitive stat if the fs has the ability. This avoids
841          * scanning the whole directory.
842          */
843         ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn,
844                                         dptr->smb_dname->base_name,
845                                         dptr->wcard,
846                                         ctx,
847                                         &found_name);
848         if (ret == 0) {
849                 name = found_name;
850                 goto clean;
851         } else if (errno == ENOENT) {
852                 /* The case-insensitive lookup was authoritative. */
853                 goto clean;
854         }
855
856         TALLOC_FREE(pathreal);
857
858         name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
859         if (name_temp == NULL) {
860                 return NULL;
861         }
862         if (talloced != NULL) {
863                 return talloc_move(ctx, &talloced);
864         }
865         return talloc_strdup(ctx, name_temp);
866
867 clean:
868         TALLOC_FREE(pathreal);
869 ret:
870         /* We need to set the underlying dir_hnd offset to -1
871          * also as this function is usually called with the
872          * output from TellDir. */
873         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
874         return name;
875 }
876
877 /****************************************************************************
878  Search for a file by name, skipping veto'ed and not visible files.
879 ****************************************************************************/
880
881 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
882 {
883         SET_STAT_INVALID(*pst);
884
885         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
886                 /* This is a singleton directory and we're already at the end. */
887                 *poffset = END_OF_DIRECTORY_OFFSET;
888                 return False;
889         }
890
891         return SearchDir(dptr->dir_hnd, name, poffset);
892 }
893
894 /****************************************************************************
895  Map a native directory offset to a 32-bit cookie.
896 ****************************************************************************/
897
898 static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
899 {
900         DATA_BLOB key;
901         DATA_BLOB val;
902
903         if (offset == END_OF_DIRECTORY_OFFSET) {
904                 return WIRE_END_OF_DIRECTORY_OFFSET;
905         } else if(offset == START_OF_DIRECTORY_OFFSET) {
906                 return WIRE_START_OF_DIRECTORY_OFFSET;
907         } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
908                 return WIRE_DOT_DOT_DIRECTORY_OFFSET;
909         }
910         if (sizeof(long) == 4) {
911                 /* 32-bit machine. We can cheat... */
912                 return (uint32_t)offset;
913         }
914         if (dptr->dptr_cache == NULL) {
915                 /* Lazy initialize cache. */
916                 dptr->dptr_cache = memcache_init(dptr, 0);
917                 if (dptr->dptr_cache == NULL) {
918                         return WIRE_END_OF_DIRECTORY_OFFSET;
919                 }
920         } else {
921                 /* Have we seen this offset before ? */
922                 key.data = (void *)&offset;
923                 key.length = sizeof(offset);
924                 if (memcache_lookup(dptr->dptr_cache,
925                                         SMB1_SEARCH_OFFSET_MAP,
926                                         key,
927                                         &val)) {
928                         uint32_t wire_offset;
929                         SMB_ASSERT(val.length == sizeof(wire_offset));
930                         memcpy(&wire_offset, val.data, sizeof(wire_offset));
931                         DEBUG(10,("found wire %u <-> offset %ld\n",
932                                 (unsigned int)wire_offset,
933                                 (long)offset));
934                         return wire_offset;
935                 }
936         }
937         /* Allocate a new wire cookie. */
938         do {
939                 dptr->counter++;
940         } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
941                  dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
942                  dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
943         /* Store it in the cache. */
944         key.data = (void *)&offset;
945         key.length = sizeof(offset);
946         val.data = (void *)&dptr->counter;
947         val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
948         memcache_add(dptr->dptr_cache,
949                         SMB1_SEARCH_OFFSET_MAP,
950                         key,
951                         val);
952         /* And the reverse mapping for lookup from
953            map_wire_to_dir_offset(). */
954         memcache_add(dptr->dptr_cache,
955                         SMB1_SEARCH_OFFSET_MAP,
956                         val,
957                         key);
958         DEBUG(10,("stored wire %u <-> offset %ld\n",
959                 (unsigned int)dptr->counter,
960                 (long)offset));
961         return dptr->counter;
962 }
963
964 /****************************************************************************
965  Fill the 5 byte server reserved dptr field.
966 ****************************************************************************/
967
968 bool dptr_fill(struct smbd_server_connection *sconn,
969                char *buf1,unsigned int key)
970 {
971         unsigned char *buf = (unsigned char *)buf1;
972         struct dptr_struct *dptr = dptr_get(sconn, key, false);
973         uint32_t wire_offset;
974         if (!dptr) {
975                 DEBUG(1,("filling null dirptr %d\n",key));
976                 return(False);
977         }
978         wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
979         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
980                 (long)dptr->dir_hnd,(int)wire_offset));
981         buf[0] = key;
982         SIVAL(buf,1,wire_offset);
983         return(True);
984 }
985
986 /****************************************************************************
987  Map a 32-bit wire cookie to a native directory offset.
988 ****************************************************************************/
989
990 static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t wire_offset)
991 {
992         DATA_BLOB key;
993         DATA_BLOB val;
994
995         if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
996                 return END_OF_DIRECTORY_OFFSET;
997         } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
998                 return START_OF_DIRECTORY_OFFSET;
999         } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
1000                 return DOT_DOT_DIRECTORY_OFFSET;
1001         }
1002         if (sizeof(long) == 4) {
1003                 /* 32-bit machine. We can cheat... */
1004                 return (long)wire_offset;
1005         }
1006         if (dptr->dptr_cache == NULL) {
1007                 /* Logic error, cache should be initialized. */
1008                 return END_OF_DIRECTORY_OFFSET;
1009         }
1010         key.data = (void *)&wire_offset;
1011         key.length = sizeof(wire_offset);
1012         if (memcache_lookup(dptr->dptr_cache,
1013                                 SMB1_SEARCH_OFFSET_MAP,
1014                                 key,
1015                                 &val)) {
1016                 /* Found mapping. */
1017                 long offset;
1018                 SMB_ASSERT(val.length == sizeof(offset));
1019                 memcpy(&offset, val.data, sizeof(offset));
1020                 DEBUG(10,("lookup wire %u <-> offset %ld\n",
1021                         (unsigned int)wire_offset,
1022                         (long)offset));
1023                 return offset;
1024         }
1025         return END_OF_DIRECTORY_OFFSET;
1026 }
1027
1028 /****************************************************************************
1029  Fetch the dir ptr and seek it given the 5 byte server field.
1030 ****************************************************************************/
1031
1032 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
1033                                char *buf, int *num)
1034 {
1035         unsigned int key = *(unsigned char *)buf;
1036         struct dptr_struct *dptr = dptr_get(sconn, key, false);
1037         uint32_t wire_offset;
1038         long seekoff;
1039
1040         if (!dptr) {
1041                 DEBUG(3,("fetched null dirptr %d\n",key));
1042                 return(NULL);
1043         }
1044         *num = key;
1045         wire_offset = IVAL(buf,1);
1046         seekoff = map_wire_to_dir_offset(dptr, wire_offset);
1047         SeekDir(dptr->dir_hnd,seekoff);
1048         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
1049                 key, dptr->smb_dname->base_name, (int)seekoff));
1050         return(dptr);
1051 }
1052
1053 /****************************************************************************
1054  Fetch the dir ptr.
1055 ****************************************************************************/
1056
1057 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
1058                                        int dptr_num)
1059 {
1060         struct dptr_struct *dptr  = dptr_get(sconn, dptr_num, false);
1061
1062         if (!dptr) {
1063                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
1064                 return(NULL);
1065         }
1066         DEBUG(3,("fetching dirptr %d for path %s\n",
1067                 dptr_num,
1068                 dptr->smb_dname->base_name));
1069         return(dptr);
1070 }
1071
1072 static bool mangle_mask_match(connection_struct *conn,
1073                 const char *filename,
1074                 const char *mask)
1075 {
1076         char mname[13];
1077
1078         if (!name_to_8_3(filename,mname,False,conn->params)) {
1079                 return False;
1080         }
1081         return mask_match_search(mname,mask,False);
1082 }
1083
1084 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
1085                            struct dptr_struct *dirptr,
1086                            const char *mask,
1087                            uint32_t dirtype,
1088                            bool dont_descend,
1089                            bool ask_sharemode,
1090                            bool get_dosmode,
1091                            bool (*match_fn)(TALLOC_CTX *ctx,
1092                                             void *private_data,
1093                                             const char *dname,
1094                                             const char *mask,
1095                                             char **_fname),
1096                            bool (*mode_fn)(TALLOC_CTX *ctx,
1097                                            void *private_data,
1098                                            struct smb_filename *smb_fname,
1099                                            bool get_dosmode,
1100                                            uint32_t *_mode),
1101                            void *private_data,
1102                            char **_fname,
1103                            struct smb_filename **_smb_fname,
1104                            uint32_t *_mode,
1105                            long *_prev_offset)
1106 {
1107         connection_struct *conn = dirptr->conn;
1108         size_t slashlen;
1109         size_t pathlen;
1110         const char *dpath = dirptr->smb_dname->base_name;
1111         bool dirptr_path_is_dot = ISDOT(dpath);
1112
1113         *_smb_fname = NULL;
1114         *_mode = 0;
1115
1116         pathlen = strlen(dpath);
1117         slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
1118
1119         while (true) {
1120                 long cur_offset;
1121                 long prev_offset;
1122                 SMB_STRUCT_STAT sbuf = { 0 };
1123                 char *dname = NULL;
1124                 bool isdots;
1125                 char *fname = NULL;
1126                 char *pathreal = NULL;
1127                 struct smb_filename smb_fname;
1128                 uint32_t mode = 0;
1129                 bool ok;
1130
1131                 cur_offset = dptr_TellDir(dirptr);
1132                 prev_offset = cur_offset;
1133                 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
1134
1135                 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
1136                         (long)dirptr, cur_offset));
1137
1138                 if (dname == NULL) {
1139                         return false;
1140                 }
1141
1142                 isdots = (ISDOT(dname) || ISDOTDOT(dname));
1143                 if (dont_descend && !isdots) {
1144                         TALLOC_FREE(dname);
1145                         continue;
1146                 }
1147
1148                 /*
1149                  * fname may get mangled, dname is never mangled.
1150                  * Whenever we're accessing the filesystem we use
1151                  * pathreal which is composed from dname.
1152                  */
1153
1154                 ok = match_fn(ctx, private_data, dname, mask, &fname);
1155                 if (!ok) {
1156                         TALLOC_FREE(dname);
1157                         continue;
1158                 }
1159
1160                 /*
1161                  * This used to be
1162                  * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
1163                  *                            needslash?"/":"", dname);
1164                  * but this was measurably slower than doing the memcpy.
1165                  */
1166
1167                 pathreal = talloc_array(
1168                         ctx, char,
1169                         pathlen + slashlen + talloc_get_size(dname));
1170                 if (!pathreal) {
1171                         TALLOC_FREE(dname);
1172                         TALLOC_FREE(fname);
1173                         return false;
1174                 }
1175
1176                 /*
1177                  * We don't want to pass ./xxx to modules below us so don't
1178                  * add the path if it is just . by itself.
1179                  */
1180                 if (dirptr_path_is_dot) {
1181                         memcpy(pathreal, dname, talloc_get_size(dname));
1182                 } else {
1183                         memcpy(pathreal, dpath, pathlen);
1184                         pathreal[pathlen] = '/';
1185                         memcpy(pathreal + slashlen + pathlen, dname,
1186                                talloc_get_size(dname));
1187                 }
1188
1189                 /* Create smb_fname with NULL stream_name. */
1190                 smb_fname = (struct smb_filename) {
1191                         .base_name = pathreal, .st = sbuf
1192                 };
1193
1194                 ok = mode_fn(ctx, private_data, &smb_fname, get_dosmode, &mode);
1195                 if (!ok) {
1196                         TALLOC_FREE(dname);
1197                         TALLOC_FREE(fname);
1198                         TALLOC_FREE(pathreal);
1199                         continue;
1200                 }
1201
1202                 if (!dir_check_ftype(mode, dirtype)) {
1203                         DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1204                                 fname, (unsigned int)mode, (unsigned int)dirtype));
1205                         TALLOC_FREE(dname);
1206                         TALLOC_FREE(fname);
1207                         TALLOC_FREE(pathreal);
1208                         continue;
1209                 }
1210
1211                 if (ask_sharemode) {
1212                         struct timespec write_time_ts;
1213                         struct file_id fileid;
1214
1215                         fileid = vfs_file_id_from_sbuf(conn,
1216                                                        &smb_fname.st);
1217                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1218                         if (!null_timespec(write_time_ts)) {
1219                                 update_stat_ex_mtime(&smb_fname.st,
1220                                                      write_time_ts);
1221                         }
1222                 }
1223
1224                 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1225                         "fname=%s (%s)\n",
1226                         mask, smb_fname_str_dbg(&smb_fname),
1227                         dname, fname));
1228
1229                 if (!conn->sconn->using_smb2) {
1230                         /*
1231                          * The dircache is only needed for SMB1 because SMB1
1232                          * uses a name for the resume wheras SMB2 always
1233                          * continues from the next position (unless it's told to
1234                          * restart or close-and-reopen the listing).
1235                          */
1236                         DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1237                 }
1238
1239                 TALLOC_FREE(dname);
1240
1241                 *_smb_fname = cp_smb_filename(ctx, &smb_fname);
1242                 TALLOC_FREE(pathreal);
1243                 if (*_smb_fname == NULL) {
1244                         return false;
1245                 }
1246                 *_fname = fname;
1247                 *_mode = mode;
1248                 *_prev_offset = prev_offset;
1249
1250                 return true;
1251         }
1252
1253         return false;
1254 }
1255
1256 /****************************************************************************
1257  Get an 8.3 directory entry.
1258 ****************************************************************************/
1259
1260 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1261                                      void *private_data,
1262                                      const char *dname,
1263                                      const char *mask,
1264                                      char **_fname)
1265 {
1266         connection_struct *conn = (connection_struct *)private_data;
1267
1268         if ((strcmp(mask,"*.*") == 0) ||
1269             mask_match_search(dname, mask, false) ||
1270             mangle_mask_match(conn, dname, mask)) {
1271                 char mname[13];
1272                 const char *fname;
1273                 /*
1274                  * Ensure we can push the original name as UCS2. If
1275                  * not, then just don't return this name.
1276                  */
1277                 NTSTATUS status;
1278                 size_t ret_len = 0;
1279                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1280                 uint8_t *tmp = talloc_array(talloc_tos(),
1281                                         uint8_t,
1282                                         len);
1283
1284                 status = srvstr_push(NULL,
1285                         FLAGS2_UNICODE_STRINGS,
1286                         tmp,
1287                         dname,
1288                         len,
1289                         STR_TERMINATE,
1290                         &ret_len);
1291
1292                 TALLOC_FREE(tmp);
1293
1294                 if (!NT_STATUS_IS_OK(status)) {
1295                         return false;
1296                 }
1297
1298                 if (!mangle_is_8_3(dname, false, conn->params)) {
1299                         bool ok = name_to_8_3(dname, mname, false,
1300                                               conn->params);
1301                         if (!ok) {
1302                                 return false;
1303                         }
1304                         fname = mname;
1305                 } else {
1306                         fname = dname;
1307                 }
1308
1309                 *_fname = talloc_strdup(ctx, fname);
1310                 if (*_fname == NULL) {
1311                         return false;
1312                 }
1313
1314                 return true;
1315         }
1316
1317         return false;
1318 }
1319
1320 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1321                                     void *private_data,
1322                                     struct smb_filename *smb_fname,
1323                                     bool get_dosmode,
1324                                     uint32_t *_mode)
1325 {
1326         connection_struct *conn = (connection_struct *)private_data;
1327
1328         if (!VALID_STAT(smb_fname->st)) {
1329                 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1330                         DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1331                                  "Couldn't stat [%s]. Error "
1332                                  "= %s\n",
1333                                  smb_fname_str_dbg(smb_fname),
1334                                  strerror(errno)));
1335                         return false;
1336                 }
1337         }
1338
1339         *_mode = dos_mode(conn, smb_fname);
1340         return true;
1341 }
1342
1343 bool get_dir_entry(TALLOC_CTX *ctx,
1344                 struct dptr_struct *dirptr,
1345                 const char *mask,
1346                 uint32_t dirtype,
1347                 char **_fname,
1348                 off_t *_size,
1349                 uint32_t *_mode,
1350                 struct timespec *_date,
1351                 bool check_descend,
1352                 bool ask_sharemode)
1353 {
1354         connection_struct *conn = dirptr->conn;
1355         char *fname = NULL;
1356         struct smb_filename *smb_fname = NULL;
1357         uint32_t mode = 0;
1358         long prev_offset;
1359         bool ok;
1360
1361         ok = smbd_dirptr_get_entry(ctx,
1362                                    dirptr,
1363                                    mask,
1364                                    dirtype,
1365                                    check_descend,
1366                                    ask_sharemode,
1367                                    true,
1368                                    smbd_dirptr_8_3_match_fn,
1369                                    smbd_dirptr_8_3_mode_fn,
1370                                    conn,
1371                                    &fname,
1372                                    &smb_fname,
1373                                    &mode,
1374                                    &prev_offset);
1375         if (!ok) {
1376                 return false;
1377         }
1378
1379         *_fname = talloc_move(ctx, &fname);
1380         *_size = smb_fname->st.st_ex_size;
1381         *_mode = mode;
1382         *_date = smb_fname->st.st_ex_mtime;
1383         TALLOC_FREE(smb_fname);
1384         return true;
1385 }
1386
1387 /*******************************************************************
1388  Check to see if a user can read a file. This is only approximate,
1389  it is used as part of the "hide unreadable" option. Don't
1390  use it for anything security sensitive.
1391 ********************************************************************/
1392
1393 static bool user_can_read_file(connection_struct *conn,
1394                                struct smb_filename *smb_fname)
1395 {
1396         NTSTATUS status;
1397         uint32_t rejected_share_access = 0;
1398         uint32_t rejected_mask = 0;
1399         struct security_descriptor *sd = NULL;
1400         uint32_t access_mask = FILE_READ_DATA|
1401                                 FILE_READ_EA|
1402                                 FILE_READ_ATTRIBUTES|
1403                                 SEC_STD_READ_CONTROL;
1404
1405         /*
1406          * Never hide files from the root user.
1407          * We use (uid_t)0 here not sec_initial_uid()
1408          * as make test uses a single user context.
1409          */
1410
1411         if (get_current_uid(conn) == (uid_t)0) {
1412                 return True;
1413         }
1414
1415         /*
1416          * We can't directly use smbd_check_access_rights()
1417          * here, as this implicitly grants FILE_READ_ATTRIBUTES
1418          * which the Windows access-based-enumeration code
1419          * explicitly checks for on the file security descriptor.
1420          * See bug:
1421          *
1422          * https://bugzilla.samba.org/show_bug.cgi?id=10252
1423          *
1424          * and the smb2.acl2.ACCESSBASED test for details.
1425          */
1426
1427         rejected_share_access = access_mask & ~(conn->share_access);
1428         if (rejected_share_access) {
1429                 DEBUG(10, ("rejected share access 0x%x "
1430                         "on %s (0x%x)\n",
1431                         (unsigned int)access_mask,
1432                         smb_fname_str_dbg(smb_fname),
1433                         (unsigned int)rejected_share_access ));
1434                 return false;
1435         }
1436
1437         status = SMB_VFS_GET_NT_ACL(conn,
1438                         smb_fname,
1439                         (SECINFO_OWNER |
1440                          SECINFO_GROUP |
1441                          SECINFO_DACL),
1442                         talloc_tos(),
1443                         &sd);
1444
1445         if (!NT_STATUS_IS_OK(status)) {
1446                 DEBUG(10, ("Could not get acl "
1447                         "on %s: %s\n",
1448                         smb_fname_str_dbg(smb_fname),
1449                         nt_errstr(status)));
1450                 return false;
1451         }
1452
1453         status = se_file_access_check(sd,
1454                                 get_current_nttok(conn),
1455                                 false,
1456                                 access_mask,
1457                                 &rejected_mask);
1458
1459         TALLOC_FREE(sd);
1460
1461         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1462                 DEBUG(10,("rejected bits 0x%x read access for %s\n",
1463                         (unsigned int)rejected_mask,
1464                         smb_fname_str_dbg(smb_fname) ));
1465                 return false;
1466         }
1467         return true;
1468 }
1469
1470 /*******************************************************************
1471  Check to see if a user can write a file (and only files, we do not
1472  check dirs on this one). This is only approximate,
1473  it is used as part of the "hide unwriteable" option. Don't
1474  use it for anything security sensitive.
1475 ********************************************************************/
1476
1477 static bool user_can_write_file(connection_struct *conn,
1478                                 const struct smb_filename *smb_fname)
1479 {
1480         /*
1481          * Never hide files from the root user.
1482          * We use (uid_t)0 here not sec_initial_uid()
1483          * as make test uses a single user context.
1484          */
1485
1486         if (get_current_uid(conn) == (uid_t)0) {
1487                 return True;
1488         }
1489
1490         SMB_ASSERT(VALID_STAT(smb_fname->st));
1491
1492         /* Pseudo-open the file */
1493
1494         if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1495                 return True;
1496         }
1497
1498         return can_write_to_file(conn, smb_fname);
1499 }
1500
1501 /*******************************************************************
1502   Is a file a "special" type ?
1503 ********************************************************************/
1504
1505 static bool file_is_special(connection_struct *conn,
1506                             const struct smb_filename *smb_fname)
1507 {
1508         /*
1509          * Never hide files from the root user.
1510          * We use (uid_t)0 here not sec_initial_uid()
1511          * as make test uses a single user context.
1512          */
1513
1514         if (get_current_uid(conn) == (uid_t)0) {
1515                 return False;
1516         }
1517
1518         SMB_ASSERT(VALID_STAT(smb_fname->st));
1519
1520         if (S_ISREG(smb_fname->st.st_ex_mode) ||
1521             S_ISDIR(smb_fname->st.st_ex_mode) ||
1522             S_ISLNK(smb_fname->st.st_ex_mode))
1523                 return False;
1524
1525         return True;
1526 }
1527
1528 /*******************************************************************
1529  Should the file be seen by the client?
1530  NOTE: A successful return is no guarantee of the file's existence.
1531 ********************************************************************/
1532
1533 bool is_visible_file(connection_struct *conn, const char *dir_path,
1534                      const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1535 {
1536         bool hide_unreadable = lp_hide_unreadable(SNUM(conn));
1537         bool hide_unwriteable = lp_hide_unwriteable_files(SNUM(conn));
1538         bool hide_special = lp_hide_special_files(SNUM(conn));
1539         int hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(conn));
1540         char *entry = NULL;
1541         struct smb_filename *smb_fname_base = NULL;
1542         bool ret = false;
1543
1544         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1545                 return True; /* . and .. are always visible. */
1546         }
1547
1548         /* If it's a vetoed file, pretend it doesn't even exist */
1549         if (use_veto && IS_VETO_PATH(conn, name)) {
1550                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1551                 return False;
1552         }
1553
1554         if (hide_unreadable ||
1555             hide_unwriteable ||
1556             hide_special ||
1557             (hide_new_files_timeout != 0))
1558         {
1559                 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1560                 if (!entry) {
1561                         ret = false;
1562                         goto out;
1563                 }
1564
1565                 /* Create an smb_filename with stream_name == NULL. */
1566                 smb_fname_base = synthetic_smb_fname(talloc_tos(),
1567                                                 entry,
1568                                                 NULL,
1569                                                 pst,
1570                                                 0);
1571                 if (smb_fname_base == NULL) {
1572                         ret = false;
1573                         goto out;
1574                 }
1575
1576                 /* If the file name does not exist, there's no point checking
1577                  * the configuration options. We succeed, on the basis that the
1578                  * checks *might* have passed if the file was present.
1579                  */
1580                 if (!VALID_STAT(*pst)) {
1581                         if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1582                                 ret = true;
1583                                 goto out;
1584                         }
1585                         *pst = smb_fname_base->st;
1586                 }
1587
1588                 /* Honour _hide unreadable_ option */
1589                 if (hide_unreadable &&
1590                     !user_can_read_file(conn, smb_fname_base)) {
1591                         DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1592                                  entry ));
1593                         ret = false;
1594                         goto out;
1595                 }
1596                 /* Honour _hide unwriteable_ option */
1597                 if (hide_unwriteable && !user_can_write_file(conn,
1598                                                              smb_fname_base)) {
1599                         DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1600                                  entry ));
1601                         ret = false;
1602                         goto out;
1603                 }
1604                 /* Honour _hide_special_ option */
1605                 if (hide_special && file_is_special(conn, smb_fname_base)) {
1606                         DEBUG(10,("is_visible_file: file %s is special.\n",
1607                                  entry ));
1608                         ret = false;
1609                         goto out;
1610                 }
1611
1612                 if (hide_new_files_timeout != 0) {
1613
1614                         double age = timespec_elapsed(
1615                                 &smb_fname_base->st.st_ex_mtime);
1616
1617                         if (age < (double)hide_new_files_timeout) {
1618                                 ret = false;
1619                                 goto out;
1620                         }
1621                 }
1622         }
1623
1624         ret = true;
1625  out:
1626         TALLOC_FREE(smb_fname_base);
1627         TALLOC_FREE(entry);
1628         return ret;
1629 }
1630
1631 static int smb_Dir_destructor(struct smb_Dir *dirp)
1632 {
1633         if (dirp->dir != NULL) {
1634                 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1635                 if (dirp->fsp != NULL) {
1636                         /*
1637                          * The SMB_VFS_CLOSEDIR above
1638                          * closes the underlying fd inside
1639                          * dirp->fsp.
1640                          */
1641                         dirp->fsp->fh->fd = -1;
1642                         if (dirp->fsp->dptr != NULL) {
1643                                 SMB_ASSERT(dirp->fsp->dptr->dir_hnd == dirp);
1644                                 dirp->fsp->dptr->dir_hnd = NULL;
1645                         }
1646                         dirp->fsp = NULL;
1647                 }
1648         }
1649         if (dirp->conn->sconn && !dirp->conn->sconn->using_smb2) {
1650                 dirp->conn->sconn->searches.dirhandles_open--;
1651         }
1652         return 0;
1653 }
1654
1655 /*******************************************************************
1656  Open a directory.
1657 ********************************************************************/
1658
1659 static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
1660                         connection_struct *conn,
1661                         const struct smb_filename *smb_dname,
1662                         const char *mask,
1663                         uint32_t attr)
1664 {
1665         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1666         struct smbd_server_connection *sconn = conn->sconn;
1667
1668         if (!dirp) {
1669                 return NULL;
1670         }
1671
1672         dirp->dir = SMB_VFS_OPENDIR(conn, smb_dname, mask, attr);
1673
1674         if (!dirp->dir) {
1675                 DEBUG(5,("OpenDir: Can't open %s. %s\n",
1676                         smb_dname->base_name,
1677                         strerror(errno) ));
1678                 goto fail;
1679         }
1680
1681         dirp->conn = conn;
1682
1683         if (!conn->sconn->using_smb2) {
1684                 /*
1685                  * The dircache is only needed for SMB1 because SMB1 uses a name
1686                  * for the resume wheras SMB2 always continues from the next
1687                  * position (unless it's told to restart or close-and-reopen the
1688                  * listing).
1689                  */
1690                 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1691         }
1692
1693         if (sconn && !sconn->using_smb2) {
1694                 sconn->searches.dirhandles_open++;
1695         }
1696         talloc_set_destructor(dirp, smb_Dir_destructor);
1697
1698         return dirp;
1699
1700   fail:
1701         TALLOC_FREE(dirp);
1702         return NULL;
1703 }
1704
1705 /****************************************************************************
1706  Open a directory handle by pathname, ensuring it's under the share path.
1707 ****************************************************************************/
1708
1709 static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
1710                                         connection_struct *conn,
1711                                         const struct smb_filename *smb_dname,
1712                                         const char *wcard,
1713                                         uint32_t attr)
1714 {
1715         struct smb_Dir *dir_hnd = NULL;
1716         struct smb_filename *smb_fname_cwd = NULL;
1717         struct smb_filename *saved_dir_fname = vfs_GetWd(ctx, conn);
1718         NTSTATUS status;
1719
1720         if (saved_dir_fname == NULL) {
1721                 return NULL;
1722         }
1723
1724         if (vfs_ChDir(conn, smb_dname) == -1) {
1725                 goto out;
1726         }
1727
1728         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1729                                         ".",
1730                                         NULL,
1731                                         NULL,
1732                                         smb_dname->flags);
1733         if (smb_fname_cwd == NULL) {
1734                 goto out;
1735         }
1736
1737         /*
1738          * Now the directory is pinned, use
1739          * REALPATH to ensure we can access it.
1740          */
1741         status = check_name(conn, smb_fname_cwd);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 goto out;
1744         }
1745
1746         dir_hnd = OpenDir_internal(ctx,
1747                                 conn,
1748                                 smb_fname_cwd,
1749                                 wcard,
1750                                 attr);
1751
1752         if (dir_hnd == NULL) {
1753                 goto out;
1754         }
1755
1756         /*
1757          * OpenDir_internal only gets "." as the dir name.
1758          * Store the real dir name here.
1759          */
1760
1761         dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, smb_dname);
1762         if (!dir_hnd->dir_smb_fname) {
1763                 TALLOC_FREE(dir_hnd);
1764                 errno = ENOMEM;
1765         }
1766
1767   out:
1768
1769         vfs_ChDir(conn, saved_dir_fname);
1770         TALLOC_FREE(saved_dir_fname);
1771         return dir_hnd;
1772 }
1773
1774 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1775                         const struct smb_filename *smb_dname,
1776                         const char *mask,
1777                         uint32_t attr)
1778 {
1779         return open_dir_safely(mem_ctx,
1780                                 conn,
1781                                 smb_dname,
1782                                 mask,
1783                                 attr);
1784 }
1785
1786 /*******************************************************************
1787  Open a directory from an fsp.
1788 ********************************************************************/
1789
1790 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1791                         files_struct *fsp,
1792                         const char *mask,
1793                         uint32_t attr)
1794 {
1795         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1796         struct smbd_server_connection *sconn = conn->sconn;
1797
1798         if (!dirp) {
1799                 goto fail;
1800         }
1801
1802         if (!fsp->is_directory) {
1803                 errno = EBADF;
1804                 goto fail;
1805         }
1806
1807         if (fsp->fh->fd == -1) {
1808                 errno = EBADF;
1809                 goto fail;
1810         }
1811
1812         dirp->conn = conn;
1813
1814         if (!conn->sconn->using_smb2) {
1815                 /*
1816                  * The dircache is only needed for SMB1 because SMB1 uses a name
1817                  * for the resume wheras SMB2 always continues from the next
1818                  * position (unless it's told to restart or close-and-reopen the
1819                  * listing).
1820                  */
1821                 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1822         }
1823
1824         dirp->dir_smb_fname = cp_smb_filename(dirp, fsp->fsp_name);
1825         if (!dirp->dir_smb_fname) {
1826                 errno = ENOMEM;
1827                 goto fail;
1828         }
1829
1830         dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1831         if (dirp->dir != NULL) {
1832                 dirp->fsp = fsp;
1833         } else {
1834                 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1835                         "NULL (%s)\n",
1836                         dirp->dir_smb_fname->base_name,
1837                         strerror(errno)));
1838                 if (errno != ENOSYS) {
1839                         goto fail;
1840                 }
1841         }
1842
1843         if (dirp->dir == NULL) {
1844                 /* FDOPENDIR is not supported. Use OPENDIR instead. */
1845                 TALLOC_FREE(dirp);
1846                 return open_dir_safely(mem_ctx,
1847                                         conn,
1848                                         fsp->fsp_name,
1849                                         mask,
1850                                         attr);
1851         }
1852
1853         if (sconn && !sconn->using_smb2) {
1854                 sconn->searches.dirhandles_open++;
1855         }
1856         talloc_set_destructor(dirp, smb_Dir_destructor);
1857
1858         return dirp;
1859
1860   fail:
1861         TALLOC_FREE(dirp);
1862         return NULL;
1863 }
1864
1865
1866 /*******************************************************************
1867  Read from a directory.
1868  Return directory entry, current offset, and optional stat information.
1869  Don't check for veto or invisible files.
1870 ********************************************************************/
1871
1872 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1873                         SMB_STRUCT_STAT *sbuf, char **ptalloced)
1874 {
1875         const char *n;
1876         char *talloced = NULL;
1877         connection_struct *conn = dirp->conn;
1878
1879         /* Cheat to allow . and .. to be the first entries returned. */
1880         if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1881              (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1882         {
1883                 if (dirp->file_number == 0) {
1884                         n = ".";
1885                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1886                 } else {
1887                         n = "..";
1888                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1889                 }
1890                 dirp->file_number++;
1891                 *ptalloced = NULL;
1892                 return n;
1893         }
1894
1895         if (*poffset == END_OF_DIRECTORY_OFFSET) {
1896                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1897                 return NULL;
1898         }
1899
1900         /* A real offset, seek to it. */
1901         SeekDir(dirp, *poffset);
1902
1903         while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1904                 /* Ignore . and .. - we've already returned them. */
1905                 if (*n == '.') {
1906                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1907                                 TALLOC_FREE(talloced);
1908                                 continue;
1909                         }
1910                 }
1911                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1912                 *ptalloced = talloced;
1913                 dirp->file_number++;
1914                 return n;
1915         }
1916         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1917         *ptalloced = NULL;
1918         return NULL;
1919 }
1920
1921 /*******************************************************************
1922  Rewind to the start.
1923 ********************************************************************/
1924
1925 void RewindDir(struct smb_Dir *dirp, long *poffset)
1926 {
1927         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1928         dirp->file_number = 0;
1929         dirp->offset = START_OF_DIRECTORY_OFFSET;
1930         *poffset = START_OF_DIRECTORY_OFFSET;
1931 }
1932
1933 /*******************************************************************
1934  Seek a dir.
1935 ********************************************************************/
1936
1937 void SeekDir(struct smb_Dir *dirp, long offset)
1938 {
1939         if (offset != dirp->offset) {
1940                 if (offset == START_OF_DIRECTORY_OFFSET) {
1941                         RewindDir(dirp, &offset);
1942                         /*
1943                          * Ok we should really set the file number here
1944                          * to 1 to enable ".." to be returned next. Trouble
1945                          * is I'm worried about callers using SeekDir(dirp,0)
1946                          * as equivalent to RewindDir(). So leave this alone
1947                          * for now.
1948                          */
1949                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1950                         RewindDir(dirp, &offset);
1951                         /*
1952                          * Set the file number to 2 - we want to get the first
1953                          * real file entry (the one we return after "..")
1954                          * on the next ReadDir.
1955                          */
1956                         dirp->file_number = 2;
1957                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1958                         ; /* Don't seek in this case. */
1959                 } else {
1960                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1961                 }
1962                 dirp->offset = offset;
1963         }
1964 }
1965
1966 /*******************************************************************
1967  Tell a dir position.
1968 ********************************************************************/
1969
1970 long TellDir(struct smb_Dir *dirp)
1971 {
1972         return(dirp->offset);
1973 }
1974
1975 /*******************************************************************
1976  Add an entry into the dcache.
1977 ********************************************************************/
1978
1979 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1980 {
1981         struct name_cache_entry *e;
1982
1983         if (dirp->name_cache_size == 0) {
1984                 return;
1985         }
1986
1987         if (dirp->name_cache == NULL) {
1988                 dirp->name_cache = talloc_zero_array(
1989                         dirp, struct name_cache_entry, dirp->name_cache_size);
1990
1991                 if (dirp->name_cache == NULL) {
1992                         return;
1993                 }
1994         }
1995
1996         dirp->name_cache_index = (dirp->name_cache_index+1) %
1997                                         dirp->name_cache_size;
1998         e = &dirp->name_cache[dirp->name_cache_index];
1999         TALLOC_FREE(e->name);
2000         e->name = talloc_strdup(dirp, name);
2001         e->offset = offset;
2002 }
2003
2004 /*******************************************************************
2005  Find an entry by name. Leave us at the offset after it.
2006  Don't check for veto or invisible files.
2007 ********************************************************************/
2008
2009 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
2010 {
2011         int i;
2012         const char *entry = NULL;
2013         char *talloced = NULL;
2014         connection_struct *conn = dirp->conn;
2015
2016         /* Search back in the name cache. */
2017         if (dirp->name_cache_size && dirp->name_cache) {
2018                 for (i = dirp->name_cache_index; i >= 0; i--) {
2019                         struct name_cache_entry *e = &dirp->name_cache[i];
2020                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
2021                                 *poffset = e->offset;
2022                                 SeekDir(dirp, e->offset);
2023                                 return True;
2024                         }
2025                 }
2026                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
2027                         struct name_cache_entry *e = &dirp->name_cache[i];
2028                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
2029                                 *poffset = e->offset;
2030                                 SeekDir(dirp, e->offset);
2031                                 return True;
2032                         }
2033                 }
2034         }
2035
2036         /* Not found in the name cache. Rewind directory and start from scratch. */
2037         SMB_VFS_REWINDDIR(conn, dirp->dir);
2038         dirp->file_number = 0;
2039         *poffset = START_OF_DIRECTORY_OFFSET;
2040         while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
2041                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
2042                         TALLOC_FREE(talloced);
2043                         return True;
2044                 }
2045                 TALLOC_FREE(talloced);
2046         }
2047         return False;
2048 }
2049
2050 struct files_below_forall_state {
2051         char *dirpath;
2052         size_t dirpath_len;
2053         int (*fn)(struct file_id fid, const struct share_mode_data *data,
2054                   void *private_data);
2055         void *private_data;
2056 };
2057
2058 static int files_below_forall_fn(struct file_id fid,
2059                                  const struct share_mode_data *data,
2060                                  void *private_data)
2061 {
2062         struct files_below_forall_state *state = private_data;
2063         char tmpbuf[PATH_MAX];
2064         char *fullpath, *to_free;
2065         size_t len;
2066
2067         len = full_path_tos(data->servicepath, data->base_name,
2068                             tmpbuf, sizeof(tmpbuf),
2069                             &fullpath, &to_free);
2070         if (len == -1) {
2071                 return 0;
2072         }
2073         if (state->dirpath_len >= len) {
2074                 /*
2075                  * Filter files above dirpath
2076                  */
2077                 goto out;
2078         }
2079         if (fullpath[state->dirpath_len] != '/') {
2080                 /*
2081                  * Filter file that don't have a path separator at the end of
2082                  * dirpath's length
2083                  */
2084                 goto out;
2085         }
2086
2087         if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
2088                 /*
2089                  * Not a parent
2090                  */
2091                 goto out;
2092         }
2093
2094         TALLOC_FREE(to_free);
2095         return state->fn(fid, data, state->private_data);
2096
2097 out:
2098         TALLOC_FREE(to_free);
2099         return 0;
2100 }
2101
2102 static int files_below_forall(connection_struct *conn,
2103                               const struct smb_filename *dir_name,
2104                               int (*fn)(struct file_id fid,
2105                                         const struct share_mode_data *data,
2106                                         void *private_data),
2107                               void *private_data)
2108 {
2109         struct files_below_forall_state state = {
2110                         .fn = fn,
2111                         .private_data = private_data,
2112         };
2113         int ret;
2114         char tmpbuf[PATH_MAX];
2115         char *to_free;
2116
2117         state.dirpath_len = full_path_tos(conn->connectpath,
2118                                           dir_name->base_name,
2119                                           tmpbuf, sizeof(tmpbuf),
2120                                           &state.dirpath, &to_free);
2121         if (state.dirpath_len == -1) {
2122                 return -1;
2123         }
2124
2125         ret = share_mode_forall(files_below_forall_fn, &state);
2126         TALLOC_FREE(to_free);
2127         return ret;
2128 }
2129
2130 struct have_file_open_below_state {
2131         bool found_one;
2132 };
2133
2134 static int have_file_open_below_fn(struct file_id fid,
2135                                    const struct share_mode_data *data,
2136                                    void *private_data)
2137 {
2138         struct have_file_open_below_state *state = private_data;
2139         state->found_one = true;
2140         return 1;
2141 }
2142
2143 bool have_file_open_below(connection_struct *conn,
2144                                  const struct smb_filename *name)
2145 {
2146         struct have_file_open_below_state state = {
2147                 .found_one = false,
2148         };
2149         int ret;
2150
2151         if (!VALID_STAT(name->st)) {
2152                 return false;
2153         }
2154         if (!S_ISDIR(name->st.st_ex_mode)) {
2155                 return false;
2156         }
2157
2158         ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
2159         if (ret == -1) {
2160                 return false;
2161         }
2162
2163         return state.found_one;
2164 }
2165
2166 /*****************************************************************
2167  Is this directory empty ?
2168 *****************************************************************/
2169
2170 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
2171 {
2172         NTSTATUS status = NT_STATUS_OK;
2173         long dirpos = 0;
2174         const char *dname = NULL;
2175         const char *dirname = fsp->fsp_name->base_name;
2176         char *talloced = NULL;
2177         SMB_STRUCT_STAT st;
2178         struct connection_struct *conn = fsp->conn;
2179         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(),
2180                                         conn,
2181                                         fsp->fsp_name,
2182                                         NULL,
2183                                         0);
2184
2185         if (!dir_hnd) {
2186                 return map_nt_error_from_unix(errno);
2187         }
2188
2189         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
2190                 /* Quick check for "." and ".." */
2191                 if (dname[0] == '.') {
2192                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
2193                                 TALLOC_FREE(talloced);
2194                                 continue;
2195                         }
2196                 }
2197
2198                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
2199                         TALLOC_FREE(talloced);
2200                         continue;
2201                 }
2202
2203                 DEBUG(10,("got name %s - can't delete\n",
2204                          dname ));
2205                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
2206                 break;
2207         }
2208         TALLOC_FREE(talloced);
2209         TALLOC_FREE(dir_hnd);
2210
2211         if (!NT_STATUS_IS_OK(status)) {
2212                 return status;
2213         }
2214
2215         if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
2216             lp_strict_rename(SNUM(conn)) &&
2217             have_file_open_below(fsp->conn, fsp->fsp_name))
2218         {
2219                 return NT_STATUS_ACCESS_DENIED;
2220         }
2221
2222         return NT_STATUS_OK;
2223 }