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