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