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