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