LCOV - code coverage report
Current view: top level - source3/lib - filename_util.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 135 159 84.9 %
Date: 2024-02-29 22:57:05 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Filename utility functions.
       4             :    Copyright (C) Tim Prouty 2009
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : #include "includes.h"
      20             : 
      21             : /**
      22             :  * XXX: This is temporary and there should be no callers of this outside of
      23             :  * this file once smb_filename is plumbed through all path based operations.
      24             :  * The one legitimate caller currently is smb_fname_str_dbg(), which this
      25             :  * could be made static for.
      26             :  */
      27    42059783 : NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
      28             :                                const struct smb_filename *smb_fname,
      29             :                                char **full_name)
      30             : {
      31    42059783 :         if (smb_fname->stream_name) {
      32             :                 /* stream_name must always be NULL if there is no stream. */
      33       30467 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
      34             : 
      35       30467 :                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
      36       30459 :                                              smb_fname->stream_name);
      37             :         } else {
      38    42029316 :                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
      39             :         }
      40             : 
      41    42059783 :         if (!*full_name) {
      42           0 :                 return NT_STATUS_NO_MEMORY;
      43             :         }
      44             : 
      45    42059783 :         return NT_STATUS_OK;
      46             : }
      47             : 
      48             : /**
      49             :  * There are actually legitimate callers of this such as functions that
      50             :  * enumerate streams using the vfs_streaminfo interface and then want to
      51             :  * operate on each stream.
      52             :  */
      53    23741014 : struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
      54             :                                          const char *base_name,
      55             :                                          const char *stream_name,
      56             :                                          const SMB_STRUCT_STAT *psbuf,
      57             :                                          NTTIME twrp,
      58             :                                          uint32_t flags)
      59             : {
      60             :         /* Setup the base_name/stream_name. */
      61             : 
      62    23741014 :         struct smb_filename smb_fname_loc = {
      63             :                 .base_name = discard_const_p(char, base_name),
      64             :                 .stream_name = discard_const_p(char, stream_name),
      65             :                 .flags = flags,
      66             :                 .twrp = twrp,
      67             :         };
      68             : 
      69             :         /* Copy the psbuf if one was given. */
      70    23741014 :         if (psbuf)
      71    10193590 :                 smb_fname_loc.st = *psbuf;
      72             : 
      73             :         /* Let cp_smb_filename() do the heavy lifting. */
      74    23741014 :         return cp_smb_filename(mem_ctx, &smb_fname_loc);
      75             : }
      76             : 
      77             : /**
      78             :  * Utility function used by VFS calls that must *NOT* operate
      79             :  * on a stream filename, only the base_name.
      80             :  */
      81     4190106 : struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx,
      82             :                                         const struct smb_filename *smb_fname_in)
      83             : {
      84     4190106 :         struct smb_filename smb_fname_loc = *smb_fname_in;
      85     4190106 :         struct smb_filename *smb_fname = NULL;
      86             : 
      87     4190106 :         smb_fname_loc.stream_name = NULL;
      88             : 
      89     4190106 :         smb_fname = cp_smb_filename(mem_ctx, &smb_fname_loc);
      90     4190106 :         return smb_fname;
      91             : }
      92             : 
      93             : /**
      94             :  * There are a few legitimate users of this.
      95             :  */
      96        4809 : struct smb_filename *synthetic_smb_fname_split(TALLOC_CTX *ctx,
      97             :                                                 const char *fname,
      98             :                                                 bool posix_path)
      99             : {
     100        4809 :         char *stream_name = NULL;
     101        4809 :         char *base_name = NULL;
     102         200 :         struct smb_filename *ret;
     103         200 :         bool ok;
     104             : 
     105        4809 :         if (posix_path) {
     106             :                 /* No stream name looked for. */
     107           0 :                 return synthetic_smb_fname(ctx,
     108             :                                 fname,
     109             :                                 NULL,
     110             :                                 NULL,
     111             :                                 0,
     112             :                                 SMB_FILENAME_POSIX_PATH);
     113             :         }
     114             : 
     115        4809 :         ok = split_stream_filename(ctx,
     116             :                                 fname,
     117             :                                 &base_name,
     118             :                                 &stream_name);
     119        4809 :         if (!ok) {
     120           0 :                 return NULL;
     121             :         }
     122             : 
     123        4809 :         ret = synthetic_smb_fname(ctx,
     124             :                                   base_name,
     125             :                                   stream_name,
     126             :                                   NULL,
     127             :                                   0,
     128             :                                   0);
     129        4809 :         TALLOC_FREE(base_name);
     130        4809 :         TALLOC_FREE(stream_name);
     131        4609 :         return ret;
     132             : }
     133             : 
     134             : /**
     135             :  * Return a string using the talloc_tos()
     136             :  */
     137     6228319 : const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
     138             : {
     139     6228319 :         char *fname = NULL;
     140       32601 :         time_t t;
     141       32601 :         struct tm tm;
     142     6228319 :         struct tm *ptm = NULL;
     143       32601 :         fstring tstr;
     144       32601 :         ssize_t slen;
     145       32601 :         NTSTATUS status;
     146             : 
     147     6228319 :         if (smb_fname == NULL) {
     148           0 :                 return "";
     149             :         }
     150     6228319 :         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
     151     6228319 :         if (!NT_STATUS_IS_OK(status)) {
     152           0 :                 return "";
     153             :         }
     154     6228319 :         if (smb_fname->twrp == 0) {
     155     6210091 :                 return fname;
     156             :         }
     157             : 
     158       18228 :         t = nt_time_to_unix(smb_fname->twrp);
     159       18228 :         ptm = gmtime_r(&t, &tm);
     160       18228 :         if (ptm == NULL) {
     161           0 :                 return "";
     162             :         }
     163             : 
     164       18228 :         slen = strftime(tstr, sizeof(tstr), GMT_FORMAT, &tm);
     165       18228 :         if (slen == 0) {
     166           0 :                 return "";
     167             :         }
     168             : 
     169       18228 :         fname = talloc_asprintf_append_buffer(
     170             :                 fname, " {%s}", tstr);
     171       18228 :         if (fname == NULL) {
     172           0 :                 return "";
     173             :         }
     174       18228 :         return fname;
     175             : }
     176             : 
     177             : /**
     178             :  * Return a debug string of the path name of an fsp using the talloc_tos().
     179             :  */
     180      138683 : const char *fsp_str_dbg(const struct files_struct *fsp)
     181             : {
     182      138683 :         const char *name = NULL;
     183             : 
     184      138683 :         name = smb_fname_str_dbg(fsp->fsp_name);
     185      138683 :         if (name == NULL) {
     186           0 :                 return "";
     187             :         }
     188             : 
     189      138683 :         return name;
     190             : }
     191             : 
     192             : /**
     193             :  * Create a debug string for the fnum of an fsp.
     194             :  *
     195             :  * This is allocated to talloc_tos() or a string constant
     196             :  * in certain corner cases. The returned string should
     197             :  * hence not be free'd directly but only via the talloc stack.
     198             :  */
     199           0 : const char *fsp_fnum_dbg(const struct files_struct *fsp)
     200             : {
     201           0 :         char *str;
     202             : 
     203           0 :         if (fsp == NULL) {
     204           0 :                 return "fnum [fsp is NULL]";
     205             :         }
     206             : 
     207           0 :         if (fsp->fnum == FNUM_FIELD_INVALID) {
     208           0 :                 return "fnum [invalid value]";
     209             :         }
     210             : 
     211           0 :         str = talloc_asprintf(talloc_tos(), "fnum %"PRIu64, fsp->fnum);
     212           0 :         if (str == NULL) {
     213           0 :                 DEBUG(1, ("%s: talloc_asprintf failed\n", __FUNCTION__));
     214           0 :                 return "fnum [talloc failed!]";
     215             :         }
     216             : 
     217           0 :         return str;
     218             : }
     219             : 
     220    67643857 : struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
     221             :                                      const struct smb_filename *in)
     222             : {
     223      144164 :         struct smb_filename *out;
     224    67643857 :         size_t base_len = 0;
     225    67643857 :         size_t stream_len = 0;
     226    67643857 :         int num = 0;
     227             : 
     228             :         /* stream_name must always be NULL if there is no stream. */
     229    67643857 :         if (in->stream_name) {
     230       50150 :                 SMB_ASSERT(in->stream_name[0] != '\0');
     231             :         }
     232             : 
     233    67643857 :         if (in->base_name != NULL) {
     234    67643857 :                 base_len = strlen(in->base_name) + 1;
     235    67643857 :                 num += 1;
     236             :         }
     237    67643857 :         if (in->stream_name != NULL) {
     238       50150 :                 stream_len = strlen(in->stream_name) + 1;
     239       50150 :                 num += 1;
     240             :         }
     241             : 
     242    67643857 :         out = talloc_pooled_object(mem_ctx, struct smb_filename,
     243             :                                 num, stream_len + base_len);
     244    67643857 :         if (out == NULL) {
     245           0 :                 return NULL;
     246             :         }
     247    67643857 :         ZERO_STRUCTP(out);
     248             : 
     249             :         /*
     250             :          * The following allocations cannot fail as we
     251             :          * pre-allocated space for them in the out pooled
     252             :          * object.
     253             :          */
     254    67643857 :         if (in->base_name != NULL) {
     255    67643857 :                 out->base_name = talloc_memdup(
     256             :                                 out, in->base_name, base_len);
     257    67643857 :                 talloc_set_name_const(out->base_name,
     258    67499693 :                                       out->base_name);
     259             :         }
     260    67643857 :         if (in->stream_name != NULL) {
     261       50150 :                 out->stream_name = talloc_memdup(
     262             :                                 out, in->stream_name, stream_len);
     263       50150 :                 talloc_set_name_const(out->stream_name,
     264       50134 :                                       out->stream_name);
     265             :         }
     266    67643857 :         out->flags = in->flags;
     267    67643857 :         out->st = in->st;
     268    67643857 :         out->twrp = in->twrp;
     269    67643857 :         return out;
     270             : }
     271             : 
     272    39701918 : static void assert_valid_stream_smb_fname(const struct smb_filename *smb_fname)
     273             : {
     274             :         /* stream_name must always be NULL if there is no stream. */
     275    39701918 :         if (smb_fname->stream_name) {
     276       84774 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
     277             :         }
     278             : 
     279    39701918 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
     280       86065 :                 SMB_ASSERT(smb_fname->stream_name == NULL);
     281             :         }
     282    39701918 : }
     283             : 
     284             : /****************************************************************************
     285             :  Simple check to determine if a smb_fname is a real named stream or the
     286             :  default stream.
     287             :  ***************************************************************************/
     288             : 
     289      684157 : bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
     290             : {
     291      684157 :         assert_valid_stream_smb_fname(smb_fname);
     292             : 
     293      684157 :         return (smb_fname->stream_name != NULL);
     294             : }
     295             : 
     296             : /****************************************************************************
     297             :  Simple check to determine if a smb_fname is pointing to a normal file or
     298             :  a named stream that is not the default stream "::$DATA".
     299             : 
     300             :   foo           -> false
     301             :   foo::$DATA    -> false
     302             :   foo:bar       -> true
     303             :   foo:bar:$DATA -> true
     304             : 
     305             :  ***************************************************************************/
     306             : 
     307    38463223 : bool is_named_stream(const struct smb_filename *smb_fname)
     308             : {
     309    38463223 :         assert_valid_stream_smb_fname(smb_fname);
     310             : 
     311    38463223 :         if (smb_fname->stream_name == NULL) {
     312    38255107 :                 return false;
     313             :         }
     314             : 
     315       67693 :         if (strequal_m(smb_fname->stream_name, "::$DATA")) {
     316         372 :                 return false;
     317             :         }
     318             : 
     319       67293 :         return true;
     320             : }
     321             : 
     322             : /****************************************************************************
     323             :  Returns true if the filename's stream == "::$DATA"
     324             :  ***************************************************************************/
     325      554538 : bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
     326             : {
     327      554538 :         assert_valid_stream_smb_fname(smb_fname);
     328             : 
     329      554538 :         if (smb_fname->stream_name == NULL) {
     330      543600 :                 return false;
     331             :         }
     332             : 
     333        9416 :         return strequal_m(smb_fname->stream_name, "::$DATA");
     334             : }
     335             : 
     336             : /****************************************************************************
     337             :  Filter out Windows invalid EA names (list probed from Windows 2012).
     338             : ****************************************************************************/
     339             : 
     340             : static const char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
     341             : 
     342       10909 : bool is_invalid_windows_ea_name(const char *name)
     343             : {
     344        1170 :         int i;
     345             :         /* EA name is pulled as ascii so we can examine
     346             :            individual bytes here. */
     347      112518 :         for (i = 0; name[i] != 0; i++) {
     348      101849 :                 int val = (name[i] & 0xff);
     349      101849 :                 if (val < ' ' || strchr(bad_ea_name_chars, val)) {
     350         192 :                         return true;
     351             :                 }
     352             :         }
     353        9547 :         return false;
     354             : }
     355             : 
     356        3513 : bool ea_list_has_invalid_name(struct ea_list *ea_list)
     357             : {
     358        8072 :         for (;ea_list; ea_list = ea_list->next) {
     359        4799 :                 if (is_invalid_windows_ea_name(ea_list->ea.name)) {
     360         192 :                         return true;
     361             :                 }
     362             :         }
     363        2802 :         return false;
     364             : }
     365             : 
     366             : /****************************************************************************
     367             :  Split an incoming name into tallocd filename and stream components.
     368             :  Returns true on success, false on out of memory.
     369             : ****************************************************************************/
     370             : 
     371        4837 : bool split_stream_filename(TALLOC_CTX *ctx,
     372             :                                 const char *filename_in,
     373             :                                 char **filename_out,
     374             :                                 char **streamname_out)
     375             : {
     376        4837 :         const char *stream_name = NULL;
     377        4837 :         char *stream_out = NULL;
     378        4837 :         char *file_out = NULL;
     379             : 
     380        4837 :         stream_name = strchr_m(filename_in, ':');
     381             : 
     382        4837 :         if (stream_name) {
     383          25 :                 stream_out = talloc_strdup(ctx, stream_name);
     384          25 :                 if (stream_out == NULL) {
     385           0 :                         return false;
     386             :                 }
     387          25 :                 file_out = talloc_strndup(ctx,
     388             :                                         filename_in,
     389          25 :                                         PTR_DIFF(stream_name, filename_in));
     390             :         } else {
     391        4812 :                 file_out = talloc_strdup(ctx, filename_in);
     392             :         }
     393             : 
     394        4837 :         if (file_out == NULL) {
     395           0 :                 TALLOC_FREE(stream_out);
     396           0 :                 return false;
     397             :         }
     398             : 
     399        4837 :         if (filename_out) {
     400        4837 :                 *filename_out = file_out;
     401             :         }
     402        4837 :         if (streamname_out) {
     403        4837 :                 *streamname_out = stream_out;
     404             :         }
     405        4633 :         return true;
     406             : }

Generated by: LCOV version 1.14