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