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 ucf_flags_from_smb_request(struct smb_request
*req
)
35 uint32_t ucf_flags
= 0;
38 if (req
->posix_pathnames
) {
39 ucf_flags
|= UCF_POSIX_PATHNAMES
;
41 if (req
->flags2
& FLAGS2_DFS_PATHNAMES
) {
42 ucf_flags
|= UCF_DFS_PATHNAME
;
44 if (req
->flags2
& FLAGS2_REPARSE_PATH
) {
45 ucf_flags
|= UCF_GMT_PATHNAME
;
52 uint32_t filename_create_ucf_flags(struct smb_request
*req
, uint32_t create_disposition
)
54 uint32_t ucf_flags
= 0;
56 ucf_flags
|= ucf_flags_from_smb_request(req
);
58 switch (create_disposition
) {
65 case FILE_OVERWRITE_IF
:
66 ucf_flags
|= UCF_PREP_CREATEFILE
;
73 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
74 connection_struct
*conn
,
75 struct smb_filename
*smb_fname
);
77 /****************************************************************************
78 Mangle the 2nd name and check if it is then equal to the first name.
79 ****************************************************************************/
81 static bool mangled_equal(const char *name1
,
83 const struct share_params
*p
)
87 if (!name_to_8_3(name2
, mname
, False
, p
)) {
90 return strequal(name1
, mname
);
93 /****************************************************************************
94 Cope with the differing wildcard and non-wildcard error cases.
95 ****************************************************************************/
97 static NTSTATUS
determine_path_error(const char *name
,
98 bool allow_wcard_last_component
,
102 bool name_has_wild
= false;
104 if (!allow_wcard_last_component
) {
105 /* Error code within a pathname. */
106 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
109 /* We're terminating here so we
110 * can be a little slower and get
111 * the error code right. Windows
112 * treats the last part of the pathname
113 * separately I think, so if the last
114 * component is a wildcard then we treat
115 * this ./ as "end of component" */
117 p
= strchr(name
, '/');
119 if (!posix_pathnames
) {
120 name_has_wild
= ms_has_wild(name
);
123 if (!p
&& (name_has_wild
|| ISDOT(name
))) {
124 /* Error code at the end of a pathname. */
125 return NT_STATUS_OBJECT_NAME_INVALID
;
127 /* Error code within a pathname. */
128 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
132 static NTSTATUS
check_for_dot_component(const struct smb_filename
*smb_fname
)
134 /* Ensure we catch all names with in "/."
135 this is disallowed under Windows and
136 in POSIX they've already been removed. */
137 const char *p
= strstr(smb_fname
->base_name
, "/."); /*mb safe*/
140 /* Error code within a pathname. */
141 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
142 } else if (p
[2] == '\0') {
143 /* Error code at the end of a pathname. */
144 return NT_STATUS_OBJECT_NAME_INVALID
;
150 /****************************************************************************
151 Optimization for common case where the missing part
152 is in the last component and the client already
153 sent the correct case.
154 Returns NT_STATUS_OK to mean continue the tree walk
155 (possibly with modified start pointer).
156 Any other NT_STATUS_XXX error means terminate the path
158 ****************************************************************************/
160 static NTSTATUS
check_parent_exists(TALLOC_CTX
*ctx
,
161 connection_struct
*conn
,
162 bool posix_pathnames
,
163 const struct smb_filename
*smb_fname
,
167 char *parent_name
= NULL
;
168 struct smb_filename
*parent_fname
= NULL
;
169 const char *last_component
= NULL
;
173 if (!parent_dirname(ctx
, smb_fname
->base_name
,
176 return NT_STATUS_NO_MEMORY
;
179 if (!posix_pathnames
) {
180 if (ms_has_wild(parent_name
)) {
181 goto no_optimization_out
;
186 * If there was no parent component in
187 * smb_fname->base_name then don't do this
190 if (smb_fname
->base_name
== last_component
) {
191 goto no_optimization_out
;
194 parent_fname
= synthetic_smb_fname(ctx
,
200 if (parent_fname
== NULL
) {
201 return NT_STATUS_NO_MEMORY
;
204 if (posix_pathnames
) {
205 ret
= SMB_VFS_LSTAT(conn
, parent_fname
);
207 ret
= SMB_VFS_STAT(conn
, parent_fname
);
210 /* If the parent stat failed, just continue
211 with the normal tree walk. */
214 goto no_optimization_out
;
217 status
= check_for_dot_component(parent_fname
);
218 if (!NT_STATUS_IS_OK(status
)) {
222 /* Parent exists - set "start" to be the
223 * last component to shorten the tree walk. */
226 * Safe to use discard_const_p
227 * here as last_component points
228 * into our smb_fname->base_name.
230 *pp_start
= discard_const_p(char, last_component
);
232 /* Update dirpath. */
233 TALLOC_FREE(*pp_dirpath
);
234 *pp_dirpath
= talloc_strdup(ctx
, parent_fname
->base_name
);
236 return NT_STATUS_NO_MEMORY
;
239 DEBUG(5,("check_parent_exists: name "
240 "= %s, dirpath = %s, "
242 smb_fname
->base_name
,
251 * We must still return an *pp_dirpath
252 * initialized to ".", and a *pp_start
253 * pointing at smb_fname->base_name.
256 TALLOC_FREE(parent_name
);
257 TALLOC_FREE(parent_fname
);
259 *pp_dirpath
= talloc_strdup(ctx
, ".");
260 if (*pp_dirpath
== NULL
) {
261 return NT_STATUS_NO_MEMORY
;
264 * Safe to use discard_const_p
265 * here as by convention smb_fname->base_name
266 * is allocated off ctx.
268 *pp_start
= discard_const_p(char, smb_fname
->base_name
);
273 * Re-order a known good @GMT-token path.
276 static NTSTATUS
rearrange_snapshot_path(struct smb_filename
*smb_fname
,
281 size_t gmt_len
= endp
- startp
;
282 char gmt_store
[gmt_len
+ 1];
284 const char *last_component
= NULL
;
288 DBG_DEBUG("|%s| -> ", smb_fname
->base_name
);
290 /* Save off the @GMT-token. */
291 memcpy(gmt_store
, startp
, gmt_len
);
292 gmt_store
[gmt_len
] = '\0';
295 /* Remove any trailing '/' */
301 * @GMT-token was at end of path.
302 * Remove any preceding '/'
304 if (startp
> smb_fname
->base_name
&& startp
[-1] == '/') {
309 /* Remove @GMT-token from the path. */
310 endlen
= strlen(endp
);
311 memmove(startp
, endp
, endlen
+ 1);
313 /* Split the remaining path into components. */
314 ret
= parent_dirname(smb_fname
,
315 smb_fname
->base_name
,
319 /* Must terminate debug with \n */
320 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
321 return NT_STATUS_NO_MEMORY
;
325 if (last_component
[0] == '\0') {
326 newstr
= talloc_strdup(smb_fname
,
329 newstr
= talloc_asprintf(smb_fname
,
335 newstr
= talloc_asprintf(smb_fname
,
343 TALLOC_FREE(smb_fname
->base_name
);
344 smb_fname
->base_name
= newstr
;
346 DBG_DEBUG("|%s|\n", newstr
);
352 * Strip a valid @GMT-token from any incoming filename path,
353 * adding any NTTIME encoded in the pathname into the
354 * twrp field of the passed in smb_fname.
356 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
357 * at the *start* of a pathname component.
359 * If twrp is passed in then smb_fname->twrp is set to that
360 * value, and the @GMT-token part of the filename is removed
361 * and does not change the stored smb_fname->twrp.
365 NTSTATUS
canonicalize_snapshot_path(struct smb_filename
*smb_fname
,
378 smb_fname
->twrp
= twrp
;
381 if (!(ucf_flags
& UCF_GMT_PATHNAME
)) {
385 startp
= strchr_m(smb_fname
->base_name
, '@');
386 if (startp
== NULL
) {
391 startp
= strstr_m(startp
, "@GMT-");
392 if (startp
== NULL
) {
397 if ((startp
> smb_fname
->base_name
) && (startp
[-1] != '/')) {
398 /* the GMT-token does not start a path-component */
402 endp
= strptime(startp
, GMT_FORMAT
, &tm
);
404 /* Not a valid timestring. */
408 if (endp
[0] != '\0' && endp
[0] != '/') {
410 * It is not a complete path component, i.e. the path
411 * component continues after the gmt-token.
416 status
= rearrange_snapshot_path(smb_fname
, startp
, endp
);
417 if (!NT_STATUS_IS_OK(status
)) {
421 startp
= smb_fname
->base_name
+ GMT_NAME_LEN
;
422 if (startp
[0] == '/') {
426 tmp
= talloc_strdup(smb_fname
, startp
);
428 return NT_STATUS_NO_MEMORY
;
431 TALLOC_FREE(smb_fname
->base_name
);
432 smb_fname
->base_name
= tmp
;
434 if (smb_fname
->twrp
== 0) {
437 unix_to_nt_time(&nt
, t
);
438 smb_fname
->twrp
= nt
;
445 * Utility function to normalize case on an incoming client filename
446 * if required on this connection struct.
447 * Performs an in-place case conversion guaranteed to stay the same size.
450 static NTSTATUS
normalize_filename_case(connection_struct
*conn
, char *filename
)
454 if (!conn
->case_sensitive
) {
457 if (conn
->case_preserve
) {
460 if (conn
->short_case_preserve
) {
463 ok
= strnorm(filename
, lp_default_case(SNUM(conn
)));
465 return NT_STATUS_INVALID_PARAMETER
;
470 /****************************************************************************
471 This routine is called to convert names from the dos namespace to unix
472 namespace. It needs to handle any case conversions, mangling, format changes,
475 We assume that we have already done a chdir() to the right "root" directory
478 Conversion to basic unix format is already done in check_path_syntax().
480 Names must be relative to the root of the service - any leading /. and
481 trailing /'s should have been trimmed by check_path_syntax().
483 The function will return an NTSTATUS error if some part of the name except for
484 the last part cannot be resolved, else NT_STATUS_OK.
486 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
487 didn't get any fatal errors that should immediately terminate the calling SMB
488 processing whilst resolving.
490 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
491 and should be allowed in the last component of the path only.
493 If the orig_path was a stream, smb_filename->base_name will point to the base
494 filename, and smb_filename->stream_name will point to the stream name. If
495 orig_path was not a stream, then smb_filename->stream_name will be NULL.
497 On exit from unix_convert, the smb_filename->st stat struct will be populated
498 if the file exists and was found, if not this stat struct will be filled with
499 zeros (and this can be detected by checking for nlinks = 0, which can never be
501 ****************************************************************************/
505 struct connection_struct
*conn
;
506 struct smb_filename
*smb_fname
;
507 const char *orig_path
;
513 bool component_was_mangled
;
514 bool name_has_wildcard
;
515 bool posix_pathnames
;
516 bool allow_wcard_last_component
;
520 static NTSTATUS
unix_convert_step_search_fail(struct uc_state
*state
)
526 * An intermediate part of the name
529 DBG_DEBUG("Intermediate [%s] missing\n",
534 * We need to return the fact that the
535 * intermediate name resolution failed.
536 * This is used to return an error of
537 * ERRbadpath rather than ERRbadfile.
538 * Some Windows applications depend on
539 * the difference between these two
544 * ENOENT, ENOTDIR and ELOOP all map
545 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
546 * in the filename walk.
549 if (errno
== ENOENT
||
553 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
555 return map_nt_error_from_unix(errno
);
559 * ENOENT/EACCESS are the only valid errors
563 if (errno
== EACCES
) {
564 if ((state
->ucf_flags
& UCF_PREP_CREATEFILE
) == 0) {
565 return NT_STATUS_ACCESS_DENIED
;
568 * This is the dropbox
569 * behaviour. A dropbox is a
570 * directory with only -wx
572 * get_real_filename fails
573 * with EACCESS, it needs to
574 * list the directory. We
575 * nevertheless want to allow
576 * users creating a file.
582 if ((errno
!= 0) && (errno
!= ENOENT
)) {
584 * ENOTDIR and ELOOP both map to
585 * NT_STATUS_OBJECT_PATH_NOT_FOUND
586 * in the filename walk.
588 if (errno
== ENOTDIR
|| errno
== ELOOP
) {
589 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
591 return map_nt_error_from_unix(errno
);
595 * Just the last part of the name doesn't exist.
596 * We need to strupper() or strlower() it as
597 * this conversion may be used for file creation
598 * purposes. Fix inspired by
599 * Thomas Neumann <t.neumann@iku-ag.de>.
601 if (!state
->conn
->case_preserve
||
602 (mangle_is_8_3(state
->name
, false,
603 state
->conn
->params
) &&
604 !state
->conn
->short_case_preserve
)) {
605 if (!strnorm(state
->name
,
606 lp_default_case(SNUM(state
->conn
)))) {
607 DBG_DEBUG("strnorm %s failed\n",
609 return NT_STATUS_INVALID_PARAMETER
;
614 * check on the mangled stack to see if we can
615 * recover the base of the filename.
618 if (mangle_is_mangled(state
->name
, state
->conn
->params
)
619 && mangle_lookup_name_from_8_3(state
->mem_ctx
,
622 state
->conn
->params
)) {
625 state
->name
- state
->smb_fname
->base_name
;
627 if (!ISDOT(state
->dirpath
)) {
628 tmp
= talloc_asprintf(
629 state
->smb_fname
, "%s/%s",
630 state
->dirpath
, unmangled
);
631 TALLOC_FREE(unmangled
);
637 DBG_ERR("talloc failed\n");
638 return NT_STATUS_NO_MEMORY
;
640 TALLOC_FREE(state
->smb_fname
->base_name
);
641 state
->smb_fname
->base_name
= tmp
;
643 state
->smb_fname
->base_name
+ name_ofs
;
644 state
->end
= state
->name
+ strlen(state
->name
);
647 DBG_DEBUG("New file [%s]\n", state
->name
);
652 static NTSTATUS
unix_convert_step_stat(struct uc_state
*state
)
654 struct smb_filename dname
;
656 char *found_name
= NULL
;
660 * Check if the name exists up to this point.
663 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state
->smb_fname
));
665 if (state
->posix_pathnames
) {
666 ret
= SMB_VFS_LSTAT(state
->conn
, state
->smb_fname
);
668 ret
= SMB_VFS_STAT(state
->conn
, state
->smb_fname
);
672 * It exists. it must either be a directory or this must
673 * be the last part of the path for it to be OK.
675 if (state
->end
&& !S_ISDIR(state
->smb_fname
->st
.st_ex_mode
)) {
677 * An intermediate part of the name isn't
680 DBG_DEBUG("Not a dir [%s]\n", state
->name
);
683 * We need to return the fact that the
684 * intermediate name resolution failed. This
685 * is used to return an error of ERRbadpath
686 * rather than ERRbadfile. Some Windows
687 * applications depend on the difference between
690 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
695 /* Stat failed - ensure we don't use it. */
696 SET_STAT_INVALID(state
->smb_fname
->st
);
698 if (state
->posix_pathnames
) {
700 * For posix_pathnames, we're done.
701 * Don't blunder into the name_has_wildcard OR
702 * get_real_filename() codepaths as they may
703 * be doing case insensitive lookups. So when
704 * creating a new POSIX directory Foo they might
707 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
709 if (state
->end
!= NULL
) {
710 const char *morepath
= NULL
;
712 * If this is intermediate we must
713 * restore the full path.
717 * If there are any more components
718 * after the failed LSTAT we cannot
721 morepath
= strchr(state
->end
+ 1, '/');
722 if (morepath
!= NULL
) {
723 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
726 if (errno
== ENOENT
) {
727 /* New file or directory. */
731 if ((errno
== EACCES
) &&
732 (state
->ucf_flags
& UCF_PREP_CREATEFILE
)) {
733 /* POSIX Dropbox case. */
738 return map_nt_error_from_unix(errno
);
742 * Reset errno so we can detect
743 * directory open errors.
748 * Try to find this part of the path in the directory.
751 if (state
->name_has_wildcard
) {
752 return unix_convert_step_search_fail(state
);
755 dname
= (struct smb_filename
) {
756 .base_name
= state
->dirpath
,
757 .twrp
= state
->smb_fname
->twrp
,
760 /* handle null paths */
761 if ((dname
.base_name
== NULL
) || (dname
.base_name
[0] == '\0')) {
762 dname
.base_name
= dot
;
765 ret
= get_real_filename(state
->conn
,
771 return unix_convert_step_search_fail(state
);
775 * Restore the rest of the string. If the string was
776 * mangled the size may have changed.
781 state
->name
- state
->smb_fname
->base_name
;
783 if (!ISDOT(state
->dirpath
)) {
784 tmp
= talloc_asprintf(state
->smb_fname
,
785 "%s/%s/%s", state
->dirpath
,
786 found_name
, state
->end
+1);
789 tmp
= talloc_asprintf(state
->smb_fname
,
794 DBG_ERR("talloc_asprintf failed\n");
795 return NT_STATUS_NO_MEMORY
;
797 TALLOC_FREE(state
->smb_fname
->base_name
);
798 state
->smb_fname
->base_name
= tmp
;
799 state
->name
= state
->smb_fname
->base_name
+ name_ofs
;
800 state
->end
= state
->name
+ strlen(found_name
);
805 state
->name
- state
->smb_fname
->base_name
;
807 if (!ISDOT(state
->dirpath
)) {
808 tmp
= talloc_asprintf(state
->smb_fname
,
809 "%s/%s", state
->dirpath
,
812 tmp
= talloc_strdup(state
->smb_fname
,
816 DBG_ERR("talloc failed\n");
817 return NT_STATUS_NO_MEMORY
;
819 TALLOC_FREE(state
->smb_fname
->base_name
);
820 state
->smb_fname
->base_name
= tmp
;
821 state
->name
= state
->smb_fname
->base_name
+ name_ofs
;
824 * We just scanned for, and found the end of
825 * the path. We must return a valid stat struct
829 if (state
->posix_pathnames
) {
830 ret
= SMB_VFS_LSTAT(state
->conn
, state
->smb_fname
);
832 ret
= SMB_VFS_STAT(state
->conn
, state
->smb_fname
);
836 SET_STAT_INVALID(state
->smb_fname
->st
);
840 TALLOC_FREE(found_name
);
844 static NTSTATUS
unix_convert_step(struct uc_state
*state
)
849 * Pinpoint the end of this section of the filename.
851 /* mb safe. '/' can't be in any encoded char. */
852 state
->end
= strchr(state
->name
, '/');
855 * Chop the name at this point.
857 if (state
->end
!= NULL
) {
861 DBG_DEBUG("dirpath [%s] name [%s]\n", state
->dirpath
, state
->name
);
863 /* The name cannot have a component of "." */
865 if (ISDOT(state
->name
)) {
866 if (state
->end
== NULL
) {
867 /* Error code at the end of a pathname. */
868 return NT_STATUS_OBJECT_NAME_INVALID
;
870 return determine_path_error(state
->end
+1,
871 state
->allow_wcard_last_component
,
872 state
->posix_pathnames
);
875 /* The name cannot have a wildcard if it's not
876 the last component. */
878 if (!state
->posix_pathnames
) {
879 state
->name_has_wildcard
= ms_has_wild(state
->name
);
882 /* Wildcards never valid within a pathname. */
883 if (state
->name_has_wildcard
&& state
->end
!= NULL
) {
884 return NT_STATUS_OBJECT_NAME_INVALID
;
887 /* Skip the stat call if it's a wildcard end. */
888 if (state
->name_has_wildcard
) {
889 DBG_DEBUG("Wildcard [%s]\n", state
->name
);
894 status
= unix_convert_step_stat(state
);
895 if (!NT_STATUS_IS_OK(status
)) {
903 * Add to the dirpath that we have resolved so far.
906 if (!ISDOT(state
->dirpath
)) {
907 char *tmp
= talloc_asprintf(state
->mem_ctx
,
908 "%s/%s", state
->dirpath
, state
->name
);
910 DBG_ERR("talloc_asprintf failed\n");
911 return NT_STATUS_NO_MEMORY
;
913 TALLOC_FREE(state
->dirpath
);
914 state
->dirpath
= tmp
;
917 TALLOC_FREE(state
->dirpath
);
918 if (!(state
->dirpath
= talloc_strdup(state
->mem_ctx
,state
->name
))) {
919 DBG_ERR("talloc_strdup failed\n");
920 return NT_STATUS_NO_MEMORY
;
925 * Cache the dirpath thus far. Don't cache a name with mangled
926 * or wildcard components as this can change the size.
928 if(!state
->component_was_mangled
&& !state
->name_has_wildcard
) {
929 stat_cache_add(state
->orig_path
,
931 state
->smb_fname
->twrp
,
932 state
->conn
->case_sensitive
);
936 * Restore the / that we wiped out earlier.
938 if (state
->end
!= NULL
) {
945 NTSTATUS
unix_convert(TALLOC_CTX
*mem_ctx
,
946 connection_struct
*conn
,
947 const char *orig_path
,
949 struct smb_filename
**smb_fname_out
,
952 struct uc_state uc_state
;
953 struct uc_state
*state
= &uc_state
;
957 *state
= (struct uc_state
) {
960 .orig_path
= orig_path
,
961 .ucf_flags
= ucf_flags
,
962 .posix_pathnames
= (ucf_flags
& UCF_POSIX_PATHNAMES
),
963 .allow_wcard_last_component
= (ucf_flags
& UCF_ALWAYS_ALLOW_WCARD_LCOMP
),
966 *smb_fname_out
= NULL
;
968 state
->smb_fname
= talloc_zero(state
->mem_ctx
, struct smb_filename
);
969 if (state
->smb_fname
== NULL
) {
970 return NT_STATUS_NO_MEMORY
;
973 if (state
->conn
->printer
) {
974 /* we don't ever use the filenames on a printer share as a
975 filename - so don't convert them */
976 state
->smb_fname
->base_name
= talloc_strdup(
977 state
->smb_fname
, state
->orig_path
);
978 if (state
->smb_fname
->base_name
== NULL
) {
979 status
= NT_STATUS_NO_MEMORY
;
985 state
->smb_fname
->flags
= state
->posix_pathnames
? SMB_FILENAME_POSIX_PATH
: 0;
987 DBG_DEBUG("Called on file [%s]\n", state
->orig_path
);
989 if (state
->orig_path
[0] == '/') {
990 DBG_ERR("Path [%s] starts with '/'\n", state
->orig_path
);
991 return NT_STATUS_OBJECT_NAME_INVALID
;
994 /* Start with the full orig_path as given by the caller. */
995 state
->smb_fname
->base_name
= talloc_strdup(
996 state
->smb_fname
, state
->orig_path
);
997 if (state
->smb_fname
->base_name
== NULL
) {
998 DBG_ERR("talloc_strdup failed\n");
999 status
= NT_STATUS_NO_MEMORY
;
1003 /* Canonicalize any @GMT- paths. */
1004 status
= canonicalize_snapshot_path(state
->smb_fname
, ucf_flags
, twrp
);
1005 if (!NT_STATUS_IS_OK(status
)) {
1010 * If we trimmed down to a single '\0' character
1011 * then we should use the "." directory to avoid
1012 * searching the cache, but not if we are in a
1014 * As we know this is valid we can return true here.
1017 if (state
->smb_fname
->base_name
[0] == '\0') {
1018 state
->smb_fname
->base_name
= talloc_strdup(state
->smb_fname
, ".");
1019 if (state
->smb_fname
->base_name
== NULL
) {
1020 status
= NT_STATUS_NO_MEMORY
;
1023 if (SMB_VFS_STAT(state
->conn
, state
->smb_fname
) != 0) {
1024 status
= map_nt_error_from_unix(errno
);
1027 DBG_DEBUG("conversion finished [] -> [%s]\n",
1028 state
->smb_fname
->base_name
);
1032 if (state
->orig_path
[0] == '.' && (state
->orig_path
[1] == '/' ||
1033 state
->orig_path
[1] == '\0')) {
1034 /* Start of pathname can't be "." only. */
1035 if (state
->orig_path
[1] == '\0' || state
->orig_path
[2] == '\0') {
1036 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1038 status
=determine_path_error(&state
->orig_path
[2],
1039 state
->allow_wcard_last_component
,
1040 state
->posix_pathnames
);
1046 * Large directory fix normalization. If we're case sensitive, and
1047 * the case preserving parameters are set to "no", normalize the case of
1048 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
1049 * This is in conflict with the current (3.0.20) man page, but is
1050 * what people expect from the "large directory howto". I'll update
1051 * the man page. Thanks to jht@samba.org for finding this. JRA.
1054 status
= normalize_filename_case(state
->conn
, state
->smb_fname
->base_name
);
1055 if (!NT_STATUS_IS_OK(status
)) {
1056 DBG_ERR("normalize_filename_case %s failed\n",
1057 state
->smb_fname
->base_name
);
1062 * Strip off the stream, and add it back when we're done with the
1065 if (!state
->posix_pathnames
) {
1066 state
->stream
= strchr_m(state
->smb_fname
->base_name
, ':');
1068 if (state
->stream
!= NULL
) {
1069 char *tmp
= talloc_strdup(state
->smb_fname
, state
->stream
);
1071 status
= NT_STATUS_NO_MEMORY
;
1075 * Since this is actually pointing into
1076 * smb_fname->base_name this truncates base_name.
1078 *state
->stream
= '\0';
1079 state
->stream
= tmp
;
1081 if (state
->smb_fname
->base_name
[0] == '\0') {
1083 * orig_name was just a stream name.
1084 * This is a stream on the root of
1085 * the share. Replace base_name with
1088 state
->smb_fname
->base_name
=
1089 talloc_strdup(state
->smb_fname
, ".");
1090 if (state
->smb_fname
->base_name
== NULL
) {
1091 status
= NT_STATUS_NO_MEMORY
;
1094 if (SMB_VFS_STAT(state
->conn
, state
->smb_fname
) != 0) {
1095 status
= map_nt_error_from_unix(errno
);
1098 /* dirpath must exist. */
1099 state
->dirpath
= talloc_strdup(state
->mem_ctx
,".");
1100 if (state
->dirpath
== NULL
) {
1101 status
= NT_STATUS_NO_MEMORY
;
1104 DBG_INFO("conversion finished [%s] -> [%s]\n",
1106 state
->smb_fname
->base_name
);
1112 state
->name
= state
->smb_fname
->base_name
;
1115 * If we're providing case insensitive semantics or
1116 * the underlying filesystem is case insensitive,
1117 * then a case-normalized hit in the stat-cache is
1118 * authoritative. JRA.
1120 * Note: We're only checking base_name. The stream_name will be
1121 * added and verified in build_stream_path().
1124 if (!state
->conn
->case_sensitive
||
1125 !(state
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
1129 found
= stat_cache_lookup(state
->conn
,
1130 state
->posix_pathnames
,
1131 &state
->smb_fname
->base_name
,
1134 state
->smb_fname
->twrp
,
1135 &state
->smb_fname
->st
);
1142 * Make sure "dirpath" is an allocated string, we use this for
1143 * building the directories with talloc_asprintf and free it.
1146 if (state
->dirpath
== NULL
) {
1147 state
->dirpath
= talloc_strdup(state
->mem_ctx
,".");
1148 if (state
->dirpath
== NULL
) {
1149 DBG_ERR("talloc_strdup failed\n");
1150 status
= NT_STATUS_NO_MEMORY
;
1156 * If we have a wildcard we must walk the path to
1157 * find where the error is, even if case sensitive
1161 if (!state
->posix_pathnames
) {
1162 /* POSIX pathnames have no wildcards. */
1163 state
->name_has_wildcard
= ms_has_wild(state
->smb_fname
->base_name
);
1164 if (state
->name_has_wildcard
&& !state
->allow_wcard_last_component
) {
1165 /* Wildcard not valid anywhere. */
1166 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1171 DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1172 state
->smb_fname
->base_name
, state
->dirpath
, state
->name
);
1174 if (!state
->name_has_wildcard
) {
1176 * stat the name - if it exists then we can add the stream back (if
1177 * there was one) and be done!
1180 if (state
->posix_pathnames
) {
1181 ret
= SMB_VFS_LSTAT(state
->conn
, state
->smb_fname
);
1183 ret
= SMB_VFS_STAT(state
->conn
, state
->smb_fname
);
1187 status
= check_for_dot_component(state
->smb_fname
);
1188 if (!NT_STATUS_IS_OK(status
)) {
1191 /* Add the path (not including the stream) to the cache. */
1192 stat_cache_add(state
->orig_path
,
1193 state
->smb_fname
->base_name
,
1194 state
->smb_fname
->twrp
,
1195 state
->conn
->case_sensitive
);
1196 DBG_DEBUG("Conversion of base_name finished "
1198 state
->orig_path
, state
->smb_fname
->base_name
);
1202 /* Stat failed - ensure we don't use it. */
1203 SET_STAT_INVALID(state
->smb_fname
->st
);
1206 * Note: we must continue processing a path if we get EACCES
1207 * from stat. With NFS4 permissions the file might be lacking
1208 * READ_ATTR, but if the parent has LIST permissions we can
1209 * resolve the path in the path traversal loop down below.
1212 if (errno
== ENOENT
) {
1213 /* Optimization when creating a new file - only
1214 the last component doesn't exist.
1215 NOTE : check_parent_exists() doesn't preserve errno.
1217 int saved_errno
= errno
;
1218 status
= check_parent_exists(state
->mem_ctx
,
1220 state
->posix_pathnames
,
1224 errno
= saved_errno
;
1225 if (!NT_STATUS_IS_OK(status
)) {
1231 * A special case - if we don't have any wildcards or mangling chars and are case
1232 * sensitive or the underlying filesystem is case insensitive then searching
1236 if ((state
->conn
->case_sensitive
|| !(state
->conn
->fs_capabilities
&
1237 FILE_CASE_SENSITIVE_SEARCH
)) &&
1238 !mangle_is_mangled(state
->smb_fname
->base_name
, state
->conn
->params
)) {
1240 status
= check_for_dot_component(state
->smb_fname
);
1241 if (!NT_STATUS_IS_OK(status
)) {
1246 * The stat failed. Could be ok as it could be
1250 if (errno
== ENOTDIR
|| errno
== ELOOP
) {
1251 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1253 } else if (errno
== ENOENT
) {
1255 * Was it a missing last component ?
1256 * or a missing intermediate component ?
1258 struct smb_filename
*parent_fname
= NULL
;
1259 struct smb_filename
*base_fname
= NULL
;
1262 ok
= parent_smb_fname(state
->mem_ctx
,
1267 status
= NT_STATUS_NO_MEMORY
;
1270 if (state
->posix_pathnames
) {
1271 ret
= SMB_VFS_LSTAT(state
->conn
,
1274 ret
= SMB_VFS_STAT(state
->conn
,
1277 TALLOC_FREE(parent_fname
);
1279 if (errno
== ENOTDIR
||
1282 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1288 * Missing last component is ok - new file.
1289 * Also deal with permission denied elsewhere.
1290 * Just drop out to done.
1297 * We have a wildcard in the pathname.
1299 * Optimization for common case where the wildcard
1300 * is in the last component and the client already
1301 * sent the correct case.
1302 * NOTE : check_parent_exists() doesn't preserve errno.
1304 int saved_errno
= errno
;
1305 status
= check_parent_exists(state
->mem_ctx
,
1307 state
->posix_pathnames
,
1311 errno
= saved_errno
;
1312 if (!NT_STATUS_IS_OK(status
)) {
1318 * is_mangled() was changed to look at an entire pathname, not
1319 * just a component. JRA.
1322 if (mangle_is_mangled(state
->name
, state
->conn
->params
)) {
1323 state
->component_was_mangled
= true;
1327 * Now we need to recursively match the name against the real
1328 * directory structure.
1332 * Match each part of the path name separately, trying the names
1333 * as is first, then trying to scan the directory for matching names.
1336 for (; state
->name
; state
->name
= (state
->end
? state
->end
+ 1:(char *)NULL
)) {
1337 status
= unix_convert_step(state
);
1338 if (!NT_STATUS_IS_OK(status
)) {
1339 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_MEMORY
)) {
1350 * Cache the full path. Don't cache a name with mangled or wildcard
1351 * components as this can change the size.
1354 if(!state
->component_was_mangled
&& !state
->name_has_wildcard
) {
1355 stat_cache_add(state
->orig_path
,
1356 state
->smb_fname
->base_name
,
1357 state
->smb_fname
->twrp
,
1358 state
->conn
->case_sensitive
);
1362 * The name has been resolved.
1366 /* Add back the stream if one was stripped off originally. */
1367 if (state
->stream
!= NULL
) {
1368 state
->smb_fname
->stream_name
= state
->stream
;
1370 /* Check path now that the base_name has been converted. */
1371 status
= build_stream_path(state
->mem_ctx
, state
->conn
, state
->smb_fname
);
1372 if (!NT_STATUS_IS_OK(status
)) {
1377 DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1378 state
->orig_path
, smb_fname_str_dbg(state
->smb_fname
));
1380 TALLOC_FREE(state
->dirpath
);
1381 *smb_fname_out
= state
->smb_fname
;
1382 return NT_STATUS_OK
;
1384 DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
1385 state
->dirpath
, state
->name
);
1386 if ((state
->dirpath
!= NULL
) && !ISDOT(state
->dirpath
)) {
1387 state
->smb_fname
->base_name
= talloc_asprintf(
1393 state
->smb_fname
->base_name
= talloc_strdup(
1394 state
->smb_fname
, state
->name
);
1396 if (state
->smb_fname
->base_name
== NULL
) {
1397 DBG_ERR("talloc_asprintf failed\n");
1398 status
= NT_STATUS_NO_MEMORY
;
1402 *smb_fname_out
= state
->smb_fname
;
1403 TALLOC_FREE(state
->dirpath
);
1406 TALLOC_FREE(state
->smb_fname
);
1410 /****************************************************************************
1411 Ensure a path is not vetoed.
1412 ****************************************************************************/
1414 static NTSTATUS
check_veto_path(connection_struct
*conn
,
1415 const struct smb_filename
*smb_fname
)
1417 const char *name
= smb_fname
->base_name
;
1419 if (IS_VETO_PATH(conn
, name
)) {
1420 /* Is it not dot or dot dot. */
1421 if (!(ISDOT(name
) || ISDOTDOT(name
))) {
1422 DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1424 return map_nt_error_from_unix(ENOENT
);
1427 return NT_STATUS_OK
;
1430 /****************************************************************************
1431 Check a filename - possibly calling check_reduced_name.
1432 This is called by every routine before it allows an operation on a filename.
1433 It does any final confirmation necessary to ensure that the filename is
1434 a valid one for the user to access.
1435 ****************************************************************************/
1437 NTSTATUS
check_name(connection_struct
*conn
,
1438 const struct smb_filename
*smb_fname
)
1440 NTSTATUS status
= check_veto_path(conn
, smb_fname
);
1442 if (!NT_STATUS_IS_OK(status
)) {
1446 if (!lp_widelinks(SNUM(conn
)) || !lp_follow_symlinks(SNUM(conn
))) {
1447 status
= check_reduced_name(conn
, NULL
, smb_fname
);
1448 if (!NT_STATUS_IS_OK(status
)) {
1449 DEBUG(5,("check_name: name %s failed with %s\n",
1450 smb_fname
->base_name
,
1451 nt_errstr(status
)));
1456 return NT_STATUS_OK
;
1459 /****************************************************************************
1460 Must be called as root. Creates the struct privilege_paths
1461 attached to the struct smb_request if this call is successful.
1462 ****************************************************************************/
1464 static NTSTATUS
check_name_with_privilege(connection_struct
*conn
,
1465 struct smb_request
*smbreq
,
1466 const struct smb_filename
*smb_fname
)
1468 NTSTATUS status
= check_veto_path(conn
, smb_fname
);
1470 if (!NT_STATUS_IS_OK(status
)) {
1473 return check_reduced_name_with_privilege(conn
,
1478 /****************************************************************************
1479 Check if two filenames are equal.
1480 This needs to be careful about whether we are case sensitive.
1481 ****************************************************************************/
1483 static bool fname_equal(const char *name1
, const char *name2
,
1484 bool case_sensitive
)
1486 /* Normal filename handling */
1487 if (case_sensitive
) {
1488 return(strcmp(name1
,name2
) == 0);
1491 return(strequal(name1
,name2
));
1494 static bool sname_equal(const char *name1
, const char *name2
,
1495 bool case_sensitive
)
1498 const char *s1
= NULL
;
1499 const char *s2
= NULL
;
1502 const char *e1
= NULL
;
1503 const char *e2
= NULL
;
1507 match
= fname_equal(name1
, name2
, case_sensitive
);
1512 if (name1
[0] != ':') {
1515 if (name2
[0] != ':') {
1519 e1
= strchr(s1
, ':');
1523 n1
= PTR_DIFF(e1
, s1
);
1526 e2
= strchr(s2
, ':');
1530 n2
= PTR_DIFF(e2
, s2
);
1533 /* Normal filename handling */
1534 if (case_sensitive
) {
1535 return (strncmp(s1
, s2
, n1
) == 0);
1539 * We can't use strnequal() here
1540 * as it takes the number of codepoints
1541 * and not the number of bytes.
1543 * So we make a copy before calling
1546 * Note that we TALLOC_FREE() in reverse order
1547 * in order to avoid memory fragmentation.
1550 c1
= talloc_strndup(talloc_tos(), s1
, n1
);
1551 c2
= talloc_strndup(talloc_tos(), s2
, n2
);
1552 if (c1
== NULL
|| c2
== NULL
) {
1555 return (strncmp(s1
, s2
, n1
) == 0);
1558 match
= strequal(c1
, c2
);
1564 /****************************************************************************
1565 Scan a directory to find a filename, matching without case sensitivity.
1566 If the name looks like a mangled name then try via the mangling functions
1567 ****************************************************************************/
1569 int get_real_filename_full_scan(connection_struct
*conn
,
1573 TALLOC_CTX
*mem_ctx
,
1576 struct smb_Dir
*cur_dir
;
1577 const char *dname
= NULL
;
1578 char *talloced
= NULL
;
1579 char *unmangled_name
= NULL
;
1581 struct smb_filename
*smb_fname
= NULL
;
1583 /* handle null paths */
1584 if ((path
== NULL
) || (*path
== 0)) {
1588 /* If we have a case-sensitive filesystem, it doesn't do us any
1589 * good to search for a name. If a case variation of the name was
1590 * there, then the original stat(2) would have found it.
1592 if (!mangled
&& !(conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
)) {
1598 * The incoming name can be mangled, and if we de-mangle it
1599 * here it will not compare correctly against the filename (name2)
1600 * read from the directory and then mangled by the name_to_8_3()
1601 * call. We need to mangle both names or neither.
1604 * Fix for bug found by Dina Fine. If in case sensitive mode then
1605 * the mangle cache is no good (3 letter extension could be wrong
1606 * case - so don't demangle in this case - leave as mangled and
1607 * allow the mangling of the directory entry read (which is done
1608 * case insensitively) to match instead. This will lead to more
1609 * false positive matches but we fail completely without it. JRA.
1612 if (mangled
&& !conn
->case_sensitive
) {
1613 mangled
= !mangle_lookup_name_from_8_3(talloc_tos(), name
,
1617 /* Name is now unmangled. */
1618 name
= unmangled_name
;
1622 smb_fname
= synthetic_smb_fname(talloc_tos(),
1628 if (smb_fname
== NULL
) {
1629 TALLOC_FREE(unmangled_name
);
1633 /* open the directory */
1634 if (!(cur_dir
= OpenDir(talloc_tos(), conn
, smb_fname
, NULL
, 0))) {
1635 DEBUG(3,("scan dir didn't open dir [%s]\n",path
));
1636 TALLOC_FREE(unmangled_name
);
1637 TALLOC_FREE(smb_fname
);
1641 TALLOC_FREE(smb_fname
);
1643 /* now scan for matching names */
1645 while ((dname
= ReadDirName(cur_dir
, &curpos
, NULL
, &talloced
))) {
1647 /* Is it dot or dot dot. */
1648 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
1649 TALLOC_FREE(talloced
);
1654 * At this point dname is the unmangled name.
1655 * name is either mangled or not, depending on the state
1656 * of the "mangled" variable. JRA.
1660 * Check mangled name against mangled name, or unmangled name
1661 * against unmangled name.
1664 if ((mangled
&& mangled_equal(name
,dname
,conn
->params
)) ||
1665 fname_equal(name
, dname
, conn
->case_sensitive
)) {
1666 /* we've found the file, change it's name and return */
1667 *found_name
= talloc_strdup(mem_ctx
, dname
);
1668 TALLOC_FREE(unmangled_name
);
1669 TALLOC_FREE(cur_dir
);
1672 TALLOC_FREE(talloced
);
1675 TALLOC_FREE(talloced
);
1678 TALLOC_FREE(talloced
);
1681 TALLOC_FREE(unmangled_name
);
1682 TALLOC_FREE(cur_dir
);
1687 /****************************************************************************
1688 Wrapper around the vfs get_real_filename and the full directory scan
1690 ****************************************************************************/
1692 int get_real_filename(connection_struct
*conn
,
1693 struct smb_filename
*path
,
1695 TALLOC_CTX
*mem_ctx
,
1701 mangled
= mangle_is_mangled(name
, conn
->params
);
1704 return get_real_filename_full_scan(conn
,
1712 /* Try the vfs first to take advantage of case-insensitive stat. */
1713 ret
= SMB_VFS_GET_REAL_FILENAME(conn
,
1720 * If the case-insensitive stat was successful, or returned an error
1721 * other than EOPNOTSUPP then there is no need to fall back on the
1722 * full directory scan.
1724 if (ret
== 0 || (ret
== -1 && errno
!= EOPNOTSUPP
)) {
1728 return get_real_filename_full_scan(conn
,
1736 static NTSTATUS
build_stream_path(TALLOC_CTX
*mem_ctx
,
1737 connection_struct
*conn
,
1738 struct smb_filename
*smb_fname
)
1741 unsigned int i
, num_streams
= 0;
1742 struct stream_struct
*streams
= NULL
;
1744 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1745 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1746 return NT_STATUS_OK
;
1749 if (errno
!= ENOENT
) {
1750 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno
)));
1751 status
= map_nt_error_from_unix(errno
);
1755 /* Fall back to a case-insensitive scan of all streams on the file. */
1756 status
= vfs_streaminfo(conn
, NULL
, smb_fname
, mem_ctx
,
1757 &num_streams
, &streams
);
1759 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1760 SET_STAT_INVALID(smb_fname
->st
);
1761 return NT_STATUS_OK
;
1764 if (!NT_STATUS_IS_OK(status
)) {
1765 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status
)));
1769 for (i
=0; i
<num_streams
; i
++) {
1770 DEBUG(10, ("comparing [%s] and [%s]: ",
1771 smb_fname
->stream_name
, streams
[i
].name
));
1772 if (sname_equal(smb_fname
->stream_name
, streams
[i
].name
,
1773 conn
->case_sensitive
)) {
1774 DEBUGADD(10, ("equal\n"));
1777 DEBUGADD(10, ("not equal\n"));
1780 /* Couldn't find the stream. */
1781 if (i
== num_streams
) {
1782 SET_STAT_INVALID(smb_fname
->st
);
1783 TALLOC_FREE(streams
);
1784 return NT_STATUS_OK
;
1787 DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1788 smb_fname
->stream_name
, streams
[i
].name
));
1791 TALLOC_FREE(smb_fname
->stream_name
);
1792 smb_fname
->stream_name
= talloc_strdup(smb_fname
, streams
[i
].name
);
1793 if (smb_fname
->stream_name
== NULL
) {
1794 status
= NT_STATUS_NO_MEMORY
;
1798 SET_STAT_INVALID(smb_fname
->st
);
1800 if (SMB_VFS_STAT(conn
, smb_fname
) == 0) {
1801 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname
)));
1803 status
= NT_STATUS_OK
;
1805 TALLOC_FREE(streams
);
1810 * Lightweight function to just get last component
1811 * for rename / enumerate directory calls.
1814 char *get_original_lcomp(TALLOC_CTX
*ctx
,
1815 connection_struct
*conn
,
1816 const char *filename_in
,
1819 struct smb_filename
*smb_fname
= NULL
;
1820 char *last_slash
= NULL
;
1825 if (ucf_flags
& UCF_DFS_PATHNAME
) {
1826 status
= resolve_dfspath_wcard(ctx
,
1830 !conn
->sconn
->using_smb2
,
1833 if (!NT_STATUS_IS_OK(status
)) {
1834 DBG_DEBUG("resolve_dfspath "
1835 "failed for name %s with %s\n",
1840 filename_in
= fname
;
1841 ucf_flags
&= ~UCF_DFS_PATHNAME
;
1845 * NB. We don't need to care about
1846 * is_fake_file_path(filename_in) here as these
1847 * code paths don't ever return original_lcomp
1851 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1853 * Ensure we don't return a @GMT
1854 * value as the last component.
1856 smb_fname
= synthetic_smb_fname(ctx
,
1862 if (smb_fname
== NULL
) {
1866 status
= canonicalize_snapshot_path(smb_fname
,
1869 if (!NT_STATUS_IS_OK(status
)) {
1871 TALLOC_FREE(smb_fname
);
1874 filename_in
= smb_fname
->base_name
;
1876 last_slash
= strrchr(filename_in
, '/');
1877 if (last_slash
!= NULL
) {
1878 orig_lcomp
= talloc_strdup(ctx
, last_slash
+1);
1880 orig_lcomp
= talloc_strdup(ctx
, filename_in
);
1882 /* We're done with any temp names here. */
1883 TALLOC_FREE(smb_fname
);
1885 if (orig_lcomp
== NULL
) {
1888 status
= normalize_filename_case(conn
, orig_lcomp
);
1889 if (!NT_STATUS_IS_OK(status
)) {
1890 TALLOC_FREE(orig_lcomp
);
1897 * Go through all the steps to validate a filename.
1899 * @param ctx talloc_ctx to allocate memory with.
1900 * @param conn connection struct for vfs calls.
1901 * @param smbreq SMB request if we're using privileges.
1902 * @param name_in The unconverted name.
1903 * @param ucf_flags flags to pass through to unix_convert().
1904 * UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
1905 * p_cont_wcard != NULL and is true and
1906 * UCF_COND_ALLOW_WCARD_LCOMP.
1907 * @param twrp Optional VSS time
1908 * @param p_cont_wcard If not NULL, will be set to true if the dfs path
1909 * resolution detects a wildcard.
1910 * @param _smb_fname The final converted name will be allocated if the
1911 * return is NT_STATUS_OK.
1913 * @return NT_STATUS_OK if all operations completed successfully, appropriate
1916 static NTSTATUS
filename_convert_internal(TALLOC_CTX
*ctx
,
1917 connection_struct
*conn
,
1918 struct smb_request
*smbreq
,
1919 const char *name_in
,
1922 bool *ppath_contains_wcard
,
1923 struct smb_filename
**_smb_fname
)
1925 struct smb_filename
*smb_fname
= NULL
;
1930 if (ucf_flags
& UCF_DFS_PATHNAME
) {
1931 bool path_contains_wcard
= false;
1933 status
= resolve_dfspath_wcard(ctx
, conn
,
1936 !conn
->sconn
->using_smb2
,
1938 &path_contains_wcard
);
1939 if (!NT_STATUS_IS_OK(status
)) {
1940 DEBUG(10,("filename_convert_internal: resolve_dfspath "
1941 "failed for name %s with %s\n",
1943 nt_errstr(status
) ));
1947 if (ppath_contains_wcard
!= NULL
&& path_contains_wcard
) {
1948 *ppath_contains_wcard
= path_contains_wcard
;
1950 ucf_flags
&= ~UCF_DFS_PATHNAME
;
1953 if (is_fake_file_path(name_in
)) {
1954 smb_fname
= synthetic_smb_fname_split(ctx
,
1956 (ucf_flags
& UCF_POSIX_PATHNAMES
));
1957 if (smb_fname
== NULL
) {
1958 return NT_STATUS_NO_MEMORY
;
1960 smb_fname
->st
= (SMB_STRUCT_STAT
) { .st_ex_nlink
= 1 };
1961 smb_fname
->st
.st_ex_btime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
1962 smb_fname
->st
.st_ex_atime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
1963 smb_fname
->st
.st_ex_mtime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
1964 smb_fname
->st
.st_ex_ctime
= (struct timespec
){0, SAMBA_UTIME_OMIT
};
1966 *_smb_fname
= smb_fname
;
1967 return NT_STATUS_OK
;
1971 * If the caller conditionally allows wildcard lookups, only add the
1972 * always allow if the path actually does contain a wildcard.
1974 if (ucf_flags
& UCF_COND_ALLOW_WCARD_LCOMP
&&
1975 ppath_contains_wcard
!= NULL
&& *ppath_contains_wcard
) {
1976 ucf_flags
|= UCF_ALWAYS_ALLOW_WCARD_LCOMP
;
1979 status
= unix_convert(ctx
, conn
, name_in
, twrp
, &smb_fname
, ucf_flags
);
1980 if (!NT_STATUS_IS_OK(status
)) {
1981 DEBUG(10,("filename_convert_internal: unix_convert failed "
1982 "for name %s with %s\n",
1984 nt_errstr(status
) ));
1988 if ((ucf_flags
& UCF_UNIX_NAME_LOOKUP
) &&
1989 VALID_STAT(smb_fname
->st
) &&
1990 S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
1991 status
= check_veto_path(conn
, smb_fname
);
1992 if (!NT_STATUS_IS_OK(status
)) {
1993 TALLOC_FREE(smb_fname
);
1996 *_smb_fname
= smb_fname
;
1997 return NT_STATUS_OK
;
2001 status
= check_name(conn
, smb_fname
);
2003 status
= check_name_with_privilege(conn
, smbreq
,
2006 if (!NT_STATUS_IS_OK(status
)) {
2007 DEBUG(3,("filename_convert_internal: check_name failed "
2008 "for name %s with %s\n",
2009 smb_fname_str_dbg(smb_fname
),
2010 nt_errstr(status
) ));
2011 TALLOC_FREE(smb_fname
);
2015 *_smb_fname
= smb_fname
;
2020 * Go through all the steps to validate a filename.
2024 NTSTATUS
filename_convert(TALLOC_CTX
*ctx
,
2025 connection_struct
*conn
,
2026 const char *name_in
,
2029 bool *ppath_contains_wcard
,
2030 struct smb_filename
**pp_smb_fname
)
2032 return filename_convert_internal(ctx
,
2038 ppath_contains_wcard
,
2043 * Go through all the steps to validate a filename.
2044 * root (privileged) version.
2047 NTSTATUS
filename_convert_with_privilege(TALLOC_CTX
*ctx
,
2048 connection_struct
*conn
,
2049 struct smb_request
*smbreq
,
2050 const char *name_in
,
2052 bool *ppath_contains_wcard
,
2053 struct smb_filename
**pp_smb_fname
)
2055 return filename_convert_internal(ctx
,
2061 ppath_contains_wcard
,