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