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