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