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