smbd: Save a few lines in smbXsrv_client_global_init()
[samba.git] / source3 / smbd / filename.c
1 /*
2    Unix SMB/CIFS implementation.
3    filename handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1999-2007
6    Copyright (C) Ying Chen 2000
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  * New hash table stat cache code added by Ying Chen.
25  */
26
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "fake_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "libcli/smb/reparse.h"
33 #include "source3/smbd/dir.h"
34
35 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
36 {
37         uint32_t ucf_flags = 0;
38
39         if (req == NULL) {
40                 return 0;
41         }
42
43         if (req->posix_pathnames) {
44                 ucf_flags |= UCF_POSIX_PATHNAMES;
45
46                 if (!conn_using_smb2(req->sconn)) {
47                         ucf_flags |= UCF_LCOMP_LNK_OK;
48                 }
49         }
50         if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
51                 ucf_flags |= UCF_DFS_PATHNAME;
52         }
53         if (req->flags2 & FLAGS2_REPARSE_PATH) {
54                 ucf_flags |= UCF_GMT_PATHNAME;
55         }
56
57         return ucf_flags;
58 }
59
60 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
61 {
62         uint32_t ucf_flags = 0;
63
64         ucf_flags |= ucf_flags_from_smb_request(req);
65
66         switch (create_disposition) {
67         case FILE_OPEN:
68         case FILE_OVERWRITE:
69                 break;
70         case FILE_SUPERSEDE:
71         case FILE_CREATE:
72         case FILE_OPEN_IF:
73         case FILE_OVERWRITE_IF:
74                 ucf_flags |= UCF_PREP_CREATEFILE;
75                 break;
76         }
77
78         return ucf_flags;
79 }
80
81 /****************************************************************************
82  Mangle the 2nd name and check if it is then equal to the first name.
83 ****************************************************************************/
84
85 static bool mangled_equal(const char *name1,
86                         const char *name2,
87                         const struct share_params *p)
88 {
89         char mname[13];
90
91         if (!name_to_8_3(name2, mname, False, p)) {
92                 return False;
93         }
94         return strequal(name1, mname);
95 }
96
97 /*
98  * Strip a valid @GMT-token from any incoming filename path,
99  * adding any NTTIME encoded in the pathname into the
100  * twrp field of the passed in smb_fname.
101  *
102  * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
103  * at the *start* of a pathname component.
104  *
105  * If twrp is passed in then smb_fname->twrp is set to that
106  * value, and the @GMT-token part of the filename is removed
107  * and does not change the stored smb_fname->twrp.
108  *
109  */
110
111 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
112                                     uint32_t ucf_flags,
113                                     NTTIME twrp)
114 {
115         bool found;
116
117         if (twrp != 0) {
118                 smb_fname->twrp = twrp;
119         }
120
121         if (!(ucf_flags & UCF_GMT_PATHNAME)) {
122                 return NT_STATUS_OK;
123         }
124
125         found = extract_snapshot_token(smb_fname->base_name, &twrp);
126         if (!found) {
127                 return NT_STATUS_OK;
128         }
129
130         if (smb_fname->twrp == 0) {
131                 smb_fname->twrp = twrp;
132         }
133
134         return NT_STATUS_OK;
135 }
136
137 static bool strnorm(char *s, int case_default)
138 {
139         if (case_default == CASE_UPPER)
140                 return strupper_m(s);
141         else
142                 return strlower_m(s);
143 }
144
145 /*
146  * Utility function to normalize case on an incoming client filename
147  * if required on this connection struct.
148  * Performs an in-place case conversion guaranteed to stay the same size.
149  */
150
151 static NTSTATUS normalize_filename_case(connection_struct *conn,
152                                         char *filename,
153                                         uint32_t ucf_flags)
154 {
155         bool ok;
156
157         if (ucf_flags & UCF_POSIX_PATHNAMES) {
158                 /*
159                  * POSIX never normalizes filename case.
160                  */
161                 return NT_STATUS_OK;
162         }
163         if (!conn->case_sensitive) {
164                 return NT_STATUS_OK;
165         }
166         if (conn->case_preserve) {
167                 return NT_STATUS_OK;
168         }
169         if (conn->short_case_preserve) {
170                 return NT_STATUS_OK;
171         }
172         ok = strnorm(filename, lp_default_case(SNUM(conn)));
173         if (!ok) {
174                 return NT_STATUS_INVALID_PARAMETER;
175         }
176         return NT_STATUS_OK;
177 }
178
179 /****************************************************************************
180  Check if two filenames are equal.
181  This needs to be careful about whether we are case sensitive.
182 ****************************************************************************/
183
184 static bool fname_equal(const char *name1, const char *name2,
185                 bool case_sensitive)
186 {
187         /* Normal filename handling */
188         if (case_sensitive) {
189                 return(strcmp(name1,name2) == 0);
190         }
191
192         return(strequal(name1,name2));
193 }
194
195 static bool sname_equal(const char *name1, const char *name2,
196                 bool case_sensitive)
197 {
198         bool match;
199         const char *s1 = NULL;
200         const char *s2 = NULL;
201         size_t n1;
202         size_t n2;
203         const char *e1 = NULL;
204         const char *e2 = NULL;
205         char *c1 = NULL;
206         char *c2 = NULL;
207
208         match = fname_equal(name1, name2, case_sensitive);
209         if (match) {
210                 return true;
211         }
212
213         if (name1[0] != ':') {
214                 return false;
215         }
216         if (name2[0] != ':') {
217                 return false;
218         }
219         s1 = &name1[1];
220         e1 = strchr(s1, ':');
221         if (e1 == NULL) {
222                 n1 = strlen(s1);
223         } else {
224                 n1 = PTR_DIFF(e1, s1);
225         }
226         s2 = &name2[1];
227         e2 = strchr(s2, ':');
228         if (e2 == NULL) {
229                 n2 = strlen(s2);
230         } else {
231                 n2 = PTR_DIFF(e2, s2);
232         }
233
234         /* Normal filename handling */
235         if (case_sensitive) {
236                 return (strncmp(s1, s2, n1) == 0);
237         }
238
239         /*
240          * We can't use strnequal() here
241          * as it takes the number of codepoints
242          * and not the number of bytes.
243          *
244          * So we make a copy before calling
245          * strequal().
246          *
247          * Note that we TALLOC_FREE() in reverse order
248          * in order to avoid memory fragmentation.
249          */
250
251         c1 = talloc_strndup(talloc_tos(), s1, n1);
252         c2 = talloc_strndup(talloc_tos(), s2, n2);
253         if (c1 == NULL || c2 == NULL) {
254                 TALLOC_FREE(c2);
255                 TALLOC_FREE(c1);
256                 return (strncmp(s1, s2, n1) == 0);
257         }
258
259         match = strequal(c1, c2);
260         TALLOC_FREE(c2);
261         TALLOC_FREE(c1);
262         return match;
263 }
264
265 /****************************************************************************
266  Scan a directory to find a filename, matching without case sensitivity.
267  If the name looks like a mangled name then try via the mangling functions
268 ****************************************************************************/
269
270 NTSTATUS get_real_filename_full_scan_at(struct files_struct *dirfsp,
271                                         const char *name,
272                                         bool mangled,
273                                         TALLOC_CTX *mem_ctx,
274                                         char **found_name)
275 {
276         struct connection_struct *conn = dirfsp->conn;
277         struct smb_Dir *cur_dir = NULL;
278         const char *dname = NULL;
279         char *talloced = NULL;
280         char *unmangled_name = NULL;
281         NTSTATUS status;
282
283         /* If we have a case-sensitive filesystem, it doesn't do us any
284          * good to search for a name. If a case variation of the name was
285          * there, then the original stat(2) would have found it.
286          */
287         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
288                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
289         }
290
291         /*
292          * The incoming name can be mangled, and if we de-mangle it
293          * here it will not compare correctly against the filename (name2)
294          * read from the directory and then mangled by the name_to_8_3()
295          * call. We need to mangle both names or neither.
296          * (JRA).
297          *
298          * Fix for bug found by Dina Fine. If in case sensitive mode then
299          * the mangle cache is no good (3 letter extension could be wrong
300          * case - so don't demangle in this case - leave as mangled and
301          * allow the mangling of the directory entry read (which is done
302          * case insensitively) to match instead. This will lead to more
303          * false positive matches but we fail completely without it. JRA.
304          */
305
306         if (mangled && !conn->case_sensitive) {
307                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
308                                                        &unmangled_name,
309                                                        conn->params);
310                 if (!mangled) {
311                         /* Name is now unmangled. */
312                         name = unmangled_name;
313                 }
314         }
315
316         /* open the directory */
317         status = OpenDir_from_pathref(talloc_tos(), dirfsp, NULL, 0, &cur_dir);
318         if (!NT_STATUS_IS_OK(status)) {
319                 DBG_NOTICE("scan dir didn't open dir [%s]: %s\n",
320                            fsp_str_dbg(dirfsp),
321                            nt_errstr(status));
322                 TALLOC_FREE(unmangled_name);
323                 return status;
324         }
325
326         /* now scan for matching names */
327         while ((dname = ReadDirName(cur_dir, &talloced))) {
328
329                 /* Is it dot or dot dot. */
330                 if (ISDOT(dname) || ISDOTDOT(dname)) {
331                         TALLOC_FREE(talloced);
332                         continue;
333                 }
334
335                 /*
336                  * At this point dname is the unmangled name.
337                  * name is either mangled or not, depending on the state
338                  * of the "mangled" variable. JRA.
339                  */
340
341                 /*
342                  * Check mangled name against mangled name, or unmangled name
343                  * against unmangled name.
344                  */
345
346                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
347                         fname_equal(name, dname, conn->case_sensitive)) {
348                         /* we've found the file, change it's name and return */
349                         *found_name = talloc_strdup(mem_ctx, dname);
350                         TALLOC_FREE(unmangled_name);
351                         TALLOC_FREE(cur_dir);
352                         if (!*found_name) {
353                                 TALLOC_FREE(talloced);
354                                 return NT_STATUS_NO_MEMORY;
355                         }
356                         TALLOC_FREE(talloced);
357                         return NT_STATUS_OK;
358                 }
359                 TALLOC_FREE(talloced);
360         }
361
362         TALLOC_FREE(unmangled_name);
363         TALLOC_FREE(cur_dir);
364         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
365 }
366
367 /****************************************************************************
368  Wrapper around the vfs get_real_filename and the full directory scan
369  fallback.
370 ****************************************************************************/
371
372 NTSTATUS get_real_filename_at(struct files_struct *dirfsp,
373                               const char *name,
374                               TALLOC_CTX *mem_ctx,
375                               char **found_name)
376 {
377         struct connection_struct *conn = dirfsp->conn;
378         NTSTATUS status;
379         bool mangled;
380
381         mangled = mangle_is_mangled(name, conn->params);
382
383         if (mangled) {
384                 status = get_real_filename_full_scan_at(
385                         dirfsp, name, mangled, mem_ctx, found_name);
386                 return status;
387         }
388
389         /* Try the vfs first to take advantage of case-insensitive stat. */
390         status = SMB_VFS_GET_REAL_FILENAME_AT(
391                 dirfsp->conn, dirfsp, name, mem_ctx, found_name);
392
393         /*
394          * If the case-insensitive stat was successful, or returned an error
395          * other than EOPNOTSUPP then there is no need to fall back on the
396          * full directory scan.
397          */
398         if (NT_STATUS_IS_OK(status) ||
399             !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
400                 return status;
401         }
402
403         status = get_real_filename_full_scan_at(
404                 dirfsp, name, mangled, mem_ctx, found_name);
405         return status;
406 }
407
408 /*
409  * Lightweight function to just get last component
410  * for rename / enumerate directory calls.
411  */
412
413 char *get_original_lcomp(TALLOC_CTX *ctx,
414                         connection_struct *conn,
415                         const char *filename_in,
416                         uint32_t ucf_flags)
417 {
418         char *last_slash = NULL;
419         char *orig_lcomp;
420         NTSTATUS status;
421
422         last_slash = strrchr(filename_in, '/');
423         if (last_slash != NULL) {
424                 orig_lcomp = talloc_strdup(ctx, last_slash+1);
425         } else {
426                 orig_lcomp = talloc_strdup(ctx, filename_in);
427         }
428         if (orig_lcomp == NULL) {
429                 return NULL;
430         }
431         status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
432         if (!NT_STATUS_IS_OK(status)) {
433                 TALLOC_FREE(orig_lcomp);
434                 return NULL;
435         }
436         return orig_lcomp;
437 }
438
439 /*
440  * Get the correct capitalized stream name hanging off
441  * base_fsp. Equivalent of get_real_filename(), but for streams.
442  */
443 static NTSTATUS get_real_stream_name(
444         TALLOC_CTX *mem_ctx,
445         struct files_struct *base_fsp,
446         const char *stream_name,
447         char **_found)
448 {
449         unsigned int i, num_streams = 0;
450         struct stream_struct *streams = NULL;
451         NTSTATUS status;
452
453         status = vfs_fstreaminfo(
454                 base_fsp, talloc_tos(), &num_streams, &streams);
455         if (!NT_STATUS_IS_OK(status)) {
456                 return status;
457         }
458
459         for (i=0; i<num_streams; i++) {
460                 bool equal = sname_equal(stream_name, streams[i].name, false);
461
462                 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
463                           stream_name,
464                           streams[i].name,
465                           equal ? "" : "not ");
466
467                 if (equal) {
468                         *_found = talloc_move(mem_ctx, &streams[i].name);
469                         TALLOC_FREE(streams);
470                         return NT_STATUS_OK;
471                 }
472         }
473
474         TALLOC_FREE(streams);
475         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
476 }
477
478 static bool filename_split_lcomp(
479         TALLOC_CTX *mem_ctx,
480         const char *name_in,
481         bool posix,
482         char **_dirname,
483         const char **_fname_rel,
484         const char **_streamname)
485 {
486         const char *lcomp = NULL;
487         const char *fname_rel = NULL;
488         const char *streamname = NULL;
489         char *dirname = NULL;
490
491         if (name_in[0] == '\0') {
492                 fname_rel = ".";
493                 dirname = talloc_strdup(mem_ctx, "");
494                 if (dirname == NULL) {
495                         return false;
496                 }
497                 goto done;
498         }
499
500         lcomp = strrchr_m(name_in, '/');
501         if (lcomp != NULL) {
502                 fname_rel = lcomp+1;
503                 dirname = talloc_strndup(mem_ctx, name_in, lcomp - name_in);
504                 if (dirname == NULL) {
505                         return false;
506                 }
507                 goto find_stream;
508         }
509
510         /*
511          * No slash, dir is empty
512          */
513         dirname = talloc_strdup(mem_ctx, "");
514         if (dirname == NULL) {
515                 return false;
516         }
517
518         if (!posix && (name_in[0] == ':')) {
519                 /*
520                  * Special case for stream on root directory
521                  */
522                 fname_rel = ".";
523                 streamname = name_in;
524                 goto done;
525         }
526
527         fname_rel = name_in;
528
529 find_stream:
530         if (!posix) {
531                 streamname = strchr_m(fname_rel, ':');
532
533                 if (streamname != NULL) {
534                         fname_rel = talloc_strndup(
535                                 mem_ctx,
536                                 fname_rel,
537                                 streamname - fname_rel);
538                         if (fname_rel == NULL) {
539                                 TALLOC_FREE(dirname);
540                                 return false;
541                         }
542                 }
543         }
544
545 done:
546         *_dirname = dirname;
547         *_fname_rel = fname_rel;
548         *_streamname = streamname;
549         return true;
550 }
551
552 /*
553  * Create the correct capitalization of a file name to be created.
554  */
555 static NTSTATUS filename_convert_normalize_new(
556         TALLOC_CTX *mem_ctx,
557         struct connection_struct *conn,
558         char *name_in,
559         char **_normalized)
560 {
561         char *name = name_in;
562
563         *_normalized = NULL;
564
565         if (!conn->case_preserve ||
566             (mangle_is_8_3(name, false,
567                            conn->params) &&
568              !conn->short_case_preserve)) {
569
570                 char *normalized = talloc_strdup(mem_ctx, name);
571                 if (normalized == NULL) {
572                         return NT_STATUS_NO_MEMORY;
573                 }
574
575                 strnorm(normalized, lp_default_case(SNUM(conn)));
576                 name = normalized;
577         }
578
579         if (mangle_is_mangled(name, conn->params)) {
580                 bool found;
581                 char *unmangled = NULL;
582
583                 found = mangle_lookup_name_from_8_3(
584                         mem_ctx, name, &unmangled, conn->params);
585                 if (found) {
586                         name = unmangled;
587                 }
588         }
589
590         if (name != name_in) {
591                 *_normalized = name;
592         }
593
594         return NT_STATUS_OK;
595 }
596
597 static const char *previous_slash(const char *name_in, const char *slash)
598 {
599         const char *prev = NULL;
600
601         SMB_ASSERT((name_in <= slash) && (slash[0] == '/'));
602
603         prev = strchr_m(name_in, '/');
604
605         if (prev == slash) {
606                 /* No previous slash */
607                 return NULL;
608         }
609
610         while (true) {
611                 const char *next = strchr_m(prev + 1, '/');
612
613                 if (next == slash) {
614                         return prev;
615                 }
616                 prev = next;
617         }
618
619         return NULL; /* unreachable */
620 }
621
622 static char *symlink_target_path(
623         TALLOC_CTX *mem_ctx,
624         const char *name_in,
625         const char *substitute,
626         size_t unparsed)
627 {
628         size_t name_in_len = strlen(name_in);
629         const char *p_unparsed = NULL;
630         const char *parent = NULL;
631         char *ret;
632
633         SMB_ASSERT(unparsed <= name_in_len);
634
635         p_unparsed = name_in + (name_in_len - unparsed);
636
637         if (substitute[0] == '/') {
638                 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
639                 return ret;
640         }
641
642         if (unparsed == 0) {
643                 parent = strrchr_m(name_in, '/');
644         } else {
645                 parent = previous_slash(name_in, p_unparsed);
646         }
647
648         if (parent == NULL) {
649                 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
650         } else {
651                 ret = talloc_asprintf(mem_ctx,
652                                       "%.*s/%s%s",
653                                       (int)(parent - name_in),
654                                       name_in,
655                                       substitute,
656                                       p_unparsed);
657         }
658
659         return ret;
660 }
661
662 NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
663                                   const char *connectpath,
664                                   const char *dir,
665                                   const char *target,
666                                   size_t unparsed,
667                                   char **_relative)
668 {
669         char *abs_target = NULL;
670         char *abs_target_canon = NULL;
671         const char *relative = NULL;
672         bool in_share;
673         NTSTATUS status = NT_STATUS_NO_MEMORY;
674
675         DBG_DEBUG("connectpath [%s] target [%s] unparsed [%zu]\n",
676                   connectpath, target, unparsed);
677
678         if (target[0] == '/') {
679                 abs_target = talloc_strdup(mem_ctx, target);
680         } else if (dir == NULL) {
681                 abs_target = talloc_asprintf(mem_ctx,
682                                              "%s/%s",
683                                              connectpath,
684                                              target);
685         } else if (dir[0] == '/') {
686                 abs_target = talloc_asprintf(mem_ctx,
687                                              "%s/%s",
688                                              dir,
689                                              target);
690         } else {
691                 abs_target = talloc_asprintf(mem_ctx,
692                                              "%s/%s/%s",
693                                              connectpath,
694                                              dir,
695                                              target);
696         }
697         if (abs_target == NULL) {
698                 goto fail;
699         }
700
701         abs_target_canon = canonicalize_absolute_path(abs_target, abs_target);
702         if (abs_target_canon == NULL) {
703                 goto fail;
704         }
705
706         DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
707
708         in_share = subdir_of(
709                 connectpath, strlen(connectpath), abs_target_canon, &relative);
710         if (!in_share) {
711                 DBG_DEBUG("wide link to %s\n", abs_target_canon);
712                 status = (unparsed != 0) ? NT_STATUS_OBJECT_PATH_NOT_FOUND
713                                          : NT_STATUS_OBJECT_NAME_NOT_FOUND;
714                 goto fail;
715         }
716
717         *_relative = talloc_strdup(mem_ctx, relative);
718         if (*_relative == NULL) {
719                 goto fail;
720         }
721
722         status = NT_STATUS_OK;
723 fail:
724         TALLOC_FREE(abs_target);
725         return status;
726 }
727
728 /*
729  * Split up name_in as sent by the client into a directory pathref fsp
730  * and a relative smb_filename.
731  */
732 static NTSTATUS filename_convert_dirfsp_nosymlink(
733         TALLOC_CTX *mem_ctx,
734         connection_struct *conn,
735         const char *name_in,
736         uint32_t ucf_flags,
737         NTTIME twrp,
738         struct files_struct **_dirfsp,
739         struct smb_filename **_smb_fname,
740         struct reparse_data_buffer **_symlink_err)
741 {
742         struct smb_filename *smb_dirname = NULL;
743         struct smb_filename *smb_fname_rel = NULL;
744         struct smb_filename *smb_fname = NULL;
745         struct reparse_data_buffer *symlink_err = NULL;
746         const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
747         char *dirname = NULL;
748         const char *fname_rel = NULL;
749         const char *streamname = NULL;
750         char *saved_streamname = NULL;
751         struct files_struct *base_fsp = NULL;
752         bool ok;
753         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
754
755         SMB_ASSERT(!(ucf_flags & UCF_DFS_PATHNAME));
756
757         if (is_fake_file_path(name_in)) {
758                 smb_fname = synthetic_smb_fname_split(mem_ctx, name_in, posix);
759                 if (smb_fname == NULL) {
760                         return NT_STATUS_NO_MEMORY;
761                 }
762                 smb_fname->st = (SMB_STRUCT_STAT){
763                         .st_ex_nlink = 1,
764                         .st_ex_mode = S_IFREG | 0644,
765                 };
766                 smb_fname->st.st_ex_btime =
767                         (struct timespec){0, SAMBA_UTIME_OMIT};
768                 smb_fname->st.st_ex_atime =
769                         (struct timespec){0, SAMBA_UTIME_OMIT};
770                 smb_fname->st.st_ex_mtime =
771                         (struct timespec){0, SAMBA_UTIME_OMIT};
772                 smb_fname->st.st_ex_ctime =
773                         (struct timespec){0, SAMBA_UTIME_OMIT};
774
775                 *_dirfsp = conn->cwd_fsp;
776                 *_smb_fname = smb_fname;
777                 return NT_STATUS_OK;
778         }
779
780         /*
781          * Catch an invalid path of "." before we
782          * call filename_split_lcomp(). We need to
783          * do this as filename_split_lcomp() will
784          * use "." for the missing relative component
785          * when an empty name_in path is sent by
786          * the client.
787          */
788         if (ISDOT(name_in)) {
789                 status = NT_STATUS_OBJECT_NAME_INVALID;
790                 goto fail;
791         }
792
793         ok = filename_split_lcomp(
794                 talloc_tos(),
795                 name_in,
796                 posix,
797                 &dirname,
798                 &fname_rel,
799                 &streamname);
800         if (!ok) {
801                 status = NT_STATUS_NO_MEMORY;
802                 goto fail;
803         }
804
805         if ((streamname != NULL) &&
806             ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) {
807                 status = NT_STATUS_OBJECT_NAME_INVALID;
808                 goto fail;
809         }
810
811         if (!posix) {
812                 bool name_has_wild = ms_has_wild(dirname);
813                 name_has_wild |= ms_has_wild(fname_rel);
814                 if (name_has_wild) {
815                         status = NT_STATUS_OBJECT_NAME_INVALID;
816                         goto fail;
817                 }
818         }
819
820         if (dirname[0] == '\0') {
821                 status = synthetic_pathref(
822                         mem_ctx,
823                         conn->cwd_fsp,
824                         ".",
825                         NULL,
826                         NULL,
827                         0,
828                         posix ? SMB_FILENAME_POSIX_PATH : 0,
829                         &smb_dirname);
830         } else {
831                 status = normalize_filename_case(conn, dirname, ucf_flags);
832                 if (!NT_STATUS_IS_OK(status)) {
833                         DBG_ERR("normalize_filename_case %s failed: %s\n",
834                                 dirname,
835                                 nt_errstr(status));
836                         goto fail;
837                 }
838
839                 status = openat_pathref_fsp_nosymlink(mem_ctx,
840                                                       conn,
841                                                       conn->cwd_fsp,
842                                                       dirname,
843                                                       twrp,
844                                                       posix,
845                                                       &smb_dirname,
846                                                       &symlink_err);
847
848                 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
849                         struct symlink_reparse_struct
850                                 *lnk = &symlink_err->parsed.lnk;
851                         size_t unparsed = lnk->unparsed_path_length;
852                         size_t name_in_len, dirname_len;
853
854                         name_in_len = strlen(name_in);
855                         dirname_len = strlen(dirname);
856
857                         SMB_ASSERT(name_in_len >= dirname_len);
858
859                         unparsed += (name_in_len - dirname_len);
860
861                         if (unparsed > UINT16_MAX) {
862                                 status = NT_STATUS_BUFFER_OVERFLOW;
863                                 goto fail;
864                         }
865
866                         lnk->unparsed_path_length = unparsed;
867                         *_symlink_err = symlink_err;
868
869                         goto fail;
870                 }
871         }
872
873         if (!NT_STATUS_IS_OK(status)) {
874                 DBG_DEBUG("opening directory %s failed: %s\n",
875                           dirname,
876                           nt_errstr(status));
877                 TALLOC_FREE(dirname);
878
879                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
880                         /*
881                          * Except ACCESS_DENIED, everything else leads
882                          * to PATH_NOT_FOUND.
883                          */
884                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
885                 }
886
887                 goto fail;
888         }
889
890         if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
891                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
892                 goto fail;
893         }
894         smb_dirname->fsp->fsp_flags.is_directory = true;
895
896         /*
897          * Only look at bad last component values
898          * once we know we have a valid directory. That
899          * way we won't confuse error messages from
900          * opening the directory path with error
901          * messages from a bad last component.
902          */
903
904         /* Relative filename can't be empty */
905         if (fname_rel[0] == '\0') {
906                 status = NT_STATUS_OBJECT_NAME_INVALID;
907                 goto fail;
908         }
909
910         /* Relative filename can't be ".." */
911         if (ISDOTDOT(fname_rel)) {
912                 status = NT_STATUS_OBJECT_NAME_INVALID;
913                 goto fail;
914         }
915         /* Relative name can only be dot if directory is empty. */
916         if (ISDOT(fname_rel) && dirname[0] != '\0') {
917                 status = NT_STATUS_OBJECT_NAME_INVALID;
918                 goto fail;
919         }
920
921         TALLOC_FREE(dirname);
922
923         smb_fname_rel = synthetic_smb_fname(
924                 mem_ctx,
925                 fname_rel,
926                 streamname,
927                 NULL,
928                 twrp,
929                 posix ? SMB_FILENAME_POSIX_PATH : 0);
930         if (smb_fname_rel == NULL) {
931                 status = NT_STATUS_NO_MEMORY;
932                 goto fail;
933         }
934
935         if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
936             is_named_stream(smb_fname_rel)) {
937                 /*
938                  * Find the base_fsp first without the stream.
939                  */
940                 saved_streamname = smb_fname_rel->stream_name;
941                 smb_fname_rel->stream_name = NULL;
942         }
943
944         status = normalize_filename_case(
945                 conn, smb_fname_rel->base_name, ucf_flags);
946         if (!NT_STATUS_IS_OK(status)) {
947                 DBG_ERR("normalize_filename_case %s failed: %s\n",
948                         smb_fname_rel->base_name,
949                         nt_errstr(status));
950                 goto fail;
951         }
952
953         status = openat_pathref_fsp_lcomp(smb_dirname->fsp,
954                                           smb_fname_rel,
955                                           ucf_flags);
956
957         if (NT_STATUS_IS_OK(status) && S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
958
959                 /*
960                  * Upper layers might need the link target. Here we
961                  * still have the relname around, get the symlink err.
962                  */
963                 status = read_symlink_reparse(mem_ctx,
964                                               smb_dirname->fsp,
965                                               smb_fname_rel,
966                                               &symlink_err);
967                 if (!NT_STATUS_IS_OK(status)) {
968                         DBG_DEBUG("Could not read symlink for %s: %s\n",
969                                   smb_fname_str_dbg(
970                                           smb_fname_rel->fsp->fsp_name),
971                                   nt_errstr(status));
972                         goto fail;
973                 }
974         }
975
976         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
977             !VALID_STAT(smb_fname_rel->st)) {
978
979                 char *normalized = NULL;
980
981                 /*
982                  * Creating a new file
983                  */
984
985                 status = filename_convert_normalize_new(
986                         smb_fname_rel,
987                         conn,
988                         smb_fname_rel->base_name,
989                         &normalized);
990                 if (!NT_STATUS_IS_OK(status)) {
991                         DBG_DEBUG("filename_convert_normalize_new failed: "
992                                   "%s\n",
993                                   nt_errstr(status));
994                         goto fail;
995                 }
996                 if (normalized != NULL) {
997                         smb_fname_rel->base_name = normalized;
998                 }
999
1000                 smb_fname_rel->stream_name = saved_streamname;
1001
1002                 smb_fname = full_path_from_dirfsp_atname(
1003                         mem_ctx, smb_dirname->fsp, smb_fname_rel);
1004                 if (smb_fname == NULL) {
1005                         status = NT_STATUS_NO_MEMORY;
1006                         goto fail;
1007                 }
1008                 goto done;
1009         }
1010
1011         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_OPEN_RESTRICTION)) {
1012                 /* A vetoed file, pretend it's not there  */
1013                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1014         }
1015         if (!NT_STATUS_IS_OK(status)) {
1016                 goto fail;
1017         }
1018
1019         if (saved_streamname == NULL) {
1020                 /* smb_fname must be allocated off mem_ctx. */
1021                 smb_fname = cp_smb_filename(mem_ctx,
1022                                             smb_fname_rel->fsp->fsp_name);
1023                 if (smb_fname == NULL) {
1024                         goto fail;
1025                 }
1026                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
1027                 if (!NT_STATUS_IS_OK(status)) {
1028                         goto fail;
1029                 }
1030                 goto done;
1031         }
1032
1033         base_fsp = smb_fname_rel->fsp;
1034         smb_fname_fsp_unlink(smb_fname_rel);
1035         SET_STAT_INVALID(smb_fname_rel->st);
1036
1037         smb_fname_rel->stream_name = saved_streamname;
1038
1039         status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
1040
1041         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
1042             !conn->case_sensitive) {
1043                 char *found = NULL;
1044
1045                 status = get_real_stream_name(
1046                         smb_fname_rel,
1047                         base_fsp,
1048                         smb_fname_rel->stream_name,
1049                         &found);
1050
1051                 if (NT_STATUS_IS_OK(status)) {
1052                         smb_fname_rel->stream_name = found;
1053                         found = NULL;
1054                         status = open_stream_pathref_fsp(
1055                                 &base_fsp, smb_fname_rel);
1056                 }
1057         }
1058
1059         if (NT_STATUS_IS_OK(status)) {
1060                 /* smb_fname must be allocated off mem_ctx. */
1061                 smb_fname = cp_smb_filename(mem_ctx,
1062                                             smb_fname_rel->fsp->fsp_name);
1063                 if (smb_fname == NULL) {
1064                         goto fail;
1065                 }
1066                 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
1067                 if (!NT_STATUS_IS_OK(status)) {
1068                         goto fail;
1069                 }
1070                 goto done;
1071         }
1072
1073         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1074                 /*
1075                  * Creating a new stream
1076                  *
1077                  * We should save the already-open base fsp for
1078                  * create_file_unixpath() somehow.
1079                  */
1080                 smb_fname = full_path_from_dirfsp_atname(
1081                         mem_ctx, smb_dirname->fsp, smb_fname_rel);
1082                 if (smb_fname == NULL) {
1083                         status = NT_STATUS_NO_MEMORY;
1084                         goto fail;
1085                 }
1086                 /*
1087                  * When open_stream_pathref_fsp() returns
1088                  * NT_STATUS_OBJECT_NAME_NOT_FOUND, smb_fname_rel->fsp
1089                  * has been set to NULL, so we must free base_fsp separately
1090                  * to prevent fd-leaks when opening a stream that doesn't
1091                  * exist.
1092                  */
1093                 fd_close(base_fsp);
1094                 file_free(NULL, base_fsp);
1095                 base_fsp = NULL;
1096                 goto done;
1097         }
1098
1099         if (!NT_STATUS_IS_OK(status)) {
1100                 goto fail;
1101         }
1102
1103 done:
1104         *_dirfsp = smb_dirname->fsp;
1105         *_smb_fname = smb_fname;
1106         *_symlink_err = symlink_err;
1107
1108         smb_fname_fsp_unlink(smb_fname_rel);
1109         TALLOC_FREE(smb_fname_rel);
1110         return NT_STATUS_OK;
1111
1112 fail:
1113         /*
1114          * If open_stream_pathref_fsp() returns an error, smb_fname_rel->fsp
1115          * has been set to NULL, so we must free base_fsp separately
1116          * to prevent fd-leaks when opening a stream that doesn't
1117          * exist.
1118          */
1119         if (base_fsp != NULL) {
1120                 fd_close(base_fsp);
1121                 file_free(NULL, base_fsp);
1122                 base_fsp = NULL;
1123         }
1124         TALLOC_FREE(dirname);
1125         TALLOC_FREE(smb_dirname);
1126         TALLOC_FREE(smb_fname_rel);
1127         return status;
1128 }
1129
1130 NTSTATUS filename_convert_dirfsp(
1131         TALLOC_CTX *mem_ctx,
1132         connection_struct *conn,
1133         const char *name_in,
1134         uint32_t ucf_flags,
1135         NTTIME twrp,
1136         struct files_struct **_dirfsp,
1137         struct smb_filename **_smb_fname)
1138 {
1139         struct reparse_data_buffer *symlink_err = NULL;
1140         struct symlink_reparse_struct *lnk = NULL;
1141         NTSTATUS status;
1142         char *target = NULL;
1143         char *safe_target = NULL;
1144         size_t symlink_redirects = 0;
1145
1146 next:
1147         if (symlink_redirects > 40) {
1148                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1149         }
1150
1151         status = filename_convert_dirfsp_nosymlink(mem_ctx,
1152                                                    conn,
1153                                                    name_in,
1154                                                    ucf_flags,
1155                                                    twrp,
1156                                                    _dirfsp,
1157                                                    _smb_fname,
1158                                                    &symlink_err);
1159
1160         if (NT_STATUS_IS_OK(status) && S_ISLNK((*_smb_fname)->st.st_ex_mode)) {
1161                 /*
1162                  * lcomp is a symlink
1163                  */
1164                 if (ucf_flags & UCF_LCOMP_LNK_OK) {
1165                         TALLOC_FREE(symlink_err);
1166                         return NT_STATUS_OK;
1167                 }
1168                 close_file_free(NULL, _dirfsp, ERROR_CLOSE);
1169                 status = NT_STATUS_STOPPED_ON_SYMLINK;
1170         }
1171
1172         if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1173                 return status;
1174         }
1175         lnk = &symlink_err->parsed.lnk;
1176
1177         /*
1178          * If we're on an MSDFS share, see if this is
1179          * an MSDFS link.
1180          */
1181         if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
1182             strnequal(lnk->substitute_name, "msdfs:", 6))
1183         {
1184                 TALLOC_FREE(*_smb_fname);
1185                 TALLOC_FREE(symlink_err);
1186                 return NT_STATUS_PATH_NOT_COVERED;
1187         }
1188
1189         if (!lp_follow_symlinks(SNUM(conn))) {
1190                 status = (lnk->unparsed_path_length == 0)
1191                                  ? NT_STATUS_OBJECT_NAME_NOT_FOUND
1192                                  : NT_STATUS_OBJECT_PATH_NOT_FOUND;
1193                 TALLOC_FREE(symlink_err);
1194                 return status;
1195         }
1196
1197         /*
1198          * Right now, SMB2 and SMB1 always traverse symlinks
1199          * within the share. SMB1+POSIX traverses non-terminal
1200          * symlinks within the share.
1201          *
1202          * When we add SMB2+POSIX we need to return
1203          * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
1204          * symlink target data read below if SMB2+POSIX has
1205          * UCF_POSIX_PATHNAMES set to cause the client to
1206          * resolve all symlinks locally.
1207          */
1208
1209         target = symlink_target_path(mem_ctx,
1210                                      name_in,
1211                                      lnk->substitute_name,
1212                                      lnk->unparsed_path_length);
1213         if (target == NULL) {
1214                 return NT_STATUS_NO_MEMORY;
1215         }
1216
1217         status = safe_symlink_target_path(mem_ctx,
1218                                           conn->connectpath,
1219                                           NULL,
1220                                           target,
1221                                           lnk->unparsed_path_length,
1222                                           &safe_target);
1223         TALLOC_FREE(symlink_err);
1224         if (!NT_STATUS_IS_OK(status)) {
1225                 return status;
1226         }
1227         name_in = safe_target;
1228
1229         symlink_redirects += 1;
1230
1231         goto next;
1232 }
1233
1234 char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx,
1235                                         const struct files_struct *dirfsp,
1236                                         const char *at_base_name)
1237 {
1238         char *path = NULL;
1239
1240         if (dirfsp == dirfsp->conn->cwd_fsp ||
1241             ISDOT(dirfsp->fsp_name->base_name) || at_base_name[0] == '/') {
1242                 path = talloc_strdup(mem_ctx, at_base_name);
1243         } else {
1244                 path = talloc_asprintf(mem_ctx,
1245                                        "%s/%s",
1246                                        dirfsp->fsp_name->base_name,
1247                                        at_base_name);
1248         }
1249
1250         return path;
1251 }
1252
1253 /*
1254  * Build the full path from a dirfsp and dirfsp relative name
1255  */
1256 struct smb_filename *
1257 full_path_from_dirfsp_atname(TALLOC_CTX *mem_ctx,
1258                              const struct files_struct *dirfsp,
1259                              const struct smb_filename *atname)
1260 {
1261         struct smb_filename *fname = NULL;
1262         char *path = NULL;
1263
1264         path = full_path_from_dirfsp_at_basename(mem_ctx,
1265                                                  dirfsp,
1266                                                  atname->base_name);
1267         if (path == NULL) {
1268                 return NULL;
1269         }
1270
1271         fname = synthetic_smb_fname(mem_ctx,
1272                                     path,
1273                                     atname->stream_name,
1274                                     &atname->st,
1275                                     atname->twrp,
1276                                     atname->flags);
1277         TALLOC_FREE(path);
1278         if (fname == NULL) {
1279                 return NULL;
1280         }
1281
1282         return fname;
1283 }