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.
28 #include "system/filesys.h"
29 #include "fake_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
33 uint32_t filename_create_ucf_flags(struct smb_request
*req
, uint32_t create_disposition
)
35 uint32_t ucf_flags
= 0;
37 if (req
!= NULL
&& req
->posix_pathnames
) {
38 ucf_flags
|= UCF_POSIX_PATHNAMES
;
41 switch (create_disposition
) {
48 case FILE_OVERWRITE_IF
:
49 ucf_flags
|= UCF_PREP_CREATEFILE
;
56 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
57 connection_struct
*conn
,
58 struct smb_filename
*smb_fname
);
60 /****************************************************************************
61 Mangle the 2nd name and check if it is then equal to the first name.
62 ****************************************************************************/
64 static bool mangled_equal(const char *name1
,
66 const struct share_params
*p
)
70 if (!name_to_8_3(name2
, mname
, False
, p
)) {
73 return strequal(name1
, mname
);
76 /****************************************************************************
77 Cope with the differing wildcard and non-wildcard error cases.
78 ****************************************************************************/
80 static NTSTATUS
determine_path_error(const char *name
,
81 bool allow_wcard_last_component
,
85 bool name_has_wild
= false;
87 if (!allow_wcard_last_component
) {
88 /* Error code within a pathname. */
89 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
92 /* We're terminating here so we
93 * can be a little slower and get
94 * the error code right. Windows
95 * treats the last part of the pathname
96 * separately I think, so if the last
97 * component is a wildcard then we treat
98 * this ./ as "end of component" */
100 p
= strchr(name
, '/');
102 if (!posix_pathnames
) {
103 name_has_wild
= ms_has_wild(name
);
106 if (!p
&& (name_has_wild
|| ISDOT(name
))) {
107 /* Error code at the end of a pathname. */
108 return NT_STATUS_OBJECT_NAME_INVALID
;
110 /* Error code within a pathname. */
111 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
115 static NTSTATUS
check_for_dot_component(const struct smb_filename
*smb_fname
)
117 /* Ensure we catch all names with in "/."
118 this is disallowed under Windows and
119 in POSIX they've already been removed. */
120 const char *p
= strstr(smb_fname
->base_name
, "/."); /*mb safe*/
123 /* Error code within a pathname. */
124 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
125 } else if (p
[2] == '\0') {
126 /* Error code at the end of a pathname. */
127 return NT_STATUS_OBJECT_NAME_INVALID
;
133 /****************************************************************************
134 Optimization for common case where the missing part
135 is in the last component and the client already
136 sent the correct case.
137 Returns NT_STATUS_OK to mean continue the tree walk
138 (possibly with modified start pointer).
139 Any other NT_STATUS_XXX error means terminate the path
141 ****************************************************************************/
143 static NTSTATUS
check_parent_exists(TALLOC_CTX
*ctx
,
144 connection_struct
*conn
,
145 bool posix_pathnames
,
146 const struct smb_filename
*smb_fname
,
150 struct smb_filename parent_fname
;
151 const char *last_component
= NULL
;
154 bool parent_fname_has_wild
= false;
156 ZERO_STRUCT(parent_fname
);
157 if (!parent_dirname(ctx
, smb_fname
->base_name
,
158 &parent_fname
.base_name
,
160 return NT_STATUS_NO_MEMORY
;
163 if (!posix_pathnames
) {
164 parent_fname_has_wild
= ms_has_wild(parent_fname
.base_name
);
168 * If there was no parent component in
169 * smb_fname->base_name of the parent name
170 * contained a wildcard then don't do this
173 if ((smb_fname
->base_name
== last_component
) ||
174 parent_fname_has_wild
) {
178 if (posix_pathnames
) {
179 ret
= SMB_VFS_LSTAT(conn
, &parent_fname
);
181 ret
= SMB_VFS_STAT(conn
, &parent_fname
);
184 /* If the parent stat failed, just continue
185 with the normal tree walk. */
191 status
= check_for_dot_component(&parent_fname
);
192 if (!NT_STATUS_IS_OK(status
)) {
196 /* Parent exists - set "start" to be the
197 * last component to shorten the tree walk. */
200 * Safe to use discard_const_p
201 * here as last_component points
202 * into our smb_fname->base_name.
204 *pp_start
= discard_const_p(char, last_component
);
206 /* Update dirpath. */
207 TALLOC_FREE(*pp_dirpath
);
208 *pp_dirpath
= talloc_strdup(ctx
, parent_fname
.base_name
);
210 return NT_STATUS_NO_MEMORY
;
213 DEBUG(5,("check_parent_exists: name "
214 "= %s, dirpath = %s, "
216 smb_fname
->base_name
,
224 * Re-order a known good @GMT-token path.
227 static NTSTATUS
rearrange_snapshot_path(struct smb_filename
*smb_fname
,
232 size_t gmt_len
= endp
- startp
;
233 char gmt_store
[gmt_len
+ 1];
235 const char *last_component
= NULL
;
239 DBG_DEBUG("|%s| -> ", smb_fname
->base_name
);
241 /* Save off the @GMT-token. */
242 memcpy(gmt_store
, startp
, gmt_len
);
243 gmt_store
[gmt_len
] = '\0';
246 /* Remove any trailing '/' */
252 * @GMT-token was at end of path.
253 * Remove any preceeding '/'
255 if (startp
> smb_fname
->base_name
&& startp
[-1] == '/') {
260 /* Remove @GMT-token from the path. */
261 endlen
= strlen(endp
);
262 memmove(startp
, endp
, endlen
+ 1);
264 /* Split the remaining path into components. */
265 ret
= parent_dirname(smb_fname
,
266 smb_fname
->base_name
,
270 /* Must terminate debug with \n */
271 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
272 return NT_STATUS_NO_MEMORY
;
276 if (last_component
[0] == '\0') {
277 newstr
= talloc_strdup(smb_fname
,
280 newstr
= talloc_asprintf(smb_fname
,
286 newstr
= talloc_asprintf(smb_fname
,
294 TALLOC_FREE(smb_fname
->base_name
);
295 smb_fname
->base_name
= newstr
;
297 DBG_DEBUG("|%s|\n", newstr
);
303 * Canonicalize any incoming pathname potentially containining
304 * a @GMT-token into a path that looks like:
306 * @GMT-YYYY-MM-DD-HH-MM-SS/path/name/components/last_component
308 * Leaves single path @GMT-token -component alone:
310 * @GMT-YYYY-MM-DD-HH-MM-SS -> @GMT-YYYY-MM-DD-HH-MM-SS
312 * Eventually when struct smb_filename is updated and the VFS
313 * ABI is changed this will remove the @GMT-YYYY-MM-DD-HH-MM-SS
314 * and store in the struct smb_filename as a struct timeval field
318 static NTSTATUS
canonicalize_snapshot_path(struct smb_filename
*smb_fname
)
320 char *startp
= strchr_m(smb_fname
->base_name
, '@');
324 if (startp
== NULL
) {
329 startp
= strstr_m(startp
, "@GMT-");
330 if (startp
== NULL
) {
335 if ((startp
> smb_fname
->base_name
) && (startp
[-1] != '/')) {
336 /* the GMT-token does not start a path-component */
340 endp
= strptime(startp
, GMT_FORMAT
, &tm
);
342 /* Not a valid timestring. */
346 if ( endp
[0] == '\0') {
347 return rearrange_snapshot_path(smb_fname
,
352 if (endp
[0] != '/') {
354 * It is not a complete path component, i.e. the path
355 * component continues after the gmt-token.
360 return rearrange_snapshot_path(smb_fname
,
365 /****************************************************************************
366 This routine is called to convert names from the dos namespace to unix
367 namespace. It needs to handle any case conversions, mangling, format changes,
370 We assume that we have already done a chdir() to the right "root" directory
373 The function will return an NTSTATUS error if some part of the name except for
374 the last part cannot be resolved, else NT_STATUS_OK.
376 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
377 didn't get any fatal errors that should immediately terminate the calling SMB
378 processing whilst resolving.
380 If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
381 of the pathname is set in smb_filename->original_lcomp.
383 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
384 and should be allowed in the last component of the path only.
386 If the orig_path was a stream, smb_filename->base_name will point to the base
387 filename, and smb_filename->stream_name will point to the stream name. If
388 orig_path was not a stream, then smb_filename->stream_name will be NULL.
390 On exit from unix_convert, the smb_filename->st stat struct will be populated
391 if the file exists and was found, if not this stat struct will be filled with
392 zeros (and this can be detected by checking for nlinks = 0, which can never be
394 ****************************************************************************/
396 NTSTATUS
unix_convert(TALLOC_CTX
*ctx
,
397 connection_struct
*conn
,
398 const char *orig_path
,
399 struct smb_filename
**smb_fname_out
,
402 struct smb_filename
*smb_fname
= NULL
;
405 * This looks strange. But we need "start" initialized to "" here but
406 * it can't be a const char *, so 'char *start = "";' does not work.
409 char *start
= &cnull
;
412 char *dirpath
= NULL
;
414 bool component_was_mangled
= False
;
415 bool name_has_wildcard
= False
;
416 bool posix_pathnames
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
417 bool allow_wcard_last_component
=
418 (ucf_flags
& UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
419 bool save_last_component
= ucf_flags
& UCF_SAVE_LCOMP
;
423 *smb_fname_out
= NULL
;
425 smb_fname
= talloc_zero(ctx
, struct smb_filename
);
426 if (smb_fname
== NULL
) {
427 return NT_STATUS_NO_MEMORY
;
431 /* we don't ever use the filenames on a printer share as a
432 filename - so don't convert them */
433 if (!(smb_fname
->base_name
= talloc_strdup(smb_fname
,
435 status
= NT_STATUS_NO_MEMORY
;
441 smb_fname
->flags
= posix_pathnames
? SMB_FILENAME_POSIX_PATH
: 0;
443 DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path
));
446 * Conversion to basic unix format is already done in
447 * check_path_syntax().
451 * Names must be relative to the root of the service - any leading /.
452 * and trailing /'s should have been trimmed by check_path_syntax().
456 SMB_ASSERT(*orig_path
!= '/');
460 * If we trimmed down to a single '\0' character
461 * then we should use the "." directory to avoid
462 * searching the cache, but not if we are in a
464 * As we know this is valid we can return true here.
468 if (!(smb_fname
->base_name
= talloc_strdup(smb_fname
, "."))) {
469 status
= NT_STATUS_NO_MEMORY
;
472 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
473 status
= map_nt_error_from_unix(errno
);
476 DEBUG(5, ("conversion finished \"\" -> %s\n",
477 smb_fname
->base_name
));
481 if (orig_path
[0] == '.' && (orig_path
[1] == '/' ||
482 orig_path
[1] == '\0')) {
483 /* Start of pathname can't be "." only. */
484 if (orig_path
[1] == '\0' || orig_path
[2] == '\0') {
485 status
= NT_STATUS_OBJECT_NAME_INVALID
;
487 status
=determine_path_error(&orig_path
[2],
488 allow_wcard_last_component
,
494 /* Start with the full orig_path as given by the caller. */
495 if (!(smb_fname
->base_name
= talloc_strdup(smb_fname
, orig_path
))) {
496 DEBUG(0, ("talloc_strdup failed\n"));
497 status
= NT_STATUS_NO_MEMORY
;
501 /* Canonicalize any @GMT- paths. */
502 if (posix_pathnames
== false) {
503 status
= canonicalize_snapshot_path(smb_fname
);
504 if (!NT_STATUS_IS_OK(status
)) {
510 * Large directory fix normalization. If we're case sensitive, and
511 * the case preserving parameters are set to "no", normalize the case of
512 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
513 * This is in conflict with the current (3.0.20) man page, but is
514 * what people expect from the "large directory howto". I'll update
515 * the man page. Thanks to jht@samba.org for finding this. JRA.
518 if (conn
->case_sensitive
&& !conn
->case_preserve
&&
519 !conn
->short_case_preserve
) {
520 if (!strnorm(smb_fname
->base_name
, lp_default_case(SNUM(conn
)))) {
521 DEBUG(0, ("strnorm %s failed\n", smb_fname
->base_name
));
522 status
= NT_STATUS_INVALID_PARAMETER
;
528 * Ensure saved_last_component is valid even if file exists.
531 if(save_last_component
) {
532 end
= strrchr_m(smb_fname
->base_name
, '/');
534 smb_fname
->original_lcomp
= talloc_strdup(smb_fname
,
537 smb_fname
->original_lcomp
=
538 talloc_strdup(smb_fname
, smb_fname
->base_name
);
540 if (smb_fname
->original_lcomp
== NULL
) {
541 status
= NT_STATUS_NO_MEMORY
;
547 * Strip off the stream, and add it back when we're done with the
550 if (!posix_pathnames
) {
551 stream
= strchr_m(smb_fname
->base_name
, ':');
553 if (stream
!= NULL
) {
554 char *tmp
= talloc_strdup(smb_fname
, stream
);
556 status
= NT_STATUS_NO_MEMORY
;
560 * Since this is actually pointing into
561 * smb_fname->base_name this truncates base_name.
566 if (smb_fname
->base_name
[0] == '\0') {
568 * orig_name was just a stream name.
569 * This is a stream on the root of
570 * the share. Replace base_name with
573 smb_fname
->base_name
=
574 talloc_strdup(smb_fname
, ".");
575 if (smb_fname
->base_name
== NULL
) {
576 status
= NT_STATUS_NO_MEMORY
;
579 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
580 status
= map_nt_error_from_unix(errno
);
583 /* dirpath must exist. */
584 dirpath
= talloc_strdup(ctx
,"");
585 if (dirpath
== NULL
) {
586 status
= NT_STATUS_NO_MEMORY
;
589 DEBUG(5, ("conversion finished %s -> %s\n",
591 smb_fname
->base_name
));
597 start
= smb_fname
->base_name
;
600 * If we're providing case insensitive semantics or
601 * the underlying filesystem is case insensitive,
602 * then a case-normalized hit in the stat-cache is
603 * authoratitive. JRA.
605 * Note: We're only checking base_name. The stream_name will be
606 * added and verified in build_stream_path().
609 if((!conn
->case_sensitive
|| !(conn
->fs_capabilities
&
610 FILE_CASE_SENSITIVE_SEARCH
)) &&
611 stat_cache_lookup(conn
, posix_pathnames
, &smb_fname
->base_name
, &dirpath
, &start
,
617 * Make sure "dirpath" is an allocated string, we use this for
618 * building the directories with talloc_asprintf and free it.
621 if ((dirpath
== NULL
) && (!(dirpath
= talloc_strdup(ctx
,"")))) {
622 DEBUG(0, ("talloc_strdup failed\n"));
623 status
= NT_STATUS_NO_MEMORY
;
628 * If we have a wildcard we must walk the path to
629 * find where the error is, even if case sensitive
633 if (!posix_pathnames
) {
634 /* POSIX pathnames have no wildcards. */
635 name_has_wildcard
= ms_has_wild(smb_fname
->base_name
);
636 if (name_has_wildcard
&& !allow_wcard_last_component
) {
637 /* Wildcard not valid anywhere. */
638 status
= NT_STATUS_OBJECT_NAME_INVALID
;
643 DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
644 smb_fname
->base_name
, dirpath
, start
));
646 if (!name_has_wildcard
) {
648 * stat the name - if it exists then we can add the stream back (if
649 * there was one) and be done!
652 if (posix_pathnames
) {
653 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
655 ret
= SMB_VFS_STAT(conn
, smb_fname
);
659 status
= check_for_dot_component(smb_fname
);
660 if (!NT_STATUS_IS_OK(status
)) {
663 /* Add the path (not including the stream) to the cache. */
664 stat_cache_add(orig_path
, smb_fname
->base_name
,
665 conn
->case_sensitive
);
666 DEBUG(5,("conversion of base_name finished %s -> %s\n",
667 orig_path
, smb_fname
->base_name
));
671 /* Stat failed - ensure we don't use it. */
672 SET_STAT_INVALID(smb_fname
->st
);
674 if (errno
== ENOENT
) {
675 /* Optimization when creating a new file - only
676 the last component doesn't exist.
677 NOTE : check_parent_exists() doesn't preserve errno.
679 int saved_errno
= errno
;
680 status
= check_parent_exists(ctx
,
687 if (!NT_STATUS_IS_OK(status
)) {
693 * A special case - if we don't have any wildcards or mangling chars and are case
694 * sensitive or the underlying filesystem is case insensitive then searching
698 if ((conn
->case_sensitive
|| !(conn
->fs_capabilities
&
699 FILE_CASE_SENSITIVE_SEARCH
)) &&
700 !mangle_is_mangled(smb_fname
->base_name
, conn
->params
)) {
702 status
= check_for_dot_component(smb_fname
);
703 if (!NT_STATUS_IS_OK(status
)) {
708 * The stat failed. Could be ok as it could be
712 if (errno
== ENOTDIR
|| errno
== ELOOP
) {
713 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
715 } else if (errno
== ENOENT
) {
717 * Was it a missing last component ?
718 * or a missing intermediate component ?
720 struct smb_filename parent_fname
;
721 const char *last_component
= NULL
;
723 ZERO_STRUCT(parent_fname
);
724 if (!parent_dirname(ctx
, smb_fname
->base_name
,
725 &parent_fname
.base_name
,
727 status
= NT_STATUS_NO_MEMORY
;
730 if (posix_pathnames
) {
731 ret
= SMB_VFS_LSTAT(conn
, &parent_fname
);
733 ret
= SMB_VFS_STAT(conn
, &parent_fname
);
736 if (errno
== ENOTDIR
||
739 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
745 * Missing last component is ok - new file.
746 * Also deal with permission denied elsewhere.
747 * Just drop out to done.
754 * We have a wildcard in the pathname.
756 * Optimization for common case where the wildcard
757 * is in the last component and the client already
758 * sent the correct case.
759 * NOTE : check_parent_exists() doesn't preserve errno.
761 int saved_errno
= errno
;
762 status
= check_parent_exists(ctx
,
769 if (!NT_STATUS_IS_OK(status
)) {
775 * is_mangled() was changed to look at an entire pathname, not
776 * just a component. JRA.
779 if (mangle_is_mangled(start
, conn
->params
)) {
780 component_was_mangled
= True
;
784 * Now we need to recursively match the name against the real
785 * directory structure.
789 * Match each part of the path name separately, trying the names
790 * as is first, then trying to scan the directory for matching names.
793 for (; start
; start
= (end
?end
+1:(char *)NULL
)) {
795 * Pinpoint the end of this section of the filename.
797 /* mb safe. '/' can't be in any encoded char. */
798 end
= strchr(start
, '/');
801 * Chop the name at this point.
807 if (save_last_component
) {
808 TALLOC_FREE(smb_fname
->original_lcomp
);
809 smb_fname
->original_lcomp
= talloc_strdup(smb_fname
,
810 end
? end
+ 1 : start
);
811 if (!smb_fname
->original_lcomp
) {
812 DEBUG(0, ("talloc failed\n"));
813 status
= NT_STATUS_NO_MEMORY
;
818 /* The name cannot have a component of "." */
822 /* Error code at the end of a pathname. */
823 status
= NT_STATUS_OBJECT_NAME_INVALID
;
825 status
= determine_path_error(end
+1,
826 allow_wcard_last_component
,
832 /* The name cannot have a wildcard if it's not
833 the last component. */
835 if (!posix_pathnames
) {
836 name_has_wildcard
= ms_has_wild(start
);
839 /* Wildcards never valid within a pathname. */
840 if (name_has_wildcard
&& end
) {
841 status
= NT_STATUS_OBJECT_NAME_INVALID
;
845 /* Skip the stat call if it's a wildcard end. */
846 if (name_has_wildcard
) {
847 DEBUG(5,("Wildcard %s\n",start
));
852 * Check if the name exists up to this point.
855 if (posix_pathnames
) {
856 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
858 ret
= SMB_VFS_STAT(conn
, smb_fname
);
863 * It exists. it must either be a directory or this must
864 * be the last part of the path for it to be OK.
866 if (end
&& !S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
868 * An intermediate part of the name isn't
871 DEBUG(5,("Not a dir %s\n",start
));
874 * We need to return the fact that the
875 * intermediate name resolution failed. This
876 * is used to return an error of ERRbadpath
877 * rather than ERRbadfile. Some Windows
878 * applications depend on the difference between
881 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
886 char *found_name
= NULL
;
888 /* Stat failed - ensure we don't use it. */
889 SET_STAT_INVALID(smb_fname
->st
);
892 * Reset errno so we can detect
893 * directory open errors.
898 * Try to find this part of the path in the directory.
901 if (name_has_wildcard
||
902 (get_real_filename(conn
, dirpath
, start
,
904 &found_name
) == -1)) {
909 * An intermediate part of the name
912 DEBUG(5,("Intermediate not found %s\n",
917 * We need to return the fact that the
918 * intermediate name resolution failed.
919 * This is used to return an error of
920 * ERRbadpath rather than ERRbadfile.
921 * Some Windows applications depend on
922 * the difference between these two
927 * ENOENT, ENOTDIR and ELOOP all map
928 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
929 * in the filename walk.
932 if (errno
== ENOENT
||
936 NT_STATUS_OBJECT_PATH_NOT_FOUND
;
940 map_nt_error_from_unix(errno
);
946 * ENOENT/EACCESS are the only valid errors
950 if (errno
== EACCES
) {
951 if ((ucf_flags
& UCF_PREP_CREATEFILE
) == 0) {
952 status
= NT_STATUS_ACCESS_DENIED
;
956 * This is the dropbox
957 * behaviour. A dropbox is a
958 * directory with only -wx
960 * get_real_filename fails
961 * with EACCESS, it needs to
962 * list the directory. We
963 * nevertheless want to allow
964 * users creating a file.
970 if ((errno
!= 0) && (errno
!= ENOENT
)) {
972 * ENOTDIR and ELOOP both map to
973 * NT_STATUS_OBJECT_PATH_NOT_FOUND
974 * in the filename walk.
976 if (errno
== ENOTDIR
||
979 NT_STATUS_OBJECT_PATH_NOT_FOUND
;
982 map_nt_error_from_unix(errno
);
988 * Just the last part of the name doesn't exist.
989 * We need to strupper() or strlower() it as
990 * this conversion may be used for file creation
991 * purposes. Fix inspired by
992 * Thomas Neumann <t.neumann@iku-ag.de>.
994 if (!conn
->case_preserve
||
995 (mangle_is_8_3(start
, False
,
997 !conn
->short_case_preserve
)) {
999 lp_default_case(SNUM(conn
)))) {
1000 DEBUG(0, ("strnorm %s failed\n",
1002 status
= NT_STATUS_INVALID_PARAMETER
;
1008 * check on the mangled stack to see if we can
1009 * recover the base of the filename.
1012 if (mangle_is_mangled(start
, conn
->params
)
1013 && mangle_lookup_name_from_8_3(ctx
,
1019 start
- smb_fname
->base_name
;
1021 if (*dirpath
!= '\0') {
1022 tmp
= talloc_asprintf(
1024 dirpath
, unmangled
);
1025 TALLOC_FREE(unmangled
);
1031 DEBUG(0, ("talloc failed\n"));
1032 status
= NT_STATUS_NO_MEMORY
;
1035 TALLOC_FREE(smb_fname
->base_name
);
1036 smb_fname
->base_name
= tmp
;
1038 smb_fname
->base_name
+ start_ofs
;
1039 end
= start
+ strlen(start
);
1042 DEBUG(5,("New file %s\n",start
));
1048 * Restore the rest of the string. If the string was
1049 * mangled the size may have changed.
1054 start
- smb_fname
->base_name
;
1056 if (*dirpath
!= '\0') {
1057 tmp
= talloc_asprintf(smb_fname
,
1058 "%s/%s/%s", dirpath
,
1062 tmp
= talloc_asprintf(smb_fname
,
1063 "%s/%s", found_name
,
1067 DEBUG(0, ("talloc_asprintf failed\n"));
1068 status
= NT_STATUS_NO_MEMORY
;
1071 TALLOC_FREE(smb_fname
->base_name
);
1072 smb_fname
->base_name
= tmp
;
1073 start
= smb_fname
->base_name
+ start_ofs
;
1074 end
= start
+ strlen(found_name
);
1079 start
- smb_fname
->base_name
;
1081 if (*dirpath
!= '\0') {
1082 tmp
= talloc_asprintf(smb_fname
,
1086 tmp
= talloc_strdup(smb_fname
,
1090 DEBUG(0, ("talloc failed\n"));
1091 status
= NT_STATUS_NO_MEMORY
;
1094 TALLOC_FREE(smb_fname
->base_name
);
1095 smb_fname
->base_name
= tmp
;
1096 start
= smb_fname
->base_name
+ start_ofs
;
1099 * We just scanned for, and found the end of
1100 * the path. We must return a valid stat struct
1101 * if it exists. JRA.
1104 if (posix_pathnames
) {
1105 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
1107 ret
= SMB_VFS_STAT(conn
, smb_fname
);
1111 SET_STAT_INVALID(smb_fname
->st
);
1115 TALLOC_FREE(found_name
);
1119 * Add to the dirpath that we have resolved so far.
1122 if (*dirpath
!= '\0') {
1123 char *tmp
= talloc_asprintf(ctx
,
1124 "%s/%s", dirpath
, start
);
1126 DEBUG(0, ("talloc_asprintf failed\n"));
1127 status
= NT_STATUS_NO_MEMORY
;
1130 TALLOC_FREE(dirpath
);
1134 TALLOC_FREE(dirpath
);
1135 if (!(dirpath
= talloc_strdup(ctx
,start
))) {
1136 DEBUG(0, ("talloc_strdup failed\n"));
1137 status
= NT_STATUS_NO_MEMORY
;
1143 * Cache the dirpath thus far. Don't cache a name with mangled
1144 * or wildcard components as this can change the size.
1146 if(!component_was_mangled
&& !name_has_wildcard
) {
1147 stat_cache_add(orig_path
, dirpath
,
1148 conn
->case_sensitive
);
1152 * Restore the / that we wiped out earlier.
1160 * Cache the full path. Don't cache a name with mangled or wildcard
1161 * components as this can change the size.
1164 if(!component_was_mangled
&& !name_has_wildcard
) {
1165 stat_cache_add(orig_path
, smb_fname
->base_name
,
1166 conn
->case_sensitive
);
1170 * The name has been resolved.
1173 DEBUG(5,("conversion finished %s -> %s\n", orig_path
,
1174 smb_fname
->base_name
));
1177 /* Add back the stream if one was stripped off originally. */
1178 if (stream
!= NULL
) {
1179 smb_fname
->stream_name
= stream
;
1181 /* Check path now that the base_name has been converted. */
1182 status
= build_stream_path(ctx
, conn
, smb_fname
);
1183 if (!NT_STATUS_IS_OK(status
)) {
1187 TALLOC_FREE(dirpath
);
1188 *smb_fname_out
= smb_fname
;
1189 return NT_STATUS_OK
;
1191 DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath
, start
));
1192 if (dirpath
&& *dirpath
!= '\0') {
1193 smb_fname
->base_name
= talloc_asprintf(smb_fname
, "%s/%s",
1196 smb_fname
->base_name
= talloc_strdup(smb_fname
, start
);
1198 if (!smb_fname
->base_name
) {
1199 DEBUG(0, ("talloc_asprintf failed\n"));
1200 status
= NT_STATUS_NO_MEMORY
;
1204 *smb_fname_out
= smb_fname
;
1205 TALLOC_FREE(dirpath
);
1208 TALLOC_FREE(smb_fname
);
1212 /****************************************************************************
1213 Ensure a path is not vetoed.
1214 ****************************************************************************/
1216 static NTSTATUS
check_veto_path(connection_struct
*conn
, const char *name
)
1218 if (IS_VETO_PATH(conn
, name
)) {
1219 /* Is it not dot or dot dot. */
1220 if (!(ISDOT(name
) || ISDOTDOT(name
))) {
1221 DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1223 return map_nt_error_from_unix(ENOENT
);
1226 return NT_STATUS_OK
;
1229 /****************************************************************************
1230 Check a filename - possibly calling check_reduced_name.
1231 This is called by every routine before it allows an operation on a filename.
1232 It does any final confirmation necessary to ensure that the filename is
1233 a valid one for the user to access.
1234 ****************************************************************************/
1236 NTSTATUS
check_name(connection_struct
*conn
, const char *name
)
1238 NTSTATUS status
= check_veto_path(conn
, name
);
1240 if (!NT_STATUS_IS_OK(status
)) {
1244 if (!lp_widelinks(SNUM(conn
)) || !lp_follow_symlinks(SNUM(conn
))) {
1245 status
= check_reduced_name(conn
, NULL
, name
);
1246 if (!NT_STATUS_IS_OK(status
)) {
1247 DEBUG(5,("check_name: name %s failed with %s\n",name
,
1248 nt_errstr(status
)));
1253 return NT_STATUS_OK
;
1256 /****************************************************************************
1257 Must be called as root. Creates the struct privilege_paths
1258 attached to the struct smb_request if this call is successful.
1259 ****************************************************************************/
1261 static NTSTATUS
check_name_with_privilege(connection_struct
*conn
,
1262 struct smb_request
*smbreq
,
1265 NTSTATUS status
= check_veto_path(conn
, name
);
1267 if (!NT_STATUS_IS_OK(status
)) {
1270 return check_reduced_name_with_privilege(conn
,
1275 /****************************************************************************
1276 Check if two filenames are equal.
1277 This needs to be careful about whether we are case sensitive.
1278 ****************************************************************************/
1280 static bool fname_equal(const char *name1
, const char *name2
,
1281 bool case_sensitive
)
1283 /* Normal filename handling */
1284 if (case_sensitive
) {
1285 return(strcmp(name1
,name2
) == 0);
1288 return(strequal(name1
,name2
));
1291 /****************************************************************************
1292 Scan a directory to find a filename, matching without case sensitivity.
1293 If the name looks like a mangled name then try via the mangling functions
1294 ****************************************************************************/
1296 static int get_real_filename_full_scan(connection_struct
*conn
,
1297 const char *path
, const char *name
,
1299 TALLOC_CTX
*mem_ctx
, char **found_name
)
1301 struct smb_Dir
*cur_dir
;
1302 const char *dname
= NULL
;
1303 char *talloced
= NULL
;
1304 char *unmangled_name
= NULL
;
1306 struct smb_filename
*smb_fname
= NULL
;
1308 /* handle null paths */
1309 if ((path
== NULL
) || (*path
== 0)) {
1313 /* If we have a case-sensitive filesystem, it doesn't do us any
1314 * good to search for a name. If a case variation of the name was
1315 * there, then the original stat(2) would have found it.
1317 if (!mangled
&& !(conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
)) {
1323 * The incoming name can be mangled, and if we de-mangle it
1324 * here it will not compare correctly against the filename (name2)
1325 * read from the directory and then mangled by the name_to_8_3()
1326 * call. We need to mangle both names or neither.
1329 * Fix for bug found by Dina Fine. If in case sensitive mode then
1330 * the mangle cache is no good (3 letter extension could be wrong
1331 * case - so don't demangle in this case - leave as mangled and
1332 * allow the mangling of the directory entry read (which is done
1333 * case insensitively) to match instead. This will lead to more
1334 * false positive matches but we fail completely without it. JRA.
1337 if (mangled
&& !conn
->case_sensitive
) {
1338 mangled
= !mangle_lookup_name_from_8_3(talloc_tos(), name
,
1342 /* Name is now unmangled. */
1343 name
= unmangled_name
;
1347 smb_fname
= synthetic_smb_fname(talloc_tos(),
1352 if (smb_fname
== NULL
) {
1353 TALLOC_FREE(unmangled_name
);
1357 /* open the directory */
1358 if (!(cur_dir
= OpenDir(talloc_tos(), conn
, smb_fname
, NULL
, 0))) {
1359 DEBUG(3,("scan dir didn't open dir [%s]\n",path
));
1360 TALLOC_FREE(unmangled_name
);
1361 TALLOC_FREE(smb_fname
);
1365 TALLOC_FREE(smb_fname
);
1367 /* now scan for matching names */
1369 while ((dname
= ReadDirName(cur_dir
, &curpos
, NULL
, &talloced
))) {
1371 /* Is it dot or dot dot. */
1372 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
1373 TALLOC_FREE(talloced
);
1378 * At this point dname is the unmangled name.
1379 * name is either mangled or not, depending on the state
1380 * of the "mangled" variable. JRA.
1384 * Check mangled name against mangled name, or unmangled name
1385 * against unmangled name.
1388 if ((mangled
&& mangled_equal(name
,dname
,conn
->params
)) ||
1389 fname_equal(name
, dname
, conn
->case_sensitive
)) {
1390 /* we've found the file, change it's name and return */
1391 *found_name
= talloc_strdup(mem_ctx
, dname
);
1392 TALLOC_FREE(unmangled_name
);
1393 TALLOC_FREE(cur_dir
);
1396 TALLOC_FREE(talloced
);
1399 TALLOC_FREE(talloced
);
1402 TALLOC_FREE(talloced
);
1405 TALLOC_FREE(unmangled_name
);
1406 TALLOC_FREE(cur_dir
);
1411 /****************************************************************************
1412 Wrapper around the vfs get_real_filename and the full directory scan
1414 ****************************************************************************/
1416 int get_real_filename(connection_struct
*conn
, const char *path
,
1417 const char *name
, TALLOC_CTX
*mem_ctx
,
1423 mangled
= mangle_is_mangled(name
, conn
->params
);
1426 return get_real_filename_full_scan(conn
, path
, name
, mangled
,
1427 mem_ctx
, found_name
);
1430 /* Try the vfs first to take advantage of case-insensitive stat. */
1431 ret
= SMB_VFS_GET_REAL_FILENAME(conn
, path
, name
, mem_ctx
, found_name
);
1434 * If the case-insensitive stat was successful, or returned an error
1435 * other than EOPNOTSUPP then there is no need to fall back on the
1436 * full directory scan.
1438 if (ret
== 0 || (ret
== -1 && errno
!= EOPNOTSUPP
)) {
1442 return get_real_filename_full_scan(conn
, path
, name
, mangled
, mem_ctx
,
1446 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
1447 connection_struct
*conn
,
1448 struct smb_filename
*smb_fname
)
1451 unsigned int i
, num_streams
= 0;
1452 struct stream_struct
*streams
= NULL
;
1454 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1455 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1456 return NT_STATUS_OK
;
1459 if (errno
!= ENOENT
) {
1460 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno
)));
1461 status
= map_nt_error_from_unix(errno
);
1465 /* Fall back to a case-insensitive scan of all streams on the file. */
1466 status
= vfs_streaminfo(conn
, NULL
, smb_fname
, mem_ctx
,
1467 &num_streams
, &streams
);
1469 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1470 SET_STAT_INVALID(smb_fname
->st
);
1471 return NT_STATUS_OK
;
1474 if (!NT_STATUS_IS_OK(status
)) {
1475 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status
)));
1479 for (i
=0; i
<num_streams
; i
++) {
1480 DEBUG(10, ("comparing [%s] and [%s]: ",
1481 smb_fname
->stream_name
, streams
[i
].name
));
1482 if (fname_equal(smb_fname
->stream_name
, streams
[i
].name
,
1483 conn
->case_sensitive
)) {
1484 DEBUGADD(10, ("equal\n"));
1487 DEBUGADD(10, ("not equal\n"));
1490 /* Couldn't find the stream. */
1491 if (i
== num_streams
) {
1492 SET_STAT_INVALID(smb_fname
->st
);
1493 TALLOC_FREE(streams
);
1494 return NT_STATUS_OK
;
1497 DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1498 smb_fname
->stream_name
, streams
[i
].name
));
1501 TALLOC_FREE(smb_fname
->stream_name
);
1502 smb_fname
->stream_name
= talloc_strdup(smb_fname
, streams
[i
].name
);
1503 if (smb_fname
->stream_name
== NULL
) {
1504 status
= NT_STATUS_NO_MEMORY
;
1508 SET_STAT_INVALID(smb_fname
->st
);
1510 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1511 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1513 status
= NT_STATUS_OK
;
1515 TALLOC_FREE(streams
);
1520 * Go through all the steps to validate a filename.
1522 * @param ctx talloc_ctx to allocate memory with.
1523 * @param conn connection struct for vfs calls.
1524 * @param dfs_path Whether this path requires dfs resolution.
1525 * @param smbreq SMB request if we're using privileges.
1526 * @param name_in The unconverted name.
1527 * @param ucf_flags flags to pass through to unix_convert().
1528 * UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
1529 * p_cont_wcard != NULL and is true and
1530 * UCF_COND_ALLOW_WCARD_LCOMP.
1531 * @param p_cont_wcard If not NULL, will be set to true if the dfs path
1532 * resolution detects a wildcard.
1533 * @param pp_smb_fname The final converted name will be allocated if the
1534 * return is NT_STATUS_OK.
1536 * @return NT_STATUS_OK if all operations completed succesfully, appropriate
1539 static NTSTATUS
filename_convert_internal(TALLOC_CTX
*ctx
,
1540 connection_struct
*conn
,
1542 struct smb_request
*smbreq
,
1543 const char *name_in
,
1545 bool *ppath_contains_wcard
,
1546 struct smb_filename
**pp_smb_fname
)
1551 *pp_smb_fname
= NULL
;
1553 status
= resolve_dfspath_wcard(ctx
, conn
,
1557 !conn
->sconn
->using_smb2
,
1559 ppath_contains_wcard
);
1560 if (!NT_STATUS_IS_OK(status
)) {
1561 DEBUG(10,("filename_convert_internal: resolve_dfspath failed "
1562 "for name %s with %s\n",
1564 nt_errstr(status
) ));
1568 if (is_fake_file_path(name_in
)) {
1572 *pp_smb_fname
= synthetic_smb_fname_split(ctx
,
1574 (ucf_flags
& UCF_POSIX_PATHNAMES
));
1575 if (*pp_smb_fname
== NULL
) {
1576 return NT_STATUS_NO_MEMORY
;
1578 (*pp_smb_fname
)->st
= st
;
1579 return NT_STATUS_OK
;
1583 * If the caller conditionally allows wildcard lookups, only add the
1584 * always allow if the path actually does contain a wildcard.
1586 if (ucf_flags
& UCF_COND_ALLOW_WCARD_LCOMP
&&
1587 ppath_contains_wcard
!= NULL
&& *ppath_contains_wcard
) {
1588 ucf_flags
|= UCF_ALWAYS_ALLOW_WCARD_LCOMP
;
1591 status
= unix_convert(ctx
, conn
, fname
, pp_smb_fname
, ucf_flags
);
1592 if (!NT_STATUS_IS_OK(status
)) {
1593 DEBUG(10,("filename_convert_internal: unix_convert failed "
1594 "for name %s with %s\n",
1596 nt_errstr(status
) ));
1600 if ((ucf_flags
& UCF_UNIX_NAME_LOOKUP
) &&
1601 VALID_STAT((*pp_smb_fname
)->st
) &&
1602 S_ISLNK((*pp_smb_fname
)->st
.st_ex_mode
)) {
1603 return check_veto_path(conn
, (*pp_smb_fname
)->base_name
);
1607 status
= check_name(conn
, (*pp_smb_fname
)->base_name
);
1609 status
= check_name_with_privilege(conn
, smbreq
, (*pp_smb_fname
)->base_name
);
1611 if (!NT_STATUS_IS_OK(status
)) {
1612 DEBUG(3,("filename_convert_internal: check_name failed "
1613 "for name %s with %s\n",
1614 smb_fname_str_dbg(*pp_smb_fname
),
1615 nt_errstr(status
) ));
1616 TALLOC_FREE(*pp_smb_fname
);
1624 * Go through all the steps to validate a filename.
1628 NTSTATUS
filename_convert(TALLOC_CTX
*ctx
,
1629 connection_struct
*conn
,
1631 const char *name_in
,
1633 bool *ppath_contains_wcard
,
1634 struct smb_filename
**pp_smb_fname
)
1636 return filename_convert_internal(ctx
,
1642 ppath_contains_wcard
,
1647 * Go through all the steps to validate a filename.
1648 * root (privileged) version.
1651 NTSTATUS
filename_convert_with_privilege(TALLOC_CTX
*ctx
,
1652 connection_struct
*conn
,
1653 struct smb_request
*smbreq
,
1654 const char *name_in
,
1656 bool *ppath_contains_wcard
,
1657 struct smb_filename
**pp_smb_fname
)
1659 return filename_convert_internal(ctx
,
1661 smbreq
->flags2
& FLAGS2_DFS_PATHNAMES
,
1665 ppath_contains_wcard
,