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