s3: smbd: Fix schedule_aio_smb2_write() to allow the last write in a compound to...
[Samba.git] / source3 / smbd / filename.c
blob1f8b33c7fda9318c3f501a15c8418e8443aa8c44
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
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.
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.
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/>.
24 * New hash table stat cache code added by Ying Chen.
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 "lib/util/memcache.h"
34 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
36 uint32_t ucf_flags = 0;
38 if (req != NULL) {
39 if (req->posix_pathnames) {
40 ucf_flags |= UCF_POSIX_PATHNAMES;
42 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
43 ucf_flags |= UCF_DFS_PATHNAME;
45 if (req->flags2 & FLAGS2_REPARSE_PATH) {
46 ucf_flags |= UCF_GMT_PATHNAME;
50 return ucf_flags;
53 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
55 uint32_t ucf_flags = 0;
57 ucf_flags |= ucf_flags_from_smb_request(req);
59 switch (create_disposition) {
60 case FILE_OPEN:
61 case FILE_OVERWRITE:
62 break;
63 case FILE_SUPERSEDE:
64 case FILE_CREATE:
65 case FILE_OPEN_IF:
66 case FILE_OVERWRITE_IF:
67 ucf_flags |= UCF_PREP_CREATEFILE;
68 break;
71 return ucf_flags;
74 /****************************************************************************
75 Mangle the 2nd name and check if it is then equal to the first name.
76 ****************************************************************************/
78 static bool mangled_equal(const char *name1,
79 const char *name2,
80 const struct share_params *p)
82 char mname[13];
84 if (!name_to_8_3(name2, mname, False, p)) {
85 return False;
87 return strequal(name1, mname);
91 * Strip a valid @GMT-token from any incoming filename path,
92 * adding any NTTIME encoded in the pathname into the
93 * twrp field of the passed in smb_fname.
95 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
96 * at the *start* of a pathname component.
98 * If twrp is passed in then smb_fname->twrp is set to that
99 * value, and the @GMT-token part of the filename is removed
100 * and does not change the stored smb_fname->twrp.
104 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
105 uint32_t ucf_flags,
106 NTTIME twrp)
108 bool found;
110 if (twrp != 0) {
111 smb_fname->twrp = twrp;
114 if (!(ucf_flags & UCF_GMT_PATHNAME)) {
115 return NT_STATUS_OK;
118 found = extract_snapshot_token(smb_fname->base_name, &twrp);
119 if (!found) {
120 return NT_STATUS_OK;
123 if (smb_fname->twrp == 0) {
124 smb_fname->twrp = twrp;
127 return NT_STATUS_OK;
130 static bool strnorm(char *s, int case_default)
132 if (case_default == CASE_UPPER)
133 return strupper_m(s);
134 else
135 return strlower_m(s);
139 * Utility function to normalize case on an incoming client filename
140 * if required on this connection struct.
141 * Performs an in-place case conversion guaranteed to stay the same size.
144 static NTSTATUS normalize_filename_case(connection_struct *conn,
145 char *filename,
146 uint32_t ucf_flags)
148 bool ok;
150 if (ucf_flags & UCF_POSIX_PATHNAMES) {
152 * POSIX never normalizes filename case.
154 return NT_STATUS_OK;
156 if (!conn->case_sensitive) {
157 return NT_STATUS_OK;
159 if (conn->case_preserve) {
160 return NT_STATUS_OK;
162 if (conn->short_case_preserve) {
163 return NT_STATUS_OK;
165 ok = strnorm(filename, lp_default_case(SNUM(conn)));
166 if (!ok) {
167 return NT_STATUS_INVALID_PARAMETER;
169 return NT_STATUS_OK;
172 /****************************************************************************
173 Check if two filenames are equal.
174 This needs to be careful about whether we are case sensitive.
175 ****************************************************************************/
177 static bool fname_equal(const char *name1, const char *name2,
178 bool case_sensitive)
180 /* Normal filename handling */
181 if (case_sensitive) {
182 return(strcmp(name1,name2) == 0);
185 return(strequal(name1,name2));
188 static bool sname_equal(const char *name1, const char *name2,
189 bool case_sensitive)
191 bool match;
192 const char *s1 = NULL;
193 const char *s2 = NULL;
194 size_t n1;
195 size_t n2;
196 const char *e1 = NULL;
197 const char *e2 = NULL;
198 char *c1 = NULL;
199 char *c2 = NULL;
201 match = fname_equal(name1, name2, case_sensitive);
202 if (match) {
203 return true;
206 if (name1[0] != ':') {
207 return false;
209 if (name2[0] != ':') {
210 return false;
212 s1 = &name1[1];
213 e1 = strchr(s1, ':');
214 if (e1 == NULL) {
215 n1 = strlen(s1);
216 } else {
217 n1 = PTR_DIFF(e1, s1);
219 s2 = &name2[1];
220 e2 = strchr(s2, ':');
221 if (e2 == NULL) {
222 n2 = strlen(s2);
223 } else {
224 n2 = PTR_DIFF(e2, s2);
227 /* Normal filename handling */
228 if (case_sensitive) {
229 return (strncmp(s1, s2, n1) == 0);
233 * We can't use strnequal() here
234 * as it takes the number of codepoints
235 * and not the number of bytes.
237 * So we make a copy before calling
238 * strequal().
240 * Note that we TALLOC_FREE() in reverse order
241 * in order to avoid memory fragmentation.
244 c1 = talloc_strndup(talloc_tos(), s1, n1);
245 c2 = talloc_strndup(talloc_tos(), s2, n2);
246 if (c1 == NULL || c2 == NULL) {
247 TALLOC_FREE(c2);
248 TALLOC_FREE(c1);
249 return (strncmp(s1, s2, n1) == 0);
252 match = strequal(c1, c2);
253 TALLOC_FREE(c2);
254 TALLOC_FREE(c1);
255 return match;
258 /****************************************************************************
259 Scan a directory to find a filename, matching without case sensitivity.
260 If the name looks like a mangled name then try via the mangling functions
261 ****************************************************************************/
263 NTSTATUS get_real_filename_full_scan_at(struct files_struct *dirfsp,
264 const char *name,
265 bool mangled,
266 TALLOC_CTX *mem_ctx,
267 char **found_name)
269 struct connection_struct *conn = dirfsp->conn;
270 struct smb_Dir *cur_dir = NULL;
271 const char *dname = NULL;
272 char *talloced = NULL;
273 char *unmangled_name = NULL;
274 long curpos;
275 NTSTATUS status;
277 /* If we have a case-sensitive filesystem, it doesn't do us any
278 * good to search for a name. If a case variation of the name was
279 * there, then the original stat(2) would have found it.
281 if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
282 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
286 * The incoming name can be mangled, and if we de-mangle it
287 * here it will not compare correctly against the filename (name2)
288 * read from the directory and then mangled by the name_to_8_3()
289 * call. We need to mangle both names or neither.
290 * (JRA).
292 * Fix for bug found by Dina Fine. If in case sensitive mode then
293 * the mangle cache is no good (3 letter extension could be wrong
294 * case - so don't demangle in this case - leave as mangled and
295 * allow the mangling of the directory entry read (which is done
296 * case insensitively) to match instead. This will lead to more
297 * false positive matches but we fail completely without it. JRA.
300 if (mangled && !conn->case_sensitive) {
301 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
302 &unmangled_name,
303 conn->params);
304 if (!mangled) {
305 /* Name is now unmangled. */
306 name = unmangled_name;
310 /* open the directory */
311 status = OpenDir_from_pathref(talloc_tos(), dirfsp, NULL, 0, &cur_dir);
312 if (!NT_STATUS_IS_OK(status)) {
313 DBG_NOTICE("scan dir didn't open dir [%s]: %s\n",
314 fsp_str_dbg(dirfsp),
315 nt_errstr(status));
316 TALLOC_FREE(unmangled_name);
317 return status;
320 /* now scan for matching names */
321 curpos = 0;
322 while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
324 /* Is it dot or dot dot. */
325 if (ISDOT(dname) || ISDOTDOT(dname)) {
326 TALLOC_FREE(talloced);
327 continue;
331 * At this point dname is the unmangled name.
332 * name is either mangled or not, depending on the state
333 * of the "mangled" variable. JRA.
337 * Check mangled name against mangled name, or unmangled name
338 * against unmangled name.
341 if ((mangled && mangled_equal(name,dname,conn->params)) ||
342 fname_equal(name, dname, conn->case_sensitive)) {
343 /* we've found the file, change it's name and return */
344 *found_name = talloc_strdup(mem_ctx, dname);
345 TALLOC_FREE(unmangled_name);
346 TALLOC_FREE(cur_dir);
347 if (!*found_name) {
348 TALLOC_FREE(talloced);
349 return NT_STATUS_NO_MEMORY;
351 TALLOC_FREE(talloced);
352 return NT_STATUS_OK;
354 TALLOC_FREE(talloced);
357 TALLOC_FREE(unmangled_name);
358 TALLOC_FREE(cur_dir);
359 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
362 /****************************************************************************
363 Wrapper around the vfs get_real_filename and the full directory scan
364 fallback.
365 ****************************************************************************/
367 NTSTATUS get_real_filename_at(struct files_struct *dirfsp,
368 const char *name,
369 TALLOC_CTX *mem_ctx,
370 char **found_name)
372 struct connection_struct *conn = dirfsp->conn;
373 NTSTATUS status;
374 bool mangled;
376 mangled = mangle_is_mangled(name, conn->params);
378 if (mangled) {
379 status = get_real_filename_full_scan_at(
380 dirfsp, name, mangled, mem_ctx, found_name);
381 return status;
384 /* Try the vfs first to take advantage of case-insensitive stat. */
385 status = SMB_VFS_GET_REAL_FILENAME_AT(
386 dirfsp->conn, dirfsp, name, mem_ctx, found_name);
389 * If the case-insensitive stat was successful, or returned an error
390 * other than EOPNOTSUPP then there is no need to fall back on the
391 * full directory scan.
393 if (NT_STATUS_IS_OK(status) ||
394 !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
395 return status;
398 status = get_real_filename_full_scan_at(
399 dirfsp, name, mangled, mem_ctx, found_name);
400 return status;
404 * Create the memcache-key for GETREALFILENAME_CACHE: This supplements
405 * the stat cache for the last component to be looked up. Cache
406 * contents is the correctly capitalized translation of the parameter
407 * "name" as it exists on disk. This is indexed by inode of the dirfsp
408 * and name, and contrary to stat_cahce_lookup() it does not
409 * vfs_stat() the last component. This will be taken care of by an
410 * attempt to do a openat_pathref_fsp().
412 static bool get_real_filename_cache_key(
413 TALLOC_CTX *mem_ctx,
414 struct files_struct *dirfsp,
415 const char *name,
416 DATA_BLOB *_key)
418 struct file_id fid = vfs_file_id_from_sbuf(
419 dirfsp->conn, &dirfsp->fsp_name->st);
420 char *upper = NULL;
421 uint8_t *key = NULL;
422 size_t namelen, keylen;
424 upper = talloc_strdup_upper(mem_ctx, name);
425 if (upper == NULL) {
426 return false;
428 namelen = talloc_get_size(upper);
430 keylen = namelen + sizeof(fid);
431 if (keylen < sizeof(fid)) {
432 TALLOC_FREE(upper);
433 return false;
436 key = talloc_size(mem_ctx, keylen);
437 if (key == NULL) {
438 TALLOC_FREE(upper);
439 return false;
442 memcpy(key, &fid, sizeof(fid));
443 memcpy(key + sizeof(fid), upper, namelen);
444 TALLOC_FREE(upper);
446 *_key = (DATA_BLOB) { .data = key, .length = keylen, };
447 return true;
451 * Lightweight function to just get last component
452 * for rename / enumerate directory calls.
455 char *get_original_lcomp(TALLOC_CTX *ctx,
456 connection_struct *conn,
457 const char *filename_in,
458 uint32_t ucf_flags)
460 char *last_slash = NULL;
461 char *orig_lcomp;
462 NTSTATUS status;
464 last_slash = strrchr(filename_in, '/');
465 if (last_slash != NULL) {
466 orig_lcomp = talloc_strdup(ctx, last_slash+1);
467 } else {
468 orig_lcomp = talloc_strdup(ctx, filename_in);
470 if (orig_lcomp == NULL) {
471 return NULL;
473 status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
474 if (!NT_STATUS_IS_OK(status)) {
475 TALLOC_FREE(orig_lcomp);
476 return NULL;
478 return orig_lcomp;
482 * Deal with the SMB1 semantics of sending a pathname with a
483 * wildcard as the terminal component for a SMB1search or
484 * trans2 findfirst.
487 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
488 connection_struct *conn,
489 char *name_in,
490 uint32_t ucf_flags,
491 struct files_struct **_dirfsp,
492 struct smb_filename **_smb_fname_out,
493 char **_mask_out)
495 NTSTATUS status;
496 char *p = NULL;
497 char *mask = NULL;
498 struct smb_filename *smb_fname = NULL;
499 NTTIME twrp = 0;
501 *_smb_fname_out = NULL;
502 *_dirfsp = NULL;
503 *_mask_out = NULL;
505 DBG_DEBUG("name_in: %s\n", name_in);
507 if (ucf_flags & UCF_GMT_PATHNAME) {
508 extract_snapshot_token(name_in, &twrp);
509 ucf_flags &= ~UCF_GMT_PATHNAME;
512 if (ucf_flags & UCF_DFS_PATHNAME) {
514 * We've been given a raw DFS pathname.
516 char *pathname = NULL;
517 DBG_DEBUG("Before dfs_filename_convert name_in: %s\n", name_in);
518 status = dfs_filename_convert(ctx,
519 conn,
520 ucf_flags,
521 name_in,
522 &pathname);
523 if (!NT_STATUS_IS_OK(status)) {
524 DBG_DEBUG("dfs_filename_convert "
525 "failed for name %s with %s\n",
526 name_in,
527 nt_errstr(status));
528 return status;
530 ucf_flags &= ~UCF_DFS_PATHNAME;
531 name_in = pathname;
532 DBG_DEBUG("After dfs_filename_convert name_in: %s\n", name_in);
535 /* Get the original lcomp. */
536 mask = get_original_lcomp(ctx,
537 conn,
538 name_in,
539 ucf_flags);
540 if (mask == NULL) {
541 return NT_STATUS_NO_MEMORY;
544 if (mask[0] == '\0') {
545 /* Windows and OS/2 systems treat search on the root as * */
546 TALLOC_FREE(mask);
547 mask = talloc_strdup(ctx, "*");
548 if (mask == NULL) {
549 return NT_STATUS_NO_MEMORY;
553 DBG_DEBUG("mask = %s\n", mask);
556 * Remove the terminal component so
557 * filename_convert_dirfsp never sees the mask.
559 p = strrchr_m(name_in,'/');
560 if (p == NULL) {
561 /* filename_convert_dirfsp handles a '\0' name. */
562 name_in[0] = '\0';
563 } else {
564 *p = '\0';
567 DBG_DEBUG("For filename_convert_dirfsp: name_in = %s\n",
568 name_in);
570 /* Convert the parent directory path. */
571 status = filename_convert_dirfsp(ctx,
572 conn,
573 name_in,
574 ucf_flags,
575 twrp,
576 _dirfsp,
577 &smb_fname);
579 if (!NT_STATUS_IS_OK(status)) {
580 DBG_DEBUG("filename_convert error for %s: %s\n",
581 name_in,
582 nt_errstr(status));
585 *_smb_fname_out = talloc_move(ctx, &smb_fname);
586 *_mask_out = talloc_move(ctx, &mask);
588 return status;
592 * Get the correct capitalized stream name hanging off
593 * base_fsp. Equivalent of get_real_filename(), but for streams.
595 static NTSTATUS get_real_stream_name(
596 TALLOC_CTX *mem_ctx,
597 struct files_struct *base_fsp,
598 const char *stream_name,
599 char **_found)
601 unsigned int i, num_streams = 0;
602 struct stream_struct *streams = NULL;
603 NTSTATUS status;
605 status = vfs_fstreaminfo(
606 base_fsp, talloc_tos(), &num_streams, &streams);
607 if (!NT_STATUS_IS_OK(status)) {
608 return status;
611 for (i=0; i<num_streams; i++) {
612 bool equal = sname_equal(stream_name, streams[i].name, false);
614 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
615 stream_name,
616 streams[i].name,
617 equal ? "" : "not ");
619 if (equal) {
620 *_found = talloc_move(mem_ctx, &streams[i].name);
621 TALLOC_FREE(streams);
622 return NT_STATUS_OK;
626 TALLOC_FREE(streams);
627 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
630 static bool filename_split_lcomp(
631 TALLOC_CTX *mem_ctx,
632 const char *name_in,
633 bool posix,
634 char **_dirname,
635 const char **_fname_rel,
636 const char **_streamname)
638 const char *lcomp = NULL;
639 const char *fname_rel = NULL;
640 const char *streamname = NULL;
641 char *dirname = NULL;
643 if (name_in[0] == '\0') {
644 fname_rel = ".";
645 dirname = talloc_strdup(mem_ctx, "");
646 if (dirname == NULL) {
647 return false;
649 goto done;
652 lcomp = strrchr_m(name_in, '/');
653 if (lcomp != NULL) {
654 fname_rel = lcomp+1;
655 dirname = talloc_strndup(mem_ctx, name_in, lcomp - name_in);
656 if (dirname == NULL) {
657 return false;
659 goto find_stream;
663 * No slash, dir is emtpy
665 dirname = talloc_strdup(mem_ctx, "");
666 if (dirname == NULL) {
667 return false;
670 if (!posix && (name_in[0] == ':')) {
672 * Special case for stream on root directory
674 fname_rel = ".";
675 streamname = name_in;
676 goto done;
679 fname_rel = name_in;
681 find_stream:
682 if (!posix) {
683 streamname = strchr_m(fname_rel, ':');
685 if (streamname != NULL) {
686 fname_rel = talloc_strndup(
687 mem_ctx,
688 fname_rel,
689 streamname - fname_rel);
690 if (fname_rel == NULL) {
691 TALLOC_FREE(dirname);
692 return false;
697 done:
698 *_dirname = dirname;
699 *_fname_rel = fname_rel;
700 *_streamname = streamname;
701 return true;
705 * Create the correct capitalization of a file name to be created.
707 static NTSTATUS filename_convert_normalize_new(
708 TALLOC_CTX *mem_ctx,
709 struct connection_struct *conn,
710 char *name_in,
711 char **_normalized)
713 char *name = name_in;
715 *_normalized = NULL;
717 if (!conn->case_preserve ||
718 (mangle_is_8_3(name, false,
719 conn->params) &&
720 !conn->short_case_preserve)) {
722 char *normalized = talloc_strdup(mem_ctx, name);
723 if (normalized == NULL) {
724 return NT_STATUS_NO_MEMORY;
727 strnorm(normalized, lp_default_case(SNUM(conn)));
728 name = normalized;
731 if (mangle_is_mangled(name, conn->params)) {
732 bool found;
733 char *unmangled = NULL;
735 found = mangle_lookup_name_from_8_3(
736 mem_ctx, name, &unmangled, conn->params);
737 if (found) {
738 name = unmangled;
742 if (name != name_in) {
743 *_normalized = name;
746 return NT_STATUS_OK;
750 * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
751 * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
752 * the first attempt based on the filename sent by the client gives
753 * ENOENT.
755 static NTSTATUS openat_pathref_fsp_case_insensitive(
756 struct files_struct *dirfsp,
757 struct smb_filename *smb_fname_rel,
758 uint32_t ucf_flags)
760 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
761 DATA_BLOB cache_key = { .data = NULL, };
762 char *found_name = NULL;
763 NTSTATUS status;
764 bool ok;
766 SET_STAT_INVALID(smb_fname_rel->st);
768 /* Check veto files - only looks at last component. */
769 if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
770 DBG_DEBUG("veto files rejecting last component %s\n",
771 smb_fname_str_dbg(smb_fname_rel));
772 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
775 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
777 if (NT_STATUS_IS_OK(status)) {
778 return NT_STATUS_OK;
781 if (VALID_STAT(smb_fname_rel->st)) {
783 * We got an error although the object existed. Might
784 * be a symlink we don't want.
786 return status;
789 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
791 * Only retry on ENOENT
793 return status;
796 if (posix || dirfsp->conn->case_sensitive) {
798 * Only return case insensitive if required
800 return status;
803 if (lp_stat_cache()) {
804 char *base_name = smb_fname_rel->base_name;
805 DATA_BLOB value = { .data = NULL };
807 ok = get_real_filename_cache_key(
808 talloc_tos(), dirfsp, base_name, &cache_key);
809 if (!ok) {
811 * probably ENOMEM, just bail
813 return status;
816 DO_PROFILE_INC(statcache_lookups);
818 ok = memcache_lookup(
819 NULL, GETREALFILENAME_CACHE, cache_key, &value);
820 if (!ok) {
821 DO_PROFILE_INC(statcache_misses);
822 goto lookup;
824 DO_PROFILE_INC(statcache_hits);
826 TALLOC_FREE(smb_fname_rel->base_name);
827 smb_fname_rel->base_name = talloc_memdup(
828 smb_fname_rel, value.data, value.length);
829 if (smb_fname_rel->base_name == NULL) {
830 TALLOC_FREE(cache_key.data);
831 return NT_STATUS_NO_MEMORY;
834 if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
835 DBG_DEBUG("veto files rejecting last component %s\n",
836 smb_fname_str_dbg(smb_fname_rel));
837 TALLOC_FREE(cache_key.data);
838 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
841 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
842 if (NT_STATUS_IS_OK(status)) {
843 TALLOC_FREE(cache_key.data);
844 return NT_STATUS_OK;
847 memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
850 lookup:
851 status = get_real_filename_at(
852 dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
853 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
854 (ucf_flags & UCF_PREP_CREATEFILE)) {
856 * dropbox
858 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
861 if (NT_STATUS_IS_OK(status)) {
862 TALLOC_FREE(smb_fname_rel->base_name);
863 smb_fname_rel->base_name = found_name;
865 if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
866 DBG_DEBUG("veto files rejecting last component %s\n",
867 smb_fname_str_dbg(smb_fname_rel));
868 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
871 status = openat_pathref_fsp(dirfsp, smb_fname_rel);
874 if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
875 DATA_BLOB value = {
876 .data = (uint8_t *)smb_fname_rel->base_name,
877 .length = strlen(smb_fname_rel->base_name) + 1,
880 memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
883 TALLOC_FREE(cache_key.data);
885 return status;
888 static const char *previous_slash(const char *name_in, const char *slash)
890 const char *prev = name_in;
892 while (true) {
893 const char *next = strchr_m(prev, '/');
895 SMB_ASSERT(next != NULL); /* we have at least one slash */
897 if (next == slash) {
898 break;
901 prev = next+1;
904 if (prev == name_in) {
905 /* no previous slash */
906 return NULL;
909 return prev;
912 static char *symlink_target_path(
913 TALLOC_CTX *mem_ctx,
914 const char *name_in,
915 const char *substitute,
916 size_t unparsed)
918 size_t name_in_len = strlen(name_in);
919 const char *p_unparsed = NULL;
920 const char *parent = NULL;
921 char *ret;
923 SMB_ASSERT(unparsed <= name_in_len);
925 p_unparsed = name_in + (name_in_len - unparsed);
927 if (substitute[0] == '/') {
928 ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed);
929 return ret;
932 if (unparsed == 0) {
933 parent = strrchr_m(name_in, '/');
934 } else {
935 parent = previous_slash(name_in, p_unparsed);
938 if (parent == NULL) {
939 /* no previous slash */
940 parent = name_in;
943 ret = talloc_asprintf(
944 mem_ctx,
945 "%.*s%s%s",
946 (int)(parent - name_in),
947 name_in,
948 substitute,
949 p_unparsed);
950 return ret;
953 static NTSTATUS safe_symlink_target_path(
954 TALLOC_CTX *mem_ctx,
955 const char *connectpath,
956 const char *name_in,
957 const char *substitute,
958 size_t unparsed,
959 char **_name_out)
961 char *target = NULL;
962 char *abs_target = NULL;
963 char *abs_target_canon = NULL;
964 const char *relative = NULL;
965 char *name_out = NULL;
966 NTSTATUS status = NT_STATUS_NO_MEMORY;
967 bool in_share;
969 target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
970 if (target == NULL) {
971 goto fail;
974 DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
975 name_in,
976 substitute,
977 unparsed,
978 target);
980 if (target[0] == '/') {
981 abs_target = target;
982 } else {
983 abs_target = talloc_asprintf(
984 target, "%s/%s", connectpath, target);
985 if (abs_target == NULL) {
986 goto fail;
990 abs_target_canon = canonicalize_absolute_path(target, abs_target);
991 if (abs_target_canon == NULL) {
992 goto fail;
995 DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
997 in_share = subdir_of(
998 connectpath, strlen(connectpath), abs_target_canon, &relative);
999 if (!in_share) {
1000 DBG_DEBUG("wide link to %s\n", abs_target_canon);
1001 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1002 goto fail;
1005 name_out = talloc_strdup(mem_ctx, relative);
1006 if (name_out == NULL) {
1007 goto fail;
1010 status = NT_STATUS_OK;
1011 *_name_out = name_out;
1012 fail:
1013 TALLOC_FREE(target);
1014 return status;
1018 * Split up name_in as sent by the client into a directory pathref fsp
1019 * and a relative smb_filename.
1021 static NTSTATUS filename_convert_dirfsp_nosymlink(
1022 TALLOC_CTX *mem_ctx,
1023 connection_struct *conn,
1024 const char *name_in,
1025 uint32_t ucf_flags,
1026 NTTIME twrp,
1027 struct files_struct **_dirfsp,
1028 struct smb_filename **_smb_fname,
1029 char **_substitute,
1030 size_t *_unparsed)
1032 struct smb_filename *smb_dirname = NULL;
1033 struct smb_filename *smb_fname_rel = NULL;
1034 struct smb_filename *smb_fname = NULL;
1035 const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
1036 char *dirname = NULL;
1037 const char *fname_rel = NULL;
1038 const char *streamname = NULL;
1039 char *saved_streamname = NULL;
1040 struct files_struct *base_fsp = NULL;
1041 bool ok;
1042 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1044 if (ucf_flags & UCF_DFS_PATHNAME) {
1046 * We've been given a raw DFS pathname.
1048 char *pathname = NULL;
1049 DBG_DEBUG("Before dfs_filename_convert name_in: %s\n",
1050 name_in);
1051 status = dfs_filename_convert(mem_ctx,
1052 conn,
1053 ucf_flags,
1054 name_in,
1055 &pathname);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 DBG_DEBUG("dfs_filename_convert "
1058 "failed for name %s with %s\n",
1059 name_in,
1060 nt_errstr(status));
1061 return status;
1063 ucf_flags &= ~UCF_DFS_PATHNAME;
1064 name_in = pathname;
1065 DBG_DEBUG("After dfs_filename_convert name_in: %s\n",
1066 name_in);
1069 if (is_fake_file_path(name_in)) {
1070 smb_fname = synthetic_smb_fname_split(mem_ctx, name_in, posix);
1071 if (smb_fname == NULL) {
1072 return NT_STATUS_NO_MEMORY;
1074 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
1075 smb_fname->st.st_ex_btime =
1076 (struct timespec){0, SAMBA_UTIME_OMIT};
1077 smb_fname->st.st_ex_atime =
1078 (struct timespec){0, SAMBA_UTIME_OMIT};
1079 smb_fname->st.st_ex_mtime =
1080 (struct timespec){0, SAMBA_UTIME_OMIT};
1081 smb_fname->st.st_ex_ctime =
1082 (struct timespec){0, SAMBA_UTIME_OMIT};
1084 *_dirfsp = conn->cwd_fsp;
1085 *_smb_fname = smb_fname;
1086 return NT_STATUS_OK;
1090 * Catch an invalid path of "." before we
1091 * call filename_split_lcomp(). We need to
1092 * do this as filename_split_lcomp() will
1093 * use "." for the missing relative component
1094 * when an empty name_in path is sent by
1095 * the client.
1097 if (ISDOT(name_in)) {
1098 status = NT_STATUS_OBJECT_NAME_INVALID;
1099 goto fail;
1102 ok = filename_split_lcomp(
1103 talloc_tos(),
1104 name_in,
1105 posix,
1106 &dirname,
1107 &fname_rel,
1108 &streamname);
1109 if (!ok) {
1110 status = NT_STATUS_NO_MEMORY;
1111 goto fail;
1114 if ((streamname != NULL) &&
1115 ((conn->fs_capabilities & FILE_NAMED_STREAMS) == 0)) {
1116 status = NT_STATUS_OBJECT_NAME_INVALID;
1117 goto fail;
1120 if (!posix) {
1121 bool name_has_wild = ms_has_wild(dirname);
1122 name_has_wild |= ms_has_wild(fname_rel);
1123 if (name_has_wild) {
1124 status = NT_STATUS_OBJECT_NAME_INVALID;
1125 goto fail;
1129 if (dirname[0] == '\0') {
1130 status = synthetic_pathref(
1131 mem_ctx,
1132 conn->cwd_fsp,
1133 ".",
1134 NULL,
1135 NULL,
1137 posix ? SMB_FILENAME_POSIX_PATH : 0,
1138 &smb_dirname);
1139 } else {
1140 char *substitute = NULL;
1141 size_t unparsed = 0;
1143 status = openat_pathref_dirfsp_nosymlink(
1144 mem_ctx,
1145 conn,
1146 dirname,
1148 &smb_dirname,
1149 &unparsed,
1150 &substitute);
1152 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1154 size_t name_in_len = strlen(name_in);
1155 size_t dirname_len = strlen(dirname);
1157 SMB_ASSERT(name_in_len >= dirname_len);
1159 *_substitute = substitute;
1160 *_unparsed = unparsed + (name_in_len - dirname_len);
1162 goto fail;
1166 if (!NT_STATUS_IS_OK(status)) {
1167 DBG_DEBUG("opening directory %s failed: %s\n",
1168 dirname,
1169 nt_errstr(status));
1170 TALLOC_FREE(dirname);
1172 if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
1173 /* MS-DFS error must propagate back out. */
1174 goto fail;
1177 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1179 * Except ACCESS_DENIED, everything else leads
1180 * to PATH_NOT_FOUND.
1182 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1185 goto fail;
1188 if (!VALID_STAT_OF_DIR(smb_dirname->st)) {
1189 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1190 goto fail;
1194 * Only look at bad last component values
1195 * once we know we have a valid directory. That
1196 * way we won't confuse error messages from
1197 * opening the directory path with error
1198 * messages from a bad last component.
1201 /* Relative filename can't be empty */
1202 if (fname_rel[0] == '\0') {
1203 status = NT_STATUS_OBJECT_NAME_INVALID;
1204 goto fail;
1207 /* Relative filename can't be ".." */
1208 if (ISDOTDOT(fname_rel)) {
1209 status = NT_STATUS_OBJECT_NAME_INVALID;
1210 goto fail;
1212 /* Relative name can only be dot if directory is empty. */
1213 if (ISDOT(fname_rel) && dirname[0] != '\0') {
1214 status = NT_STATUS_OBJECT_NAME_INVALID;
1215 goto fail;
1218 TALLOC_FREE(dirname);
1220 smb_fname_rel = synthetic_smb_fname(
1221 mem_ctx,
1222 fname_rel,
1223 streamname,
1224 NULL,
1225 twrp,
1226 posix ? SMB_FILENAME_POSIX_PATH : 0);
1227 if (smb_fname_rel == NULL) {
1228 status = NT_STATUS_NO_MEMORY;
1229 goto fail;
1232 if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
1233 is_named_stream(smb_fname_rel)) {
1235 * Find the base_fsp first without the stream.
1237 saved_streamname = smb_fname_rel->stream_name;
1238 smb_fname_rel->stream_name = NULL;
1241 status = normalize_filename_case(
1242 conn, smb_fname_rel->base_name, ucf_flags);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 DBG_ERR("normalize_filename_case %s failed: %s\n",
1245 smb_fname_rel->base_name,
1246 nt_errstr(status));
1247 goto fail;
1250 status = openat_pathref_fsp_case_insensitive(
1251 smb_dirname->fsp, smb_fname_rel, ucf_flags);
1253 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1255 char *normalized = NULL;
1257 if (VALID_STAT(smb_fname_rel->st)) {
1259 * If we're on an MSDFS share, see if this is
1260 * an MSDFS link.
1262 if (lp_host_msdfs() &&
1263 lp_msdfs_root(SNUM(conn)) &&
1264 S_ISLNK(smb_fname_rel->st.st_ex_mode) &&
1265 is_msdfs_link(smb_dirname->fsp, smb_fname_rel))
1267 status = NT_STATUS_PATH_NOT_COVERED;
1268 goto fail;
1271 #if defined(WITH_SMB1SERVER)
1273 * In SMB1 posix mode, if this is a symlink,
1274 * allow access to the name with a NULL smb_fname->fsp.
1276 if (!conn->sconn->using_smb2 &&
1277 posix &&
1278 S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
1279 SMB_ASSERT(smb_fname_rel->fsp == NULL);
1280 SMB_ASSERT(streamname == NULL);
1282 smb_fname = full_path_from_dirfsp_atname(
1283 mem_ctx,
1284 smb_dirname->fsp,
1285 smb_fname_rel);
1286 if (smb_fname == NULL) {
1287 status = NT_STATUS_NO_MEMORY;
1288 goto fail;
1290 goto done;
1292 #endif
1294 * NT_STATUS_OBJECT_NAME_NOT_FOUND is
1295 * misleading: The object exists but might be
1296 * a symlink pointing outside the share.
1298 goto fail;
1302 * Creating a new file
1305 status = filename_convert_normalize_new(
1306 smb_fname_rel,
1307 conn,
1308 smb_fname_rel->base_name,
1309 &normalized);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 DBG_DEBUG("filename_convert_normalize_new failed: "
1312 "%s\n",
1313 nt_errstr(status));
1314 goto fail;
1316 if (normalized != NULL) {
1317 smb_fname_rel->base_name = normalized;
1320 smb_fname_rel->stream_name = saved_streamname;
1322 smb_fname = full_path_from_dirfsp_atname(
1323 mem_ctx, smb_dirname->fsp, smb_fname_rel);
1324 if (smb_fname == NULL) {
1325 status = NT_STATUS_NO_MEMORY;
1326 goto fail;
1328 goto done;
1331 if (!NT_STATUS_IS_OK(status)) {
1332 goto fail;
1335 if (saved_streamname == NULL) {
1336 /* smb_fname must be allocated off mem_ctx. */
1337 smb_fname = cp_smb_filename(mem_ctx,
1338 smb_fname_rel->fsp->fsp_name);
1339 if (smb_fname == NULL) {
1340 goto fail;
1342 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 goto fail;
1346 goto done;
1349 base_fsp = smb_fname_rel->fsp;
1350 smb_fname_fsp_unlink(smb_fname_rel);
1351 SET_STAT_INVALID(smb_fname_rel->st);
1353 smb_fname_rel->stream_name = saved_streamname;
1355 status = open_stream_pathref_fsp(&base_fsp, smb_fname_rel);
1357 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
1358 !conn->case_sensitive) {
1359 char *found = NULL;
1361 status = get_real_stream_name(
1362 smb_fname_rel,
1363 base_fsp,
1364 smb_fname_rel->stream_name,
1365 &found);
1367 if (NT_STATUS_IS_OK(status)) {
1368 smb_fname_rel->stream_name = found;
1369 found = NULL;
1370 status = open_stream_pathref_fsp(
1371 &base_fsp, smb_fname_rel);
1375 if (NT_STATUS_IS_OK(status)) {
1376 /* smb_fname must be allocated off mem_ctx. */
1377 smb_fname = cp_smb_filename(mem_ctx,
1378 smb_fname_rel->fsp->fsp_name);
1379 if (smb_fname == NULL) {
1380 goto fail;
1382 status = move_smb_fname_fsp_link(smb_fname, smb_fname_rel);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 goto fail;
1386 goto done;
1389 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1391 * Creating a new stream
1393 * We should save the already-open base fsp for
1394 * create_file_unixpath() somehow.
1396 smb_fname = full_path_from_dirfsp_atname(
1397 mem_ctx, smb_dirname->fsp, smb_fname_rel);
1398 if (smb_fname == NULL) {
1399 status = NT_STATUS_NO_MEMORY;
1400 goto fail;
1402 goto done;
1405 if (!NT_STATUS_IS_OK(status)) {
1406 goto fail;
1409 done:
1410 *_dirfsp = smb_dirname->fsp;
1411 *_smb_fname = smb_fname;
1413 smb_fname_fsp_unlink(smb_fname_rel);
1414 TALLOC_FREE(smb_fname_rel);
1415 return NT_STATUS_OK;
1417 fail:
1418 TALLOC_FREE(dirname);
1419 TALLOC_FREE(smb_dirname);
1420 TALLOC_FREE(smb_fname_rel);
1421 return status;
1424 NTSTATUS filename_convert_dirfsp(
1425 TALLOC_CTX *mem_ctx,
1426 connection_struct *conn,
1427 const char *name_in,
1428 uint32_t ucf_flags,
1429 NTTIME twrp,
1430 struct files_struct **_dirfsp,
1431 struct smb_filename **_smb_fname)
1433 char *substitute = NULL;
1434 size_t unparsed = 0;
1435 NTSTATUS status;
1436 char *target = NULL;
1437 size_t symlink_redirects = 0;
1439 next:
1440 if (symlink_redirects > 40) {
1441 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1444 status = filename_convert_dirfsp_nosymlink(
1445 mem_ctx,
1446 conn,
1447 name_in,
1448 ucf_flags,
1449 twrp,
1450 _dirfsp,
1451 _smb_fname,
1452 &substitute,
1453 &unparsed);
1455 if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1456 return status;
1459 if (!lp_follow_symlinks(SNUM(conn))) {
1460 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1464 * Right now, SMB2 and SMB1 always traverse symlinks
1465 * within the share. SMB1+POSIX traverses non-terminal
1466 * symlinks within the share.
1468 * When we add SMB2+POSIX we need to return
1469 * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
1470 * symlink target data read below if SMB2+POSIX has
1471 * UCF_POSIX_PATHNAMES set to cause the client to
1472 * resolve all symlinks locally.
1475 status = safe_symlink_target_path(
1476 mem_ctx,
1477 conn->connectpath,
1478 name_in,
1479 substitute,
1480 unparsed,
1481 &target);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 return status;
1485 name_in = target;
1487 symlink_redirects += 1;
1489 goto next;
1493 * Build the full path from a dirfsp and dirfsp relative name
1495 struct smb_filename *full_path_from_dirfsp_atname(
1496 TALLOC_CTX *mem_ctx,
1497 const struct files_struct *dirfsp,
1498 const struct smb_filename *atname)
1500 struct smb_filename *fname = NULL;
1501 char *path = NULL;
1503 if (dirfsp == dirfsp->conn->cwd_fsp ||
1504 ISDOT(dirfsp->fsp_name->base_name) ||
1505 atname->base_name[0] == '/')
1507 path = talloc_strdup(mem_ctx, atname->base_name);
1508 } else {
1509 path = talloc_asprintf(mem_ctx, "%s/%s",
1510 dirfsp->fsp_name->base_name,
1511 atname->base_name);
1513 if (path == NULL) {
1514 return NULL;
1517 fname = synthetic_smb_fname(mem_ctx,
1518 path,
1519 atname->stream_name,
1520 &atname->st,
1521 atname->twrp,
1522 atname->flags);
1523 TALLOC_FREE(path);
1524 if (fname == NULL) {
1525 return NULL;
1528 return fname;