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