LCOV - code coverage report
Current view: top level - source3/smbd - filename.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 664 806 82.4 %
Date: 2021-08-25 13:27:56 Functions: 26 28 92.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    filename handling routines
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Jeremy Allison 1999-2007
       6             :    Copyright (C) Ying Chen 2000
       7             :    Copyright (C) Volker Lendecke 2007
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : /*
      24             :  * New hash table stat cache code added by Ying Chen.
      25             :  */
      26             : 
      27             : #include "includes.h"
      28             : #include "system/filesys.h"
      29             : #include "fake_file.h"
      30             : #include "smbd/smbd.h"
      31             : #include "smbd/globals.h"
      32             : 
      33      594929 : uint32_t ucf_flags_from_smb_request(struct smb_request *req)
      34             : {
      35      594929 :         uint32_t ucf_flags = 0;
      36             : 
      37      594929 :         if (req != NULL) {
      38      594929 :                 if (req->posix_pathnames) {
      39        1638 :                         ucf_flags |= UCF_POSIX_PATHNAMES;
      40             :                 }
      41      594929 :                 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
      42        8794 :                         ucf_flags |= UCF_DFS_PATHNAME;
      43             :                 }
      44      594929 :                 if (req->flags2 & FLAGS2_REPARSE_PATH) {
      45        3582 :                         ucf_flags |= UCF_GMT_PATHNAME;
      46             :                 }
      47             :         }
      48             : 
      49      594929 :         return ucf_flags;
      50             : }
      51             : 
      52      501634 : uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
      53             : {
      54      501634 :         uint32_t ucf_flags = 0;
      55             : 
      56      501634 :         ucf_flags |= ucf_flags_from_smb_request(req);
      57             : 
      58      500928 :         switch (create_disposition) {
      59      306018 :         case FILE_OPEN:
      60             :         case FILE_OVERWRITE:
      61      306018 :                 break;
      62      195175 :         case FILE_SUPERSEDE:
      63             :         case FILE_CREATE:
      64             :         case FILE_OPEN_IF:
      65             :         case FILE_OVERWRITE_IF:
      66      195175 :                 ucf_flags |= UCF_PREP_CREATEFILE;
      67      195175 :                 break;
      68             :         }
      69             : 
      70      501634 :         return ucf_flags;
      71             : }
      72             : 
      73             : static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
      74             :                                   connection_struct *conn,
      75             :                                   struct smb_filename *smb_fname);
      76             : 
      77             : /****************************************************************************
      78             :  Mangle the 2nd name and check if it is then equal to the first name.
      79             : ****************************************************************************/
      80             : 
      81           4 : static bool mangled_equal(const char *name1,
      82             :                         const char *name2,
      83             :                         const struct share_params *p)
      84             : {
      85             :         char mname[13];
      86             : 
      87           4 :         if (!name_to_8_3(name2, mname, False, p)) {
      88           0 :                 return False;
      89             :         }
      90           4 :         return strequal(name1, mname);
      91             : }
      92             : 
      93             : /****************************************************************************
      94             :  Cope with the differing wildcard and non-wildcard error cases.
      95             : ****************************************************************************/
      96             : 
      97          88 : static NTSTATUS determine_path_error(const char *name,
      98             :                         bool allow_wcard_last_component,
      99             :                         bool posix_pathnames)
     100             : {
     101             :         const char *p;
     102          88 :         bool name_has_wild = false;
     103             : 
     104          88 :         if (!allow_wcard_last_component) {
     105             :                 /* Error code within a pathname. */
     106          84 :                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     107             :         }
     108             : 
     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" */
     116             : 
     117           4 :         p = strchr(name, '/');
     118             : 
     119           4 :         if (!posix_pathnames) {
     120           4 :                 name_has_wild = ms_has_wild(name);
     121             :         }
     122             : 
     123           4 :         if (!p && (name_has_wild || ISDOT(name))) {
     124             :                 /* Error code at the end of a pathname. */
     125           4 :                 return NT_STATUS_OBJECT_NAME_INVALID;
     126             :         } else {
     127             :                 /* Error code within a pathname. */
     128           0 :                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     129             :         }
     130             : }
     131             : 
     132      468609 : static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
     133             : {
     134             :         /* Ensure we catch all names with in "/."
     135             :            this is disallowed under Windows and
     136             :            in POSIX they've already been removed. */
     137      468609 :         const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
     138      468609 :         if (p) {
     139         197 :                 if (p[2] == '/') {
     140             :                         /* Error code within a pathname. */
     141          48 :                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     142         149 :                 } else if (p[2] == '\0') {
     143             :                         /* Error code at the end of a pathname. */
     144          32 :                         return NT_STATUS_OBJECT_NAME_INVALID;
     145             :                 }
     146             :         }
     147      468529 :         return NT_STATUS_OK;
     148             : }
     149             : 
     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
     157             :  lookup here.
     158             : ****************************************************************************/
     159             : 
     160      295752 : static NTSTATUS check_parent_exists(TALLOC_CTX *ctx,
     161             :                                 connection_struct *conn,
     162             :                                 bool posix_pathnames,
     163             :                                 const struct smb_filename *smb_fname,
     164             :                                 char **pp_dirpath,
     165             :                                 char **pp_start,
     166             :                                 int *p_parent_stat_errno)
     167             : {
     168      295752 :         char *parent_name = NULL;
     169      295752 :         struct smb_filename *parent_fname = NULL;
     170      295752 :         const char *last_component = NULL;
     171             :         NTSTATUS status;
     172             :         int ret;
     173             : 
     174      295752 :         if (!parent_dirname(ctx, smb_fname->base_name,
     175             :                                 &parent_name,
     176             :                                 &last_component)) {
     177           0 :                 return NT_STATUS_NO_MEMORY;
     178             :         }
     179             : 
     180      295752 :         if (!posix_pathnames) {
     181      295056 :                 if (ms_has_wild(parent_name)) {
     182           0 :                         goto no_optimization_out;
     183             :                 }
     184             :         }
     185             : 
     186             :         /*
     187             :          * If there was no parent component in
     188             :          * smb_fname->base_name then don't do this
     189             :          * optimization.
     190             :          */
     191      295752 :         if (smb_fname->base_name == last_component) {
     192       14401 :                 goto no_optimization_out;
     193             :         }
     194             : 
     195      280954 :         parent_fname = synthetic_smb_fname(ctx,
     196             :                                            parent_name,
     197             :                                            NULL,
     198             :                                            NULL,
     199             :                                            smb_fname->twrp,
     200             :                                            smb_fname->flags);
     201      280954 :         if (parent_fname == NULL) {
     202           0 :                 return NT_STATUS_NO_MEMORY;
     203             :         }
     204             : 
     205      280954 :         if (posix_pathnames) {
     206         134 :                 ret = SMB_VFS_LSTAT(conn, parent_fname);
     207             :         } else {
     208      280820 :                 ret = SMB_VFS_STAT(conn, parent_fname);
     209             :         }
     210             : 
     211             :         /* If the parent stat failed, just continue
     212             :            with the normal tree walk. */
     213             : 
     214      280954 :         if (ret == -1) {
     215             :                 /*
     216             :                  * Optimization. Preserving the
     217             :                  * errno from the STAT/LSTAT here
     218             :                  * will allow us to save a duplicate
     219             :                  * STAT/LSTAT system call of the parent
     220             :                  * pathname in a hot code path in the caller.
     221             :                  */
     222        1583 :                 if (p_parent_stat_errno != NULL) {
     223        1544 :                         *p_parent_stat_errno = errno;
     224             :                 }
     225        1579 :                 goto no_optimization_out;
     226             :         }
     227             : 
     228      279371 :         status = check_for_dot_component(parent_fname);
     229      279371 :         if (!NT_STATUS_IS_OK(status)) {
     230           0 :                 return status;
     231             :         }
     232             : 
     233             :         /* Parent exists - set "start" to be the
     234             :          * last component to shorten the tree walk. */
     235             : 
     236             :         /*
     237             :          * Safe to use discard_const_p
     238             :          * here as last_component points
     239             :          * into our smb_fname->base_name.
     240             :          */
     241      279371 :         *pp_start = discard_const_p(char, last_component);
     242             : 
     243             :         /* Update dirpath. */
     244      279371 :         TALLOC_FREE(*pp_dirpath);
     245      279371 :         *pp_dirpath = talloc_strdup(ctx, parent_fname->base_name);
     246      279371 :         if (!*pp_dirpath) {
     247           0 :                 return NT_STATUS_NO_MEMORY;
     248             :         }
     249             : 
     250      279371 :         DEBUG(5,("check_parent_exists: name "
     251             :                 "= %s, dirpath = %s, "
     252             :                 "start = %s\n",
     253             :                 smb_fname->base_name,
     254             :                 *pp_dirpath,
     255             :                 *pp_start));
     256             : 
     257      279371 :         return NT_STATUS_OK;
     258             : 
     259       16377 :   no_optimization_out:
     260             : 
     261             :         /*
     262             :          * We must still return an *pp_dirpath
     263             :          * initialized to ".", and a *pp_start
     264             :          * pointing at smb_fname->base_name.
     265             :          */
     266             : 
     267       16381 :         TALLOC_FREE(parent_name);
     268       16381 :         TALLOC_FREE(parent_fname);
     269             : 
     270       16381 :         *pp_dirpath = talloc_strdup(ctx, ".");
     271       16381 :         if (*pp_dirpath == NULL) {
     272           0 :                 return NT_STATUS_NO_MEMORY;
     273             :         }
     274             :         /*
     275             :          * Safe to use discard_const_p
     276             :          * here as by convention smb_fname->base_name
     277             :          * is allocated off ctx.
     278             :          */
     279       16381 :         *pp_start = discard_const_p(char, smb_fname->base_name);
     280       16381 :         return NT_STATUS_OK;
     281             : }
     282             : 
     283             : /*
     284             :  * Re-order a known good @GMT-token path.
     285             :  */
     286             : 
     287        3650 : static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname,
     288             :                                 char *startp,
     289             :                                 char *endp)
     290        3650 : {
     291        3650 :         size_t endlen = 0;
     292        3650 :         size_t gmt_len = endp - startp;
     293        3650 :         char gmt_store[gmt_len + 1];
     294        3650 :         char *parent = NULL;
     295        3650 :         const char *last_component = NULL;
     296             :         char *newstr;
     297             :         bool ret;
     298             : 
     299        3650 :         DBG_DEBUG("|%s| -> ", smb_fname->base_name);
     300             : 
     301             :         /* Save off the @GMT-token. */
     302        3650 :         memcpy(gmt_store, startp, gmt_len);
     303        3650 :         gmt_store[gmt_len] = '\0';
     304             : 
     305        3650 :         if (*endp == '/') {
     306             :                 /* Remove any trailing '/' */
     307        3648 :                 endp++;
     308             :         }
     309             : 
     310        3650 :         if (*endp == '\0') {
     311             :                 /*
     312             :                  * @GMT-token was at end of path.
     313             :                  * Remove any preceding '/'
     314             :                  */
     315           2 :                 if (startp > smb_fname->base_name && startp[-1] == '/') {
     316           0 :                         startp--;
     317             :                 }
     318             :         }
     319             : 
     320             :         /* Remove @GMT-token from the path. */
     321        3650 :         endlen = strlen(endp);
     322        3650 :         memmove(startp, endp, endlen + 1);
     323             : 
     324             :         /* Split the remaining path into components. */
     325        3650 :         ret = parent_dirname(smb_fname,
     326        3650 :                                 smb_fname->base_name,
     327             :                                 &parent,
     328             :                                 &last_component);
     329        3650 :         if (ret == false) {
     330             :                 /* Must terminate debug with \n */
     331           0 :                 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
     332           0 :                 return NT_STATUS_NO_MEMORY;
     333             :         }
     334             : 
     335        3650 :         if (ISDOT(parent)) {
     336        2820 :                 if (last_component[0] == '\0') {
     337           2 :                         newstr = talloc_strdup(smb_fname,
     338             :                                         gmt_store);
     339             :                 } else {
     340        1408 :                         newstr = talloc_asprintf(smb_fname,
     341             :                                         "%s/%s",
     342             :                                         gmt_store,
     343             :                                         last_component);
     344             :                 }
     345             :         } else {
     346        2240 :                 newstr = talloc_asprintf(smb_fname,
     347             :                                         "%s/%s/%s",
     348             :                                         gmt_store,
     349             :                                         parent,
     350             :                                         last_component);
     351             :         }
     352             : 
     353        3650 :         TALLOC_FREE(parent);
     354        3650 :         TALLOC_FREE(smb_fname->base_name);
     355        3650 :         smb_fname->base_name = newstr;
     356             : 
     357        3650 :         DBG_DEBUG("|%s|\n", newstr);
     358             : 
     359        3650 :         return NT_STATUS_OK;
     360             : }
     361             : 
     362             : /*
     363             :  * Strip a valid @GMT-token from any incoming filename path,
     364             :  * adding any NTTIME encoded in the pathname into the
     365             :  * twrp field of the passed in smb_fname.
     366             :  *
     367             :  * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
     368             :  * at the *start* of a pathname component.
     369             :  *
     370             :  * If twrp is passed in then smb_fname->twrp is set to that
     371             :  * value, and the @GMT-token part of the filename is removed
     372             :  * and does not change the stored smb_fname->twrp.
     373             :  *
     374             :  */
     375             : 
     376      599516 : NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
     377             :                                     uint32_t ucf_flags,
     378             :                                     NTTIME twrp)
     379             : {
     380      599516 :         char *startp = NULL;
     381      599516 :         char *endp = NULL;
     382      599516 :         char *tmp = NULL;
     383             :         struct tm tm;
     384             :         time_t t;
     385             :         NTTIME nt;
     386             :         NTSTATUS status;
     387             : 
     388      599516 :         if (twrp != 0) {
     389        2331 :                 smb_fname->twrp = twrp;
     390             :         }
     391             : 
     392      599516 :         if (!(ucf_flags & UCF_GMT_PATHNAME)) {
     393      595748 :                 return NT_STATUS_OK;
     394             :         }
     395             : 
     396        3768 :         startp = strchr_m(smb_fname->base_name, '@');
     397        3768 :         if (startp == NULL) {
     398             :                 /* No @ */
     399         118 :                 return NT_STATUS_OK;
     400             :         }
     401             : 
     402        3650 :         startp = strstr_m(startp, "@GMT-");
     403        3650 :         if (startp == NULL) {
     404             :                 /* No @ */
     405           0 :                 return NT_STATUS_OK;
     406             :         }
     407             : 
     408        3650 :         if ((startp > smb_fname->base_name) && (startp[-1] != '/')) {
     409             :                 /* the GMT-token does not start a path-component */
     410           0 :                 return NT_STATUS_OK;
     411             :         }
     412             : 
     413        3650 :         endp = strptime(startp, GMT_FORMAT, &tm);
     414        3650 :         if (endp == NULL) {
     415             :                 /* Not a valid timestring. */
     416           0 :                 return NT_STATUS_OK;
     417             :         }
     418             : 
     419        3650 :         if (endp[0] != '\0' && endp[0] != '/') {
     420             :                 /*
     421             :                  * It is not a complete path component, i.e. the path
     422             :                  * component continues after the gmt-token.
     423             :                  */
     424           0 :                 return NT_STATUS_OK;
     425             :         }
     426             : 
     427        3650 :         status = rearrange_snapshot_path(smb_fname, startp, endp);
     428        3650 :         if (!NT_STATUS_IS_OK(status)) {
     429           0 :                 return status;
     430             :         }
     431             : 
     432        3650 :         startp = smb_fname->base_name + GMT_NAME_LEN;
     433        3650 :         if (startp[0] == '/') {
     434        3648 :                 startp++;
     435             :         }
     436             : 
     437        3650 :         tmp = talloc_strdup(smb_fname, startp);
     438        3650 :         if (tmp == NULL) {
     439           0 :                 return NT_STATUS_NO_MEMORY;
     440             :         }
     441             : 
     442        3650 :         TALLOC_FREE(smb_fname->base_name);
     443        3650 :         smb_fname->base_name = tmp;
     444             : 
     445        3650 :         if (smb_fname->twrp == 0) {
     446        3650 :                 tm.tm_isdst = -1;
     447        3650 :                 t = timegm(&tm);
     448        3650 :                 unix_to_nt_time(&nt, t);
     449        3650 :                 smb_fname->twrp = nt;
     450             :         }
     451             : 
     452        3650 :         return NT_STATUS_OK;
     453             : }
     454             : 
     455             : /*
     456             :  * Utility function to normalize case on an incoming client filename
     457             :  * if required on this connection struct.
     458             :  * Performs an in-place case conversion guaranteed to stay the same size.
     459             :  */
     460             : 
     461      643426 : static NTSTATUS normalize_filename_case(connection_struct *conn, char *filename)
     462             : {
     463             :         bool ok;
     464             : 
     465      643426 :         if (!conn->case_sensitive) {
     466      640500 :                 return NT_STATUS_OK;
     467             :         }
     468        2926 :         if (conn->case_preserve) {
     469        2806 :                 return NT_STATUS_OK;
     470             :         }
     471         120 :         if (conn->short_case_preserve) {
     472           0 :                 return NT_STATUS_OK;
     473             :         }
     474         120 :         ok = strnorm(filename, lp_default_case(SNUM(conn)));
     475         120 :         if (!ok) {
     476           0 :                 return NT_STATUS_INVALID_PARAMETER;
     477             :         }
     478         120 :         return NT_STATUS_OK;
     479             : }
     480             : 
     481             : /****************************************************************************
     482             : This routine is called to convert names from the dos namespace to unix
     483             : namespace. It needs to handle any case conversions, mangling, format changes,
     484             : streams etc.
     485             : 
     486             : We assume that we have already done a chdir() to the right "root" directory
     487             : for this service.
     488             : 
     489             : Conversion to basic unix format is already done in check_path_syntax().
     490             : 
     491             : Names must be relative to the root of the service - any leading /.  and
     492             : trailing /'s should have been trimmed by check_path_syntax().
     493             : 
     494             : The function will return an NTSTATUS error if some part of the name except for
     495             : the last part cannot be resolved, else NT_STATUS_OK.
     496             : 
     497             : Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
     498             : didn't get any fatal errors that should immediately terminate the calling SMB
     499             : processing whilst resolving.
     500             : 
     501             : If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard
     502             : should be allowed in the last component of the path only.
     503             : 
     504             : If the orig_path was a stream, smb_filename->base_name will point to the base
     505             : filename, and smb_filename->stream_name will point to the stream name.  If
     506             : orig_path was not a stream, then smb_filename->stream_name will be NULL.
     507             : 
     508             : On exit from unix_convert, the smb_filename->st stat struct will be populated
     509             : if the file exists and was found, if not this stat struct will be filled with
     510             : zeros (and this can be detected by checking for nlinks = 0, which can never be
     511             : true for any file).
     512             : ****************************************************************************/
     513             : 
     514             : struct uc_state {
     515             :         TALLOC_CTX *mem_ctx;
     516             :         struct connection_struct *conn;
     517             :         struct smb_filename *smb_fname;
     518             :         const char *orig_path;
     519             :         uint32_t ucf_flags;
     520             :         char *name;
     521             :         char *end;
     522             :         char *dirpath;
     523             :         char *stream;
     524             :         bool component_was_mangled;
     525             :         bool name_has_wildcard;
     526             :         bool posix_pathnames;
     527             :         bool allow_wcard_last_component;
     528             :         bool done;
     529             : };
     530             : 
     531      281047 : static NTSTATUS unix_convert_step_search_fail(struct uc_state *state)
     532             : {
     533             :         char *unmangled;
     534             : 
     535      281047 :         if (state->end) {
     536             :                 /*
     537             :                  * An intermediate part of the name
     538             :                  * can't be found.
     539             :                  */
     540         651 :                 DBG_DEBUG("Intermediate [%s] missing\n",
     541             :                           state->name);
     542         651 :                 *state->end = '/';
     543             : 
     544             :                 /*
     545             :                  * We need to return the fact that the
     546             :                  * intermediate name resolution failed.
     547             :                  * This is used to return an error of
     548             :                  * ERRbadpath rather than ERRbadfile.
     549             :                  * Some Windows applications depend on
     550             :                  * the difference between these two
     551             :                  * errors.
     552             :                  */
     553             : 
     554             :                 /*
     555             :                  * ENOENT, ENOTDIR and ELOOP all map
     556             :                  * to NT_STATUS_OBJECT_PATH_NOT_FOUND
     557             :                  * in the filename walk.
     558             :                  */
     559             : 
     560         651 :                 if (errno == ENOENT ||
     561           0 :                     errno == ENOTDIR ||
     562           0 :                     errno == ELOOP)
     563             :                 {
     564         651 :                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     565             :                 }
     566           0 :                 return map_nt_error_from_unix(errno);
     567             :         }
     568             : 
     569             :         /*
     570             :          * ENOENT/EACCESS are the only valid errors
     571             :          * here.
     572             :          */
     573             : 
     574      280396 :         if (errno == EACCES) {
     575           1 :                 if ((state->ucf_flags & UCF_PREP_CREATEFILE) == 0) {
     576           0 :                         return NT_STATUS_ACCESS_DENIED;
     577             :                 } else {
     578             :                         /*
     579             :                          * This is the dropbox
     580             :                          * behaviour. A dropbox is a
     581             :                          * directory with only -wx
     582             :                          * permissions, so
     583             :                          * get_real_filename fails
     584             :                          * with EACCESS, it needs to
     585             :                          * list the directory. We
     586             :                          * nevertheless want to allow
     587             :                          * users creating a file.
     588             :                          */
     589           1 :                         errno = 0;
     590             :                 }
     591             :         }
     592             : 
     593      280396 :         if ((errno != 0) && (errno != ENOENT)) {
     594             :                 /*
     595             :                  * ENOTDIR and ELOOP both map to
     596             :                  * NT_STATUS_OBJECT_PATH_NOT_FOUND
     597             :                  * in the filename walk.
     598             :                  */
     599           0 :                 if (errno == ENOTDIR || errno == ELOOP) {
     600           0 :                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     601             :                 }
     602           0 :                 return map_nt_error_from_unix(errno);
     603             :         }
     604             : 
     605             :         /*
     606             :          * Just the last part of the name doesn't exist.
     607             :          * We need to strupper() or strlower() it as
     608             :          * this conversion may be used for file creation
     609             :          * purposes. Fix inspired by
     610             :          * Thomas Neumann <t.neumann@iku-ag.de>.
     611             :          */
     612      560792 :         if (!state->conn->case_preserve ||
     613      280396 :             (mangle_is_8_3(state->name, false,
     614      533531 :                            state->conn->params) &&
     615      253135 :              !state->conn->short_case_preserve)) {
     616           0 :                 if (!strnorm(state->name,
     617           0 :                              lp_default_case(SNUM(state->conn)))) {
     618           0 :                         DBG_DEBUG("strnorm %s failed\n",
     619             :                                   state->name);
     620           0 :                         return NT_STATUS_INVALID_PARAMETER;
     621             :                 }
     622             :         }
     623             : 
     624             :         /*
     625             :          * check on the mangled stack to see if we can
     626             :          * recover the base of the filename.
     627             :          */
     628             : 
     629      280396 :         if (mangle_is_mangled(state->name, state->conn->params)
     630          44 :             && mangle_lookup_name_from_8_3(state->mem_ctx,
     631          44 :                                            state->name,
     632             :                                            &unmangled,
     633          44 :                                            state->conn->params)) {
     634             :                 char *tmp;
     635          44 :                 size_t name_ofs =
     636          44 :                         state->name - state->smb_fname->base_name;
     637             : 
     638          44 :                 if (!ISDOT(state->dirpath)) {
     639          88 :                         tmp = talloc_asprintf(
     640          44 :                                 state->smb_fname, "%s/%s",
     641             :                                 state->dirpath, unmangled);
     642          44 :                         TALLOC_FREE(unmangled);
     643             :                 }
     644             :                 else {
     645           0 :                         tmp = unmangled;
     646             :                 }
     647          44 :                 if (tmp == NULL) {
     648           0 :                         DBG_ERR("talloc failed\n");
     649           0 :                         return NT_STATUS_NO_MEMORY;
     650             :                 }
     651          44 :                 TALLOC_FREE(state->smb_fname->base_name);
     652          44 :                 state->smb_fname->base_name = tmp;
     653          44 :                 state->name =
     654          44 :                         state->smb_fname->base_name + name_ofs;
     655          44 :                 state->end = state->name + strlen(state->name);
     656             :         }
     657             : 
     658      280396 :         DBG_DEBUG("New file [%s]\n", state->name);
     659      280396 :         state->done = true;
     660      280396 :         return NT_STATUS_OK;
     661             : }
     662             : 
     663      286114 : static NTSTATUS unix_convert_step_stat(struct uc_state *state)
     664             : {
     665             :         struct smb_filename dname;
     666      286114 :         char dot[2] = ".";
     667      286114 :         char *found_name = NULL;
     668             :         int ret;
     669             : 
     670             :         /*
     671             :          * Check if the name exists up to this point.
     672             :          */
     673             : 
     674      286114 :         DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state->smb_fname));
     675             : 
     676      286114 :         ret = vfs_stat(state->conn, state->smb_fname);
     677      286114 :         if (ret == 0) {
     678             :                 /*
     679             :                  * It exists. it must either be a directory or this must
     680             :                  * be the last part of the path for it to be OK.
     681             :                  */
     682        2836 :                 if (state->end && !S_ISDIR(state->smb_fname->st.st_ex_mode)) {
     683             :                         /*
     684             :                          * An intermediate part of the name isn't
     685             :                          * a directory.
     686             :                          */
     687           4 :                         DBG_DEBUG("Not a dir [%s]\n", state->name);
     688           4 :                         *state->end = '/';
     689             :                         /*
     690             :                          * We need to return the fact that the
     691             :                          * intermediate name resolution failed. This
     692             :                          * is used to return an error of ERRbadpath
     693             :                          * rather than ERRbadfile. Some Windows
     694             :                          * applications depend on the difference between
     695             :                          * these two errors.
     696             :                          */
     697           4 :                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     698             :                 }
     699        2832 :                 return NT_STATUS_OK;
     700             :         }
     701             : 
     702             :         /* Stat failed - ensure we don't use it. */
     703      283278 :         SET_STAT_INVALID(state->smb_fname->st);
     704             : 
     705      283278 :         if (state->posix_pathnames) {
     706             :                 /*
     707             :                  * For posix_pathnames, we're done.
     708             :                  * Don't blunder into the name_has_wildcard OR
     709             :                  * get_real_filename() codepaths as they may
     710             :                  * be doing case insensitive lookups. So when
     711             :                  * creating a new POSIX directory Foo they might
     712             :                  * match on name foo.
     713             :                  *
     714             :                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
     715             :                  */
     716         692 :                 if (state->end != NULL) {
     717          56 :                         const char *morepath = NULL;
     718             :                         /*
     719             :                          * If this is intermediate we must
     720             :                          * restore the full path.
     721             :                          */
     722          56 :                         *state->end = '/';
     723             :                         /*
     724             :                          * If there are any more components
     725             :                          * after the failed LSTAT we cannot
     726             :                          * continue.
     727             :                          */
     728          56 :                         morepath = strchr(state->end + 1, '/');
     729          56 :                         if (morepath != NULL) {
     730           0 :                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     731             :                         }
     732             :                 }
     733         692 :                 if (errno == ENOENT) {
     734             :                         /* New file or directory. */
     735         692 :                         state->done = true;
     736         692 :                         return NT_STATUS_OK;
     737             :                 }
     738           0 :                 if ((errno == EACCES) &&
     739           0 :                     (state->ucf_flags & UCF_PREP_CREATEFILE)) {
     740             :                         /* POSIX Dropbox case. */
     741           0 :                         errno = 0;
     742           0 :                         state->done = true;
     743           0 :                         return NT_STATUS_OK;
     744             :                 }
     745           0 :                 return map_nt_error_from_unix(errno);
     746             :         }
     747             : 
     748             :         /*
     749             :          * Reset errno so we can detect
     750             :          * directory open errors.
     751             :          */
     752      282586 :         errno = 0;
     753             : 
     754             :         /*
     755             :          * Try to find this part of the path in the directory.
     756             :          */
     757             : 
     758      282586 :         if (state->name_has_wildcard) {
     759           0 :                 return unix_convert_step_search_fail(state);
     760             :         }
     761             : 
     762      282586 :         dname = (struct smb_filename) {
     763      282586 :                 .base_name = state->dirpath,
     764      282586 :                 .twrp = state->smb_fname->twrp,
     765             :         };
     766             : 
     767             :         /* handle null paths */
     768      282586 :         if ((dname.base_name == NULL) || (dname.base_name[0] == '\0')) {
     769           0 :                 dname.base_name = dot;
     770             :         }
     771             : 
     772      565172 :         ret = get_real_filename(state->conn,
     773             :                                 &dname,
     774      282586 :                                 state->name,
     775             :                                 talloc_tos(),
     776             :                                 &found_name);
     777      282586 :         if (ret != 0) {
     778      281047 :                 return unix_convert_step_search_fail(state);
     779             :         }
     780             : 
     781             :         /*
     782             :          * Restore the rest of the string. If the string was
     783             :          * mangled the size may have changed.
     784             :          */
     785        1539 :         if (state->end) {
     786             :                 char *tmp;
     787         682 :                 size_t name_ofs =
     788         682 :                         state->name - state->smb_fname->base_name;
     789             : 
     790         682 :                 if (!ISDOT(state->dirpath)) {
     791         548 :                         tmp = talloc_asprintf(state->smb_fname,
     792             :                                               "%s/%s/%s", state->dirpath,
     793         548 :                                               found_name, state->end+1);
     794             :                 }
     795             :                 else {
     796         134 :                         tmp = talloc_asprintf(state->smb_fname,
     797             :                                               "%s/%s", found_name,
     798         134 :                                               state->end+1);
     799             :                 }
     800         682 :                 if (tmp == NULL) {
     801           0 :                         DBG_ERR("talloc_asprintf failed\n");
     802           0 :                         return NT_STATUS_NO_MEMORY;
     803             :                 }
     804         682 :                 TALLOC_FREE(state->smb_fname->base_name);
     805         682 :                 state->smb_fname->base_name = tmp;
     806         682 :                 state->name = state->smb_fname->base_name + name_ofs;
     807         682 :                 state->end = state->name + strlen(found_name);
     808         682 :                 *state->end = '\0';
     809             :         } else {
     810             :                 char *tmp;
     811         857 :                 size_t name_ofs =
     812         857 :                         state->name - state->smb_fname->base_name;
     813             : 
     814         857 :                 if (!ISDOT(state->dirpath)) {
     815         619 :                         tmp = talloc_asprintf(state->smb_fname,
     816             :                                               "%s/%s", state->dirpath,
     817             :                                               found_name);
     818             :                 } else {
     819         238 :                         tmp = talloc_strdup(state->smb_fname,
     820             :                                             found_name);
     821             :                 }
     822         857 :                 if (tmp == NULL) {
     823           0 :                         DBG_ERR("talloc failed\n");
     824           0 :                         return NT_STATUS_NO_MEMORY;
     825             :                 }
     826         857 :                 TALLOC_FREE(state->smb_fname->base_name);
     827         857 :                 state->smb_fname->base_name = tmp;
     828         857 :                 state->name = state->smb_fname->base_name + name_ofs;
     829             : 
     830             :                 /*
     831             :                  * We just scanned for, and found the end of
     832             :                  * the path. We must return a valid stat struct
     833             :                  * if it exists. JRA.
     834             :                  */
     835             : 
     836         857 :                 ret = vfs_stat(state->conn, state->smb_fname);
     837         857 :                 if (ret != 0) {
     838         660 :                         SET_STAT_INVALID(state->smb_fname->st);
     839             :                 }
     840             :         }
     841             : 
     842        1539 :         TALLOC_FREE(found_name);
     843        1539 :         return NT_STATUS_OK;
     844             : }
     845             : 
     846      297657 : static NTSTATUS unix_convert_step(struct uc_state *state)
     847             : {
     848             :         NTSTATUS status;
     849             : 
     850             :         /*
     851             :          * Pinpoint the end of this section of the filename.
     852             :          */
     853             :         /* mb safe. '/' can't be in any encoded char. */
     854      297657 :         state->end = strchr(state->name, '/');
     855             : 
     856             :         /*
     857             :          * Chop the name at this point.
     858             :          */
     859      297657 :         if (state->end != NULL) {
     860        4036 :                 *state->end = 0;
     861             :         }
     862             : 
     863      297657 :         DBG_DEBUG("dirpath [%s] name [%s]\n", state->dirpath, state->name);
     864             : 
     865             :         /* The name cannot have a component of "." */
     866             : 
     867      297657 :         if (ISDOT(state->name)) {
     868           0 :                 if (state->end == NULL)  {
     869             :                         /* Error code at the end of a pathname. */
     870           0 :                         return NT_STATUS_OBJECT_NAME_INVALID;
     871             :                 }
     872           0 :                 return determine_path_error(state->end+1,
     873           0 :                                             state->allow_wcard_last_component,
     874           0 :                                             state->posix_pathnames);
     875             :         }
     876             : 
     877             :         /* The name cannot have a wildcard if it's not
     878             :            the last component. */
     879             : 
     880      297657 :         if (!state->posix_pathnames) {
     881      296961 :                 state->name_has_wildcard = ms_has_wild(state->name);
     882             :         }
     883             : 
     884             :         /* Wildcards never valid within a pathname. */
     885      297657 :         if (state->name_has_wildcard && state->end != NULL) {
     886           0 :                 return NT_STATUS_OBJECT_NAME_INVALID;
     887             :         }
     888             : 
     889             :         /* Skip the stat call if it's a wildcard end. */
     890      297657 :         if (state->name_has_wildcard) {
     891       11543 :                 DBG_DEBUG("Wildcard [%s]\n", state->name);
     892       11543 :                 state->done = true;
     893       11543 :                 return NT_STATUS_OK;
     894             :         }
     895             : 
     896      286114 :         status = unix_convert_step_stat(state);
     897      286114 :         if (!NT_STATUS_IS_OK(status)) {
     898         655 :                 return status;
     899             :         }
     900      285459 :         if (state->done) {
     901      281088 :                 return NT_STATUS_OK;
     902             :         }
     903             : 
     904             :         /*
     905             :          * Add to the dirpath that we have resolved so far.
     906             :          */
     907             : 
     908        7755 :         if (!ISDOT(state->dirpath)) {
     909        3384 :                 char *tmp = talloc_asprintf(state->mem_ctx,
     910             :                                             "%s/%s", state->dirpath, state->name);
     911        3384 :                 if (!tmp) {
     912           0 :                         DBG_ERR("talloc_asprintf failed\n");
     913           0 :                         return NT_STATUS_NO_MEMORY;
     914             :                 }
     915        3384 :                 TALLOC_FREE(state->dirpath);
     916        3384 :                 state->dirpath = tmp;
     917             :         }
     918             :         else {
     919         987 :                 TALLOC_FREE(state->dirpath);
     920         987 :                 if (!(state->dirpath = talloc_strdup(state->mem_ctx,state->name))) {
     921           0 :                         DBG_ERR("talloc_strdup failed\n");
     922           0 :                         return NT_STATUS_NO_MEMORY;
     923             :                 }
     924             :         }
     925             : 
     926             :         /*
     927             :          * Cache the dirpath thus far. Don't cache a name with mangled
     928             :          * or wildcard components as this can change the size.
     929             :          */
     930        4371 :         if(!state->component_was_mangled && !state->name_has_wildcard) {
     931       12777 :                 stat_cache_add(state->orig_path,
     932        4259 :                                state->dirpath,
     933        4259 :                                state->smb_fname->twrp,
     934        4259 :                                state->conn->case_sensitive);
     935             :         }
     936             : 
     937             :         /*
     938             :          * Restore the / that we wiped out earlier.
     939             :          */
     940        4371 :         if (state->end != NULL) {
     941        3325 :                 *state->end = '/';
     942             :         }
     943             : 
     944        4371 :         return NT_STATUS_OK;
     945             : }
     946             : 
     947      599332 : NTSTATUS unix_convert(TALLOC_CTX *mem_ctx,
     948             :                       connection_struct *conn,
     949             :                       const char *orig_path,
     950             :                       NTTIME twrp,
     951             :                       struct smb_filename **smb_fname_out,
     952             :                       uint32_t ucf_flags)
     953             : {
     954             :         struct uc_state uc_state;
     955      599332 :         struct uc_state *state = &uc_state;
     956             :         NTSTATUS status;
     957      599332 :         int ret = -1;
     958             : 
     959      599332 :         *state = (struct uc_state) {
     960             :                 .mem_ctx = mem_ctx,
     961             :                 .conn = conn,
     962             :                 .orig_path = orig_path,
     963             :                 .ucf_flags = ucf_flags,
     964      599332 :                 .posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES),
     965      599332 :                 .allow_wcard_last_component = (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP),
     966             :         };
     967             : 
     968      599332 :         *smb_fname_out = NULL;
     969             : 
     970      599332 :         state->smb_fname = talloc_zero(state->mem_ctx, struct smb_filename);
     971      599332 :         if (state->smb_fname == NULL) {
     972           0 :                 return NT_STATUS_NO_MEMORY;
     973             :         }
     974             : 
     975      599332 :         if (state->conn->printer) {
     976             :                 /* we don't ever use the filenames on a printer share as a
     977             :                         filename - so don't convert them */
     978           4 :                 state->smb_fname->base_name = talloc_strdup(
     979           2 :                         state->smb_fname, state->orig_path);
     980           2 :                 if (state->smb_fname->base_name == NULL) {
     981           0 :                         status = NT_STATUS_NO_MEMORY;
     982           0 :                         goto err;
     983             :                 }
     984           2 :                 goto done;
     985             :         }
     986             : 
     987      599330 :         state->smb_fname->flags = state->posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
     988             : 
     989      599330 :         DBG_DEBUG("Called on file [%s]\n", state->orig_path);
     990             : 
     991      599330 :         if (state->orig_path[0] == '/') {
     992           0 :                 DBG_ERR("Path [%s] starts with '/'\n", state->orig_path);
     993           0 :                 return NT_STATUS_OBJECT_NAME_INVALID;
     994             :         }
     995             : 
     996             :         /* Start with the full orig_path as given by the caller. */
     997     1188610 :         state->smb_fname->base_name = talloc_strdup(
     998      599330 :                 state->smb_fname, state->orig_path);
     999      599330 :         if (state->smb_fname->base_name == NULL) {
    1000           0 :                 DBG_ERR("talloc_strdup failed\n");
    1001           0 :                 status = NT_STATUS_NO_MEMORY;
    1002           0 :                 goto err;
    1003             :         }
    1004             : 
    1005             :         /* Canonicalize any @GMT- paths. */
    1006      599330 :         status = canonicalize_snapshot_path(state->smb_fname, ucf_flags, twrp);
    1007      599330 :         if (!NT_STATUS_IS_OK(status)) {
    1008           0 :                 goto err;
    1009             :         }
    1010             : 
    1011             :         /*
    1012             :          * If we trimmed down to a single '\0' character
    1013             :          * then we should use the "." directory to avoid
    1014             :          * searching the cache, but not if we are in a
    1015             :          * printing share.
    1016             :          * As we know this is valid we can return true here.
    1017             :          */
    1018             : 
    1019      599330 :         if (state->smb_fname->base_name[0] == '\0') {
    1020        5585 :                 state->smb_fname->base_name = talloc_strdup(state->smb_fname, ".");
    1021        5585 :                 if (state->smb_fname->base_name == NULL) {
    1022           0 :                         status = NT_STATUS_NO_MEMORY;
    1023           0 :                         goto err;
    1024             :                 }
    1025        5585 :                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
    1026           0 :                         status = map_nt_error_from_unix(errno);
    1027           0 :                         goto err;
    1028             :                 }
    1029        5585 :                 DBG_DEBUG("conversion finished [] -> [%s]\n",
    1030             :                           state->smb_fname->base_name);
    1031        5585 :                 goto done;
    1032             :         }
    1033             : 
    1034      593845 :         if (state->orig_path[0] == '.' && (state->orig_path[1] == '/' ||
    1035         100 :                                 state->orig_path[1] == '\0')) {
    1036             :                 /* Start of pathname can't be "." only. */
    1037         176 :                 if (state->orig_path[1] == '\0' || state->orig_path[2] == '\0') {
    1038          88 :                         status = NT_STATUS_OBJECT_NAME_INVALID;
    1039             :                 } else {
    1040         176 :                         status =determine_path_error(&state->orig_path[2],
    1041          88 :                             state->allow_wcard_last_component,
    1042          88 :                             state->posix_pathnames);
    1043             :                 }
    1044         176 :                 goto err;
    1045             :         }
    1046             : 
    1047             :         /*
    1048             :          * Large directory fix normalization. If we're case sensitive, and
    1049             :          * the case preserving parameters are set to "no", normalize the case of
    1050             :          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
    1051             :          * This is in conflict with the current (3.0.20) man page, but is
    1052             :          * what people expect from the "large directory howto". I'll update
    1053             :          * the man page. Thanks to jht@samba.org for finding this. JRA.
    1054             :          */
    1055             : 
    1056      593569 :         status = normalize_filename_case(state->conn, state->smb_fname->base_name);
    1057      593569 :         if (!NT_STATUS_IS_OK(status)) {
    1058           0 :                 DBG_ERR("normalize_filename_case %s failed\n",
    1059             :                                 state->smb_fname->base_name);
    1060           0 :                 goto err;
    1061             :         }
    1062             : 
    1063             :         /*
    1064             :          * Strip off the stream, and add it back when we're done with the
    1065             :          * base_name.
    1066             :          */
    1067      593569 :         if (!state->posix_pathnames) {
    1068      591951 :                 state->stream = strchr_m(state->smb_fname->base_name, ':');
    1069             : 
    1070      591951 :                 if (state->stream != NULL) {
    1071        6275 :                         char *tmp = talloc_strdup(state->smb_fname, state->stream);
    1072        6275 :                         if (tmp == NULL) {
    1073           0 :                                 status = NT_STATUS_NO_MEMORY;
    1074           0 :                                 goto err;
    1075             :                         }
    1076             :                         /*
    1077             :                          * Since this is actually pointing into
    1078             :                          * smb_fname->base_name this truncates base_name.
    1079             :                          */
    1080        6275 :                         *state->stream = '\0';
    1081        6275 :                         state->stream = tmp;
    1082             : 
    1083        6275 :                         if (state->smb_fname->base_name[0] == '\0') {
    1084             :                                 /*
    1085             :                                  * orig_name was just a stream name.
    1086             :                                  * This is a stream on the root of
    1087             :                                  * the share. Replace base_name with
    1088             :                                  * a "."
    1089             :                                  */
    1090         112 :                                 state->smb_fname->base_name =
    1091         112 :                                         talloc_strdup(state->smb_fname, ".");
    1092          56 :                                 if (state->smb_fname->base_name == NULL) {
    1093           0 :                                         status = NT_STATUS_NO_MEMORY;
    1094           0 :                                         goto err;
    1095             :                                 }
    1096          56 :                                 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
    1097           0 :                                         status = map_nt_error_from_unix(errno);
    1098           0 :                                         goto err;
    1099             :                                 }
    1100             :                                 /* dirpath must exist. */
    1101          56 :                                 state->dirpath = talloc_strdup(state->mem_ctx,".");
    1102          56 :                                 if (state->dirpath == NULL) {
    1103           0 :                                         status = NT_STATUS_NO_MEMORY;
    1104           0 :                                         goto err;
    1105             :                                 }
    1106          56 :                                 DBG_INFO("conversion finished [%s] -> [%s]\n",
    1107             :                                          state->orig_path,
    1108             :                                          state->smb_fname->base_name);
    1109          56 :                                 goto done;
    1110             :                         }
    1111             :                 }
    1112             :         }
    1113             : 
    1114      593513 :         state->name = state->smb_fname->base_name;
    1115             : 
    1116             :         /*
    1117             :          * If we're providing case insensitive semantics or
    1118             :          * the underlying filesystem is case insensitive,
    1119             :          * then a case-normalized hit in the stat-cache is
    1120             :          * authoritative. JRA.
    1121             :          *
    1122             :          * Note: We're only checking base_name.  The stream_name will be
    1123             :          * added and verified in build_stream_path().
    1124             :          */
    1125             : 
    1126      595909 :         if (!state->conn->case_sensitive ||
    1127        2396 :             !(state->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
    1128             :         {
    1129             :                 bool found;
    1130             : 
    1131     2344368 :                 found = stat_cache_lookup(state->conn,
    1132      591117 :                                           state->posix_pathnames,
    1133      581067 :                                           &state->smb_fname->base_name,
    1134             :                                           &state->dirpath,
    1135             :                                           &state->name,
    1136      581067 :                                           state->smb_fname->twrp,
    1137      581067 :                                           &state->smb_fname->st);
    1138      591117 :                 if (found) {
    1139      100731 :                         goto done;
    1140             :                 }
    1141             :         }
    1142             : 
    1143             :         /*
    1144             :          * Make sure "dirpath" is an allocated string, we use this for
    1145             :          * building the directories with talloc_asprintf and free it.
    1146             :          */
    1147             : 
    1148      483674 :         if (state->dirpath == NULL) {
    1149      311122 :                 state->dirpath = talloc_strdup(state->mem_ctx,".");
    1150      311122 :                 if (state->dirpath == NULL) {
    1151           0 :                         DBG_ERR("talloc_strdup failed\n");
    1152           0 :                         status = NT_STATUS_NO_MEMORY;
    1153           0 :                         goto err;
    1154             :                 }
    1155             :         }
    1156             : 
    1157             :         /*
    1158             :          * If we have a wildcard we must walk the path to
    1159             :          * find where the error is, even if case sensitive
    1160             :          * is true.
    1161             :          */
    1162             : 
    1163      483674 :         if (!state->posix_pathnames) {
    1164             :                 /* POSIX pathnames have no wildcards. */
    1165      482700 :                 state->name_has_wildcard = ms_has_wild(state->smb_fname->base_name);
    1166      482700 :                 if (state->name_has_wildcard && !state->allow_wcard_last_component) {
    1167             :                         /* Wildcard not valid anywhere. */
    1168         104 :                         status = NT_STATUS_OBJECT_NAME_INVALID;
    1169         104 :                         goto fail;
    1170             :                 }
    1171             :         }
    1172             : 
    1173      483570 :         DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
    1174             :                   state->smb_fname->base_name, state->dirpath, state->name);
    1175             : 
    1176      483570 :         if (!state->name_has_wildcard) {
    1177      471998 :                 int parent_stat_errno = 0;
    1178             : 
    1179             :                 /*
    1180             :                  * stat the name - if it exists then we can add the stream back (if
    1181             :                  * there was one) and be done!
    1182             :                  */
    1183             : 
    1184      471998 :                 ret = vfs_stat(state->conn, state->smb_fname);
    1185      471998 :                 if (ret == 0) {
    1186      187790 :                         status = check_for_dot_component(state->smb_fname);
    1187      187790 :                         if (!NT_STATUS_IS_OK(status)) {
    1188         380 :                                 goto fail;
    1189             :                         }
    1190             :                         /* Add the path (not including the stream) to the cache. */
    1191      562736 :                         stat_cache_add(state->orig_path,
    1192      187501 :                                        state->smb_fname->base_name,
    1193      187501 :                                        state->smb_fname->twrp,
    1194      187734 :                                        state->conn->case_sensitive);
    1195      187734 :                         DBG_DEBUG("Conversion of base_name finished "
    1196             :                                   "[%s] -> [%s]\n",
    1197             :                                   state->orig_path, state->smb_fname->base_name);
    1198      376415 :                         goto done;
    1199             :                 }
    1200             : 
    1201             :                 /* Stat failed - ensure we don't use it. */
    1202      284208 :                 SET_STAT_INVALID(state->smb_fname->st);
    1203             : 
    1204             :                 /*
    1205             :                  * Note: we must continue processing a path if we get EACCES
    1206             :                  * from stat. With NFS4 permissions the file might be lacking
    1207             :                  * READ_ATTR, but if the parent has LIST permissions we can
    1208             :                  * resolve the path in the path traversal loop down below.
    1209             :                  */
    1210             : 
    1211      284208 :                 if (errno == ENOENT) {
    1212             :                         /* Optimization when creating a new file - only
    1213             :                            the last component doesn't exist.
    1214             :                            NOTE : check_parent_exists() doesn't preserve errno.
    1215             :                         */
    1216      284180 :                         int saved_errno = errno;
    1217      851933 :                         status = check_parent_exists(state->mem_ctx,
    1218      284180 :                                                 state->conn,
    1219      284180 :                                                 state->posix_pathnames,
    1220      283573 :                                                 state->smb_fname,
    1221             :                                                 &state->dirpath,
    1222             :                                                 &state->name,
    1223             :                                                 &parent_stat_errno);
    1224      284180 :                         errno = saved_errno;
    1225      284180 :                         if (!NT_STATUS_IS_OK(status)) {
    1226           0 :                                 goto fail;
    1227             :                         }
    1228             :                 }
    1229             : 
    1230             :                 /*
    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
    1233             :                  * won't help.
    1234             :                  */
    1235             : 
    1236      284208 :                 if ((state->conn->case_sensitive || !(state->conn->fs_capabilities &
    1237        1452 :                                         FILE_CASE_SENSITIVE_SEARCH)) &&
    1238        1452 :                                 !mangle_is_mangled(state->smb_fname->base_name, state->conn->params)) {
    1239             : 
    1240        1448 :                         status = check_for_dot_component(state->smb_fname);
    1241        1448 :                         if (!NT_STATUS_IS_OK(status)) {
    1242          24 :                                 goto fail;
    1243             :                         }
    1244             : 
    1245             :                         /*
    1246             :                          * The stat failed. Could be ok as it could be
    1247             :                          * a new file.
    1248             :                          */
    1249             : 
    1250        1424 :                         if (errno == ENOTDIR || errno == ELOOP) {
    1251          20 :                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
    1252          20 :                                 goto fail;
    1253        1404 :                         } else if (errno == ENOENT) {
    1254             :                                 /*
    1255             :                                  * Was it a missing last component ?
    1256             :                                  * or a missing intermediate component ?
    1257             :                                  *
    1258             :                                  * Optimization.
    1259             :                                  *
    1260             :                                  * For this code path we can guarantee that
    1261             :                                  * we have gone through check_parent_exists()
    1262             :                                  * and it returned NT_STATUS_OK.
    1263             :                                  *
    1264             :                                  * Either there was no parent component (".")
    1265             :                                  * parent_stat_errno == 0 and we have a missing
    1266             :                                  * last component here.
    1267             :                                  *
    1268             :                                  * OR check_parent_exists() called STAT/LSTAT
    1269             :                                  * and if it failed parent_stat_errno has been
    1270             :                                  * set telling us if the parent existed or not.
    1271             :                                  *
    1272             :                                  * Either way we can avoid another STAT/LSTAT
    1273             :                                  * system call on the parent here.
    1274             :                                  */
    1275        2808 :                                 if (parent_stat_errno == ENOTDIR ||
    1276        2584 :                                                 parent_stat_errno == ENOENT ||
    1277        1180 :                                                 parent_stat_errno == ELOOP) {
    1278         224 :                                         status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
    1279         224 :                                         goto fail;
    1280             :                                 }
    1281             : 
    1282             :                                 /*
    1283             :                                  * Missing last component is ok - new file.
    1284             :                                  * Also deal with permission denied elsewhere.
    1285             :                                  * Just drop out to done.
    1286             :                                  */
    1287        1180 :                                 goto done;
    1288             :                         }
    1289             :                 }
    1290             :         } else {
    1291             :                 /*
    1292             :                  * We have a wildcard in the pathname.
    1293             :                  *
    1294             :                  * Optimization for common case where the wildcard
    1295             :                  * is in the last component and the client already
    1296             :                  * sent the correct case.
    1297             :                  * NOTE : check_parent_exists() doesn't preserve errno.
    1298             :                  */
    1299       11572 :                 int saved_errno = errno;
    1300       34614 :                 status = check_parent_exists(state->mem_ctx,
    1301       11572 :                                         state->conn,
    1302       11572 :                                         state->posix_pathnames,
    1303       11572 :                                         state->smb_fname,
    1304             :                                         &state->dirpath,
    1305             :                                         &state->name,
    1306             :                                         NULL);
    1307       11572 :                 errno = saved_errno;
    1308       11572 :                 if (!NT_STATUS_IS_OK(status)) {
    1309           0 :                         goto fail;
    1310             :                 }
    1311             :         }
    1312             : 
    1313             :         /*
    1314             :          * is_mangled() was changed to look at an entire pathname, not
    1315             :          * just a component. JRA.
    1316             :          */
    1317             : 
    1318      294332 :         if (mangle_is_mangled(state->name, state->conn->params)) {
    1319         156 :                 state->component_was_mangled = true;
    1320             :         }
    1321             : 
    1322             :         /*
    1323             :          * Now we need to recursively match the name against the real
    1324             :          * directory structure.
    1325             :          */
    1326             : 
    1327             :         /*
    1328             :          * Match each part of the path name separately, trying the names
    1329             :          * as is first, then trying to scan the directory for matching names.
    1330             :          */
    1331             : 
    1332      297994 :         for (; state->name ; state->name = (state->end ? state->end + 1:(char *)NULL)) {
    1333      297657 :                 status = unix_convert_step(state);
    1334      297657 :                 if (!NT_STATUS_IS_OK(status)) {
    1335         655 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
    1336           0 :                                 goto err;
    1337             :                         }
    1338         651 :                         goto fail;
    1339             :                 }
    1340      297002 :                 if (state->done) {
    1341      291929 :                         goto done;
    1342             :                 }
    1343             :         }
    1344             : 
    1345             :         /*
    1346             :          * Cache the full path. Don't cache a name with mangled or wildcard
    1347             :          * components as this can change the size.
    1348             :          */
    1349             : 
    1350        1986 :         if(!state->component_was_mangled && !state->name_has_wildcard) {
    1351        2820 :                 stat_cache_add(state->orig_path,
    1352         940 :                                state->smb_fname->base_name,
    1353         940 :                                state->smb_fname->twrp,
    1354         940 :                                state->conn->case_sensitive);
    1355             :         }
    1356             : 
    1357             :         /*
    1358             :          * The name has been resolved.
    1359             :          */
    1360             : 
    1361      607989 :  done:
    1362             :         /* Add back the stream if one was stripped off originally. */
    1363      598073 :         if (state->stream != NULL) {
    1364        6275 :                 state->smb_fname->stream_name = state->stream;
    1365             : 
    1366             :                 /* Check path now that the base_name has been converted. */
    1367        6275 :                 status = build_stream_path(state->mem_ctx, state->conn, state->smb_fname);
    1368        6275 :                 if (!NT_STATUS_IS_OK(status)) {
    1369          48 :                         goto fail;
    1370             :                 }
    1371             :         }
    1372             : 
    1373      598025 :         DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
    1374             :                    state->orig_path, smb_fname_str_dbg(state->smb_fname));
    1375             : 
    1376      598025 :         TALLOC_FREE(state->dirpath);
    1377      598025 :         *smb_fname_out = state->smb_fname;
    1378      598025 :         return NT_STATUS_OK;
    1379        1127 :  fail:
    1380        1131 :         DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
    1381             :                   state->dirpath, state->name);
    1382        1131 :         if ((state->dirpath != NULL) && !ISDOT(state->dirpath)) {
    1383         338 :                 state->smb_fname->base_name = talloc_asprintf(
    1384         169 :                         state->smb_fname,
    1385             :                         "%s/%s",
    1386             :                         state->dirpath,
    1387             :                         state->name);
    1388             :         } else {
    1389         962 :                 state->smb_fname->base_name = talloc_strdup(
    1390         962 :                         state->smb_fname, state->name);
    1391             :         }
    1392        1131 :         if (state->smb_fname->base_name == NULL) {
    1393           0 :                 DBG_ERR("talloc_asprintf failed\n");
    1394           0 :                 status = NT_STATUS_NO_MEMORY;
    1395           0 :                 goto err;
    1396             :         }
    1397             : 
    1398        1131 :         *smb_fname_out = state->smb_fname;
    1399        1131 :         TALLOC_FREE(state->dirpath);
    1400        1131 :         return status;
    1401         176 :  err:
    1402         176 :         TALLOC_FREE(state->smb_fname);
    1403         176 :         return status;
    1404             : }
    1405             : 
    1406             : /****************************************************************************
    1407             :  Ensure a path is not vetoed.
    1408             : ****************************************************************************/
    1409             : 
    1410      625188 : static NTSTATUS check_veto_path(connection_struct *conn,
    1411             :                         const struct smb_filename *smb_fname)
    1412             : {
    1413      625188 :         const char *name = smb_fname->base_name;
    1414             : 
    1415      625188 :         if (IS_VETO_PATH(conn, name))  {
    1416             :                 /* Is it not dot or dot dot. */
    1417           0 :                 if (!(ISDOT(name) || ISDOTDOT(name))) {
    1418           0 :                         DEBUG(5,("check_veto_path: file path name %s vetoed\n",
    1419             :                                                 name));
    1420           0 :                         return map_nt_error_from_unix(ENOENT);
    1421             :                 }
    1422             :         }
    1423      625188 :         return NT_STATUS_OK;
    1424             : }
    1425             : 
    1426             : /****************************************************************************
    1427             :  Check a filename - possibly calling check_reduced_name.
    1428             :  This is called by every routine before it allows an operation on a filename.
    1429             :  It does any final confirmation necessary to ensure that the filename is
    1430             :  a valid one for the user to access.
    1431             : ****************************************************************************/
    1432             : 
    1433      624590 : NTSTATUS check_name(connection_struct *conn,
    1434             :                         const struct smb_filename *smb_fname)
    1435             : {
    1436      624590 :         NTSTATUS status = check_veto_path(conn, smb_fname);
    1437             : 
    1438      624590 :         if (!NT_STATUS_IS_OK(status)) {
    1439           0 :                 return status;
    1440             :         }
    1441             : 
    1442      624590 :         if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
    1443      623642 :                 status = check_reduced_name(conn, NULL, smb_fname);
    1444      623642 :                 if (!NT_STATUS_IS_OK(status)) {
    1445        1590 :                         DEBUG(5,("check_name: name %s failed with %s\n",
    1446             :                                         smb_fname->base_name,
    1447             :                                         nt_errstr(status)));
    1448        1590 :                         return status;
    1449             :                 }
    1450             :         }
    1451             : 
    1452      623000 :         return NT_STATUS_OK;
    1453             : }
    1454             : 
    1455             : /****************************************************************************
    1456             :  Must be called as root. Creates the struct privilege_paths
    1457             :  attached to the struct smb_request if this call is successful.
    1458             : ****************************************************************************/
    1459             : 
    1460           0 : static NTSTATUS check_name_with_privilege(connection_struct *conn,
    1461             :                 struct smb_request *smbreq,
    1462             :                 const struct smb_filename *smb_fname)
    1463             : {
    1464           0 :         NTSTATUS status = check_veto_path(conn, smb_fname);
    1465             : 
    1466           0 :         if (!NT_STATUS_IS_OK(status)) {
    1467           0 :                 return status;
    1468             :         }
    1469           0 :         return check_reduced_name_with_privilege(conn,
    1470             :                         smb_fname,
    1471             :                         smbreq);
    1472             : }
    1473             : 
    1474             : /****************************************************************************
    1475             :  Check if two filenames are equal.
    1476             :  This needs to be careful about whether we are case sensitive.
    1477             : ****************************************************************************/
    1478             : 
    1479   206301814 : static bool fname_equal(const char *name1, const char *name2,
    1480             :                 bool case_sensitive)
    1481             : {
    1482             :         /* Normal filename handling */
    1483   206301814 :         if (case_sensitive) {
    1484           0 :                 return(strcmp(name1,name2) == 0);
    1485             :         }
    1486             : 
    1487   206301814 :         return(strequal(name1,name2));
    1488             : }
    1489             : 
    1490        3930 : static bool sname_equal(const char *name1, const char *name2,
    1491             :                 bool case_sensitive)
    1492             : {
    1493             :         bool match;
    1494        3930 :         const char *s1 = NULL;
    1495        3930 :         const char *s2 = NULL;
    1496             :         size_t n1;
    1497             :         size_t n2;
    1498        3930 :         const char *e1 = NULL;
    1499        3930 :         const char *e2 = NULL;
    1500        3930 :         char *c1 = NULL;
    1501        3930 :         char *c2 = NULL;
    1502             : 
    1503        3930 :         match = fname_equal(name1, name2, case_sensitive);
    1504        3930 :         if (match) {
    1505          28 :                 return true;
    1506             :         }
    1507             : 
    1508        3902 :         if (name1[0] != ':') {
    1509           0 :                 return false;
    1510             :         }
    1511        3902 :         if (name2[0] != ':') {
    1512           0 :                 return false;
    1513             :         }
    1514        3902 :         s1 = &name1[1];
    1515        3902 :         e1 = strchr(s1, ':');
    1516        3902 :         if (e1 == NULL) {
    1517         506 :                 n1 = strlen(s1);
    1518             :         } else {
    1519        3396 :                 n1 = PTR_DIFF(e1, s1);
    1520             :         }
    1521        3902 :         s2 = &name2[1];
    1522        3902 :         e2 = strchr(s2, ':');
    1523        3902 :         if (e2 == NULL) {
    1524           0 :                 n2 = strlen(s2);
    1525             :         } else {
    1526        3902 :                 n2 = PTR_DIFF(e2, s2);
    1527             :         }
    1528             : 
    1529             :         /* Normal filename handling */
    1530        3902 :         if (case_sensitive) {
    1531           0 :                 return (strncmp(s1, s2, n1) == 0);
    1532             :         }
    1533             : 
    1534             :         /*
    1535             :          * We can't use strnequal() here
    1536             :          * as it takes the number of codepoints
    1537             :          * and not the number of bytes.
    1538             :          *
    1539             :          * So we make a copy before calling
    1540             :          * strequal().
    1541             :          *
    1542             :          * Note that we TALLOC_FREE() in reverse order
    1543             :          * in order to avoid memory fragmentation.
    1544             :          */
    1545             : 
    1546        3902 :         c1 = talloc_strndup(talloc_tos(), s1, n1);
    1547        3902 :         c2 = talloc_strndup(talloc_tos(), s2, n2);
    1548        3902 :         if (c1 == NULL || c2 == NULL) {
    1549           0 :                 TALLOC_FREE(c2);
    1550           0 :                 TALLOC_FREE(c1);
    1551           0 :                 return (strncmp(s1, s2, n1) == 0);
    1552             :         }
    1553             : 
    1554        3902 :         match = strequal(c1, c2);
    1555        3902 :         TALLOC_FREE(c2);
    1556        3902 :         TALLOC_FREE(c1);
    1557        3902 :         return match;
    1558             : }
    1559             : 
    1560             : /****************************************************************************
    1561             :  Scan a directory to find a filename, matching without case sensitivity.
    1562             :  If the name looks like a mangled name then try via the mangling functions
    1563             : ****************************************************************************/
    1564             : 
    1565      282586 : int get_real_filename_full_scan(connection_struct *conn,
    1566             :                                 const char *path,
    1567             :                                 const char *name,
    1568             :                                 bool mangled,
    1569             :                                 TALLOC_CTX *mem_ctx,
    1570             :                                 char **found_name)
    1571             : {
    1572             :         struct smb_Dir *cur_dir;
    1573      282586 :         const char *dname = NULL;
    1574      282586 :         char *talloced = NULL;
    1575      282586 :         char *unmangled_name = NULL;
    1576             :         long curpos;
    1577      282586 :         struct smb_filename *smb_fname = NULL;
    1578             : 
    1579             :         /* handle null paths */
    1580      282586 :         if ((path == NULL) || (*path == 0)) {
    1581           8 :                 path = ".";
    1582             :         }
    1583             : 
    1584             :         /* If we have a case-sensitive filesystem, it doesn't do us any
    1585             :          * good to search for a name. If a case variation of the name was
    1586             :          * there, then the original stat(2) would have found it.
    1587             :          */
    1588      282586 :         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
    1589           0 :                 errno = ENOENT;
    1590           0 :                 return -1;
    1591             :         }
    1592             : 
    1593             :         /*
    1594             :          * The incoming name can be mangled, and if we de-mangle it
    1595             :          * here it will not compare correctly against the filename (name2)
    1596             :          * read from the directory and then mangled by the name_to_8_3()
    1597             :          * call. We need to mangle both names or neither.
    1598             :          * (JRA).
    1599             :          *
    1600             :          * Fix for bug found by Dina Fine. If in case sensitive mode then
    1601             :          * the mangle cache is no good (3 letter extension could be wrong
    1602             :          * case - so don't demangle in this case - leave as mangled and
    1603             :          * allow the mangling of the directory entry read (which is done
    1604             :          * case insensitively) to match instead. This will lead to more
    1605             :          * false positive matches but we fail completely without it. JRA.
    1606             :          */
    1607             : 
    1608      282586 :         if (mangled && !conn->case_sensitive) {
    1609         304 :                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
    1610             :                                                        &unmangled_name,
    1611         304 :                                                        conn->params);
    1612         152 :                 if (!mangled) {
    1613             :                         /* Name is now unmangled. */
    1614         152 :                         name = unmangled_name;
    1615             :                 }
    1616             :         }
    1617             : 
    1618      282586 :         smb_fname = synthetic_smb_fname(talloc_tos(),
    1619             :                                         path,
    1620             :                                         NULL,
    1621             :                                         NULL,
    1622             :                                         0,
    1623             :                                         0);
    1624      282586 :         if (smb_fname == NULL) {
    1625           0 :                 TALLOC_FREE(unmangled_name);
    1626           0 :                 return -1;
    1627             :         }
    1628             : 
    1629             :         /* open the directory */
    1630      282586 :         if (!(cur_dir = OpenDir(talloc_tos(), conn, smb_fname, NULL, 0))) {
    1631         411 :                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
    1632         411 :                 TALLOC_FREE(unmangled_name);
    1633         411 :                 TALLOC_FREE(smb_fname);
    1634         411 :                 return -1;
    1635             :         }
    1636             : 
    1637      282175 :         TALLOC_FREE(smb_fname);
    1638             : 
    1639             :         /* now scan for matching names */
    1640      282175 :         curpos = 0;
    1641   207425049 :         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
    1642             : 
    1643             :                 /* Is it dot or dot dot. */
    1644   206862238 :                 if (ISDOT(dname) || ISDOTDOT(dname)) {
    1645      564350 :                         TALLOC_FREE(talloced);
    1646      564350 :                         continue;
    1647             :                 }
    1648             : 
    1649             :                 /*
    1650             :                  * At this point dname is the unmangled name.
    1651             :                  * name is either mangled or not, depending on the state
    1652             :                  * of the "mangled" variable. JRA.
    1653             :                  */
    1654             : 
    1655             :                 /*
    1656             :                  * Check mangled name against mangled name, or unmangled name
    1657             :                  * against unmangled name.
    1658             :                  */
    1659             : 
    1660   412595772 :                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
    1661   206297884 :                         fname_equal(name, dname, conn->case_sensitive)) {
    1662             :                         /* we've found the file, change it's name and return */
    1663        1539 :                         *found_name = talloc_strdup(mem_ctx, dname);
    1664        1539 :                         TALLOC_FREE(unmangled_name);
    1665        1539 :                         TALLOC_FREE(cur_dir);
    1666        1539 :                         if (!*found_name) {
    1667           0 :                                 errno = ENOMEM;
    1668           0 :                                 TALLOC_FREE(talloced);
    1669           0 :                                 return -1;
    1670             :                         }
    1671        1539 :                         TALLOC_FREE(talloced);
    1672        1536 :                         return 0;
    1673             :                 }
    1674   206296349 :                 TALLOC_FREE(talloced);
    1675             :         }
    1676             : 
    1677      280636 :         TALLOC_FREE(unmangled_name);
    1678      280636 :         TALLOC_FREE(cur_dir);
    1679      280636 :         errno = ENOENT;
    1680      280636 :         return -1;
    1681             : }
    1682             : 
    1683             : /****************************************************************************
    1684             :  Wrapper around the vfs get_real_filename and the full directory scan
    1685             :  fallback.
    1686             : ****************************************************************************/
    1687             : 
    1688      282586 : int get_real_filename(connection_struct *conn,
    1689             :                       struct smb_filename *path,
    1690             :                       const char *name,
    1691             :                       TALLOC_CTX *mem_ctx,
    1692             :                       char **found_name)
    1693             : {
    1694             :         int ret;
    1695             :         bool mangled;
    1696             : 
    1697      282586 :         mangled = mangle_is_mangled(name, conn->params);
    1698             : 
    1699      282586 :         if (mangled) {
    1700         312 :                 return get_real_filename_full_scan(conn,
    1701         156 :                                                    path->base_name,
    1702             :                                                    name,
    1703             :                                                    mangled,
    1704             :                                                    mem_ctx,
    1705             :                                                    found_name);
    1706             :         }
    1707             : 
    1708             :         /* Try the vfs first to take advantage of case-insensitive stat. */
    1709      282430 :         ret = SMB_VFS_GET_REAL_FILENAME(conn,
    1710             :                                         path,
    1711             :                                         name,
    1712             :                                         mem_ctx,
    1713             :                                         found_name);
    1714             : 
    1715             :         /*
    1716             :          * If the case-insensitive stat was successful, or returned an error
    1717             :          * other than EOPNOTSUPP then there is no need to fall back on the
    1718             :          * full directory scan.
    1719             :          */
    1720      282430 :         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
    1721          16 :                 return ret;
    1722             :         }
    1723             : 
    1724      564220 :         return get_real_filename_full_scan(conn,
    1725      282414 :                                            path->base_name,
    1726             :                                            name,
    1727             :                                            mangled,
    1728             :                                            mem_ctx,
    1729             :                                            found_name);
    1730             : }
    1731             : 
    1732        6275 : static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
    1733             :                                   connection_struct *conn,
    1734             :                                   struct smb_filename *smb_fname)
    1735             : {
    1736             :         NTSTATUS status;
    1737        6275 :         unsigned int i, num_streams = 0;
    1738        6275 :         struct stream_struct *streams = NULL;
    1739        6275 :         struct smb_filename *pathref = NULL;
    1740             : 
    1741        6275 :         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
    1742        2228 :                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
    1743        2228 :                 return NT_STATUS_OK;
    1744             :         }
    1745             : 
    1746        4047 :         if (errno != ENOENT) {
    1747          48 :                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
    1748          48 :                 status = map_nt_error_from_unix(errno);
    1749          48 :                 goto fail;
    1750             :         }
    1751             : 
    1752        3999 :         if (smb_fname->fsp == NULL) {
    1753        7998 :                 status = synthetic_pathref(mem_ctx,
    1754             :                                         conn->cwd_fsp,
    1755        3999 :                                         smb_fname->base_name,
    1756             :                                         NULL,
    1757             :                                         NULL,
    1758             :                                         smb_fname->twrp,
    1759             :                                         smb_fname->flags,
    1760             :                                         &pathref);
    1761        3999 :                 if (!NT_STATUS_IS_OK(status)) {
    1762         206 :                         if (NT_STATUS_EQUAL(status,
    1763             :                                 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    1764         206 :                                 TALLOC_FREE(pathref);
    1765         206 :                                 SET_STAT_INVALID(smb_fname->st);
    1766         206 :                                 return NT_STATUS_OK;
    1767             :                         }
    1768           0 :                         DBG_DEBUG("synthetic_pathref failed: %s\n",
    1769             :                                   nt_errstr(status));
    1770           0 :                         goto fail;
    1771             :                 }
    1772             :         } else {
    1773           0 :                 pathref = smb_fname;
    1774             :         }
    1775             : 
    1776             :         /* Fall back to a case-insensitive scan of all streams on the file. */
    1777        3793 :         status = vfs_fstreaminfo(pathref->fsp, mem_ctx,
    1778             :                                 &num_streams, &streams);
    1779        3793 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    1780           0 :                 SET_STAT_INVALID(smb_fname->st);
    1781           0 :                 TALLOC_FREE(pathref);
    1782           0 :                 return NT_STATUS_OK;
    1783             :         }
    1784             : 
    1785        3793 :         if (!NT_STATUS_IS_OK(status)) {
    1786           0 :                 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status)));
    1787           0 :                 goto fail;
    1788             :         }
    1789             : 
    1790        7662 :         for (i=0; i<num_streams; i++) {
    1791        3930 :                 DEBUG(10, ("comparing [%s] and [%s]: ",
    1792             :                            smb_fname->stream_name, streams[i].name));
    1793        3930 :                 if (sname_equal(smb_fname->stream_name, streams[i].name,
    1794        3930 :                                 conn->case_sensitive)) {
    1795          60 :                         DEBUGADD(10, ("equal\n"));
    1796          60 :                         break;
    1797             :                 }
    1798        3870 :                 DEBUGADD(10, ("not equal\n"));
    1799             :         }
    1800             : 
    1801             :         /* Couldn't find the stream. */
    1802        3793 :         if (i == num_streams) {
    1803        3733 :                 SET_STAT_INVALID(smb_fname->st);
    1804        3733 :                 TALLOC_FREE(pathref);
    1805        3733 :                 TALLOC_FREE(streams);
    1806        3733 :                 return NT_STATUS_OK;
    1807             :         }
    1808             : 
    1809          60 :         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
    1810             :                 smb_fname->stream_name, streams[i].name));
    1811             : 
    1812             : 
    1813          60 :         TALLOC_FREE(smb_fname->stream_name);
    1814          60 :         smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
    1815          60 :         if (smb_fname->stream_name == NULL) {
    1816           0 :                 status = NT_STATUS_NO_MEMORY;
    1817           0 :                 goto fail;
    1818             :         }
    1819             : 
    1820          60 :         SET_STAT_INVALID(smb_fname->st);
    1821             : 
    1822          60 :         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
    1823          60 :                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
    1824             :         }
    1825          60 :         status = NT_STATUS_OK;
    1826         108 :  fail:
    1827         108 :         TALLOC_FREE(pathref);
    1828         108 :         TALLOC_FREE(streams);
    1829         108 :         return status;
    1830             : }
    1831             : 
    1832             : /*
    1833             :  * Lightweight function to just get last component
    1834             :  * for rename / enumerate directory calls.
    1835             :  */
    1836             : 
    1837       49857 : char *get_original_lcomp(TALLOC_CTX *ctx,
    1838             :                         connection_struct *conn,
    1839             :                         const char *filename_in,
    1840             :                         uint32_t ucf_flags)
    1841             : {
    1842       49857 :         struct smb_filename *smb_fname = NULL;
    1843       49857 :         char *last_slash = NULL;
    1844             :         char *orig_lcomp;
    1845       49857 :         char *fname = NULL;
    1846             :         NTSTATUS status;
    1847             : 
    1848       49857 :         if (ucf_flags & UCF_DFS_PATHNAME) {
    1849          32 :                 status = dfs_redirect(ctx,
    1850             :                                 conn,
    1851             :                                 filename_in,
    1852             :                                 ucf_flags,
    1853          64 :                                 !conn->sconn->using_smb2,
    1854          32 :                                 &fname);
    1855          32 :                 if (!NT_STATUS_IS_OK(status)) {
    1856           0 :                         DBG_DEBUG("dfs_redirect "
    1857             :                                 "failed for name %s with %s\n",
    1858             :                                 filename_in,
    1859             :                                 nt_errstr(status));
    1860           0 :                         return NULL;
    1861             :                 }
    1862          32 :                 filename_in = fname;
    1863          32 :                 ucf_flags &= ~UCF_DFS_PATHNAME;
    1864             :         }
    1865             : 
    1866             :         /*
    1867             :          * NB. We don't need to care about
    1868             :          * is_fake_file_path(filename_in) here as these
    1869             :          * code paths don't ever return original_lcomp
    1870             :          * or use it anyway.
    1871             :          */
    1872             : 
    1873       49857 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    1874             :                 /*
    1875             :                  * Ensure we don't return a @GMT
    1876             :                  * value as the last component.
    1877             :                  */
    1878          68 :                 smb_fname = synthetic_smb_fname(ctx,
    1879             :                                         filename_in,
    1880             :                                         NULL,
    1881             :                                         NULL,
    1882             :                                         0,
    1883             :                                         0);
    1884          68 :                 if (smb_fname == NULL) {
    1885           0 :                         TALLOC_FREE(fname);
    1886           0 :                         return NULL;
    1887             :                 }
    1888          68 :                 status = canonicalize_snapshot_path(smb_fname,
    1889             :                                                     ucf_flags,
    1890             :                                                     0);
    1891          68 :                 if (!NT_STATUS_IS_OK(status)) {
    1892           0 :                         TALLOC_FREE(fname);
    1893           0 :                         TALLOC_FREE(smb_fname);
    1894           0 :                         return NULL;
    1895             :                 }
    1896          68 :                 filename_in = smb_fname->base_name;
    1897             :         }
    1898       49857 :         last_slash = strrchr(filename_in, '/');
    1899       49857 :         if (last_slash != NULL) {
    1900       42205 :                 orig_lcomp = talloc_strdup(ctx, last_slash+1);
    1901             :         } else {
    1902        7652 :                 orig_lcomp = talloc_strdup(ctx, filename_in);
    1903             :         }
    1904             :         /* We're done with any temp names here. */
    1905       49857 :         TALLOC_FREE(smb_fname);
    1906       49857 :         TALLOC_FREE(fname);
    1907       49857 :         if (orig_lcomp == NULL) {
    1908           0 :                 return NULL;
    1909             :         }
    1910       49857 :         status = normalize_filename_case(conn, orig_lcomp);
    1911       49857 :         if (!NT_STATUS_IS_OK(status)) {
    1912           0 :                 TALLOC_FREE(orig_lcomp);
    1913           0 :                 return NULL;
    1914             :         }
    1915       45182 :         return orig_lcomp;
    1916             : }
    1917             : 
    1918             : /**
    1919             :  * Go through all the steps to validate a filename.
    1920             :  *
    1921             :  * @param ctx           talloc_ctx to allocate memory with.
    1922             :  * @param conn          connection struct for vfs calls.
    1923             :  * @param smbreq        SMB request if we're using privileges.
    1924             :  * @param name_in       The unconverted name.
    1925             :  * @param ucf_flags     flags to pass through to unix_convert().
    1926             :  * @param twrp          Optional VSS time
    1927             :  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
    1928             :  *                      resolution detects a wildcard.
    1929             :  * @param _smb_fname    The final converted name will be allocated if the
    1930             :  *                      return is NT_STATUS_OK.
    1931             :  *
    1932             :  * @return NT_STATUS_OK if all operations completed successfully, appropriate
    1933             :  *         error otherwise.
    1934             :  */
    1935      594253 : static NTSTATUS filename_convert_internal(TALLOC_CTX *ctx,
    1936             :                                 connection_struct *conn,
    1937             :                                 struct smb_request *smbreq,
    1938             :                                 const char *name_in,
    1939             :                                 uint32_t ucf_flags,
    1940             :                                 NTTIME twrp,
    1941             :                                 struct smb_filename **_smb_fname)
    1942             : {
    1943      594253 :         struct smb_filename *smb_fname = NULL;
    1944             :         bool has_wild;
    1945             :         NTSTATUS status;
    1946             : 
    1947      594253 :         *_smb_fname = NULL;
    1948             : 
    1949      594253 :         if (ucf_flags & UCF_DFS_PATHNAME) {
    1950        8794 :                 char *fname = NULL;
    1951        8794 :                 status = dfs_redirect(ctx, conn,
    1952             :                                 name_in,
    1953             :                                 ucf_flags,
    1954       17588 :                                 !conn->sconn->using_smb2,
    1955        8794 :                                 &fname);
    1956        8794 :                 if (!NT_STATUS_IS_OK(status)) {
    1957         512 :                         DEBUG(10,("filename_convert_internal: dfs_redirect "
    1958             :                                 "failed for name %s with %s\n",
    1959             :                                 name_in,
    1960             :                                 nt_errstr(status) ));
    1961         512 :                         return status;
    1962             :                 }
    1963        8282 :                 name_in = fname;
    1964        8282 :                 ucf_flags &= ~UCF_DFS_PATHNAME;
    1965             :         }
    1966             : 
    1967      593741 :         if (is_fake_file_path(name_in)) {
    1968          21 :                 smb_fname = synthetic_smb_fname_split(ctx,
    1969             :                                         name_in,
    1970          21 :                                         (ucf_flags & UCF_POSIX_PATHNAMES));
    1971          21 :                 if (smb_fname == NULL) {
    1972           0 :                         return NT_STATUS_NO_MEMORY;
    1973             :                 }
    1974          21 :                 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
    1975          21 :                 smb_fname->st.st_ex_btime = (struct timespec){0, SAMBA_UTIME_OMIT};
    1976          21 :                 smb_fname->st.st_ex_atime = (struct timespec){0, SAMBA_UTIME_OMIT};
    1977          21 :                 smb_fname->st.st_ex_mtime = (struct timespec){0, SAMBA_UTIME_OMIT};
    1978          21 :                 smb_fname->st.st_ex_ctime = (struct timespec){0, SAMBA_UTIME_OMIT};
    1979             : 
    1980          21 :                 *_smb_fname = smb_fname;
    1981          21 :                 return NT_STATUS_OK;
    1982             :         }
    1983             : 
    1984      593720 :         status = unix_convert(ctx, conn, name_in, twrp, &smb_fname, ucf_flags);
    1985      593720 :         if (!NT_STATUS_IS_OK(status)) {
    1986        1307 :                 DEBUG(10,("filename_convert_internal: unix_convert failed "
    1987             :                         "for name %s with %s\n",
    1988             :                         name_in,
    1989             :                         nt_errstr(status) ));
    1990        1307 :                 return status;
    1991             :         }
    1992             : 
    1993      594039 :         if ((ucf_flags & UCF_POSIX_PATHNAMES) &&
    1994        2556 :             VALID_STAT(smb_fname->st) &&
    1995         930 :             S_ISLNK(smb_fname->st.st_ex_mode))
    1996             :         {
    1997         598 :                 status = check_veto_path(conn, smb_fname);
    1998        1196 :                 if (!NT_STATUS_IS_OK(status)) {
    1999           0 :                         TALLOC_FREE(smb_fname);
    2000           0 :                         return status;
    2001             :                 }
    2002      591815 :         } else if (!smbreq) {
    2003      591815 :                 status = check_name(conn, smb_fname);
    2004             :         } else {
    2005           0 :                 status = check_name_with_privilege(conn, smbreq,
    2006             :                                 smb_fname);
    2007             :         }
    2008      592413 :         if (!NT_STATUS_IS_OK(status)) {
    2009        1590 :                 DEBUG(3,("filename_convert_internal: check_name failed "
    2010             :                         "for name %s with %s\n",
    2011             :                         smb_fname_str_dbg(smb_fname),
    2012             :                         nt_errstr(status) ));
    2013        1590 :                 TALLOC_FREE(smb_fname);
    2014        1590 :                 return status;
    2015             :         }
    2016             : 
    2017      590823 :         has_wild = ms_has_wild(name_in);
    2018      590823 :         if (has_wild) {
    2019       11589 :                 DBG_DEBUG("[%s] contains wildcard, skipping pathref fsp\n",
    2020             :                           name_in);
    2021       11589 :                 *_smb_fname = smb_fname;
    2022       11589 :                 return NT_STATUS_OK;
    2023             :         }
    2024             : 
    2025      579234 :         if (!VALID_STAT(smb_fname->st)) {
    2026      284335 :                 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
    2027             :                           smb_fname_str_dbg(smb_fname));
    2028      284335 :                 *_smb_fname = smb_fname;
    2029      284335 :                 return NT_STATUS_OK;
    2030             :         }
    2031             : 
    2032      294899 :         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
    2033      294899 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    2034             :                 /*
    2035             :                  * We deal with symlinks here as we do in
    2036             :                  * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
    2037             :                  * the notable difference that there will be no fsp in
    2038             :                  * smb_fname->fsp.
    2039             :                  *
    2040             :                  * For Windows (non POSIX) clients fail with
    2041             :                  * NT_STATUS_OBJECT_NAME_NOT_FOUND.
    2042             :                  */
    2043        1196 :                 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH &&
    2044         598 :                     S_ISLNK(smb_fname->st.st_ex_mode))
    2045             :                 {
    2046         598 :                         status = NT_STATUS_OK;
    2047             :                 }
    2048             :         }
    2049      294899 :         if (!NT_STATUS_IS_OK(status)) {
    2050           0 :                 DBG_DEBUG("open_pathref_fsp [%s] failed: %s\n",
    2051             :                           smb_fname_str_dbg(smb_fname),
    2052             :                           nt_errstr(status));
    2053           0 :                 return status;
    2054             :         }
    2055             : 
    2056      294899 :         *_smb_fname = smb_fname;
    2057      294899 :         return status;
    2058             : }
    2059             : 
    2060             : /*
    2061             :  * Go through all the steps to validate a filename.
    2062             :  * Non-root version.
    2063             :  */
    2064             : 
    2065      594253 : NTSTATUS filename_convert(TALLOC_CTX *ctx,
    2066             :                                 connection_struct *conn,
    2067             :                                 const char *name_in,
    2068             :                                 uint32_t ucf_flags,
    2069             :                                 NTTIME twrp,
    2070             :                                 struct smb_filename **pp_smb_fname)
    2071             : {
    2072      594253 :         return filename_convert_internal(ctx,
    2073             :                                         conn,
    2074             :                                         NULL,
    2075             :                                         name_in,
    2076             :                                         ucf_flags,
    2077             :                                         twrp,
    2078             :                                         pp_smb_fname);
    2079             : }
    2080             : 
    2081             : /*
    2082             :  * Go through all the steps to validate a filename.
    2083             :  * root (privileged) version.
    2084             :  */
    2085             : 
    2086           0 : NTSTATUS filename_convert_with_privilege(TALLOC_CTX *ctx,
    2087             :                                 connection_struct *conn,
    2088             :                                 struct smb_request *smbreq,
    2089             :                                 const char *name_in,
    2090             :                                 uint32_t ucf_flags,
    2091             :                                 struct smb_filename **pp_smb_fname)
    2092             : {
    2093           0 :         return filename_convert_internal(ctx,
    2094             :                                         conn,
    2095             :                                         smbreq,
    2096             :                                         name_in,
    2097             :                                         ucf_flags,
    2098             :                                         0,
    2099             :                                         pp_smb_fname);
    2100             : }
    2101             : 
    2102             : /*
    2103             :  * Build the full path from a dirfsp and dirfsp relative name
    2104             :  */
    2105    10519410 : struct smb_filename *full_path_from_dirfsp_atname(
    2106             :         TALLOC_CTX *mem_ctx,
    2107             :         const struct files_struct *dirfsp,
    2108             :         const struct smb_filename *atname)
    2109             : {
    2110    10519410 :         struct smb_filename *fname = NULL;
    2111    10519410 :         char *path = NULL;
    2112             : 
    2113    11567713 :         if (dirfsp == dirfsp->conn->cwd_fsp ||
    2114     2096606 :             ISDOT(dirfsp->fsp_name->base_name) ||
    2115      983706 :             atname->base_name[0] == '/')
    2116             :         {
    2117     9535704 :                 path = talloc_strdup(mem_ctx, atname->base_name);
    2118             :         } else {
    2119     1967071 :                 path = talloc_asprintf(mem_ctx, "%s/%s",
    2120      983365 :                                        dirfsp->fsp_name->base_name,
    2121             :                                        atname->base_name);
    2122             :         }
    2123    10519410 :         if (path == NULL) {
    2124           0 :                 return NULL;
    2125             :         }
    2126             : 
    2127    21038820 :         fname = synthetic_smb_fname(mem_ctx,
    2128             :                                     path,
    2129    10519410 :                                     atname->stream_name,
    2130             :                                     &atname->st,
    2131             :                                     atname->twrp,
    2132             :                                     atname->flags);
    2133    10519410 :         TALLOC_FREE(path);
    2134    10519410 :         if (fname == NULL) {
    2135           0 :                 return NULL;
    2136             :         }
    2137             : 
    2138    10519410 :         return fname;
    2139             : }

Generated by: LCOV version 1.13