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