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