LCOV - code coverage report
Current view: top level - source3/lib - filename_util.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 135 159 84.9 %
Date: 2023-11-21 12:31:41 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    41546885 : NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
      28             :                                const struct smb_filename *smb_fname,
      29             :                                char **full_name)
      30             : {
      31    41546885 :         if (smb_fname->stream_name) {
      32             :                 /* stream_name must always be NULL if there is no stream. */
      33       30149 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
      34             : 
      35       30149 :                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
      36       30141 :                                              smb_fname->stream_name);
      37             :         } else {
      38    41516736 :                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
      39             :         }
      40             : 
      41    41546885 :         if (!*full_name) {
      42           0 :                 return NT_STATUS_NO_MEMORY;
      43             :         }
      44             : 
      45    41546885 :         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    23672517 : 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    23672517 :         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    23672517 :         if (psbuf)
      71    10163007 :                 smb_fname_loc.st = *psbuf;
      72             : 
      73             :         /* Let cp_smb_filename() do the heavy lifting. */
      74    23672517 :         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     4180769 : struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx,
      82             :                                         const struct smb_filename *smb_fname_in)
      83             : {
      84     4180769 :         struct smb_filename smb_fname_loc = *smb_fname_in;
      85     4180769 :         struct smb_filename *smb_fname = NULL;
      86             : 
      87     4180769 :         smb_fname_loc.stream_name = NULL;
      88             : 
      89     4180769 :         smb_fname = cp_smb_filename(mem_ctx, &smb_fname_loc);
      90     4180769 :         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     6210531 : const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
     138             : {
     139     6210531 :         char *fname = NULL;
     140       32599 :         time_t t;
     141       32599 :         struct tm tm;
     142     6210531 :         struct tm *ptm = NULL;
     143       32599 :         fstring tstr;
     144       32599 :         ssize_t slen;
     145       32599 :         NTSTATUS status;
     146             : 
     147     6210531 :         if (smb_fname == NULL) {
     148           0 :                 return "";
     149             :         }
     150     6210531 :         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
     151     6210531 :         if (!NT_STATUS_IS_OK(status)) {
     152           0 :                 return "";
     153             :         }
     154     6210531 :         if (smb_fname->twrp == 0) {
     155     6199880 :                 return fname;
     156             :         }
     157             : 
     158       10651 :         t = nt_time_to_unix(smb_fname->twrp);
     159       10651 :         ptm = gmtime_r(&t, &tm);
     160       10651 :         if (ptm == NULL) {
     161           0 :                 return "";
     162             :         }
     163             : 
     164       10651 :         slen = strftime(tstr, sizeof(tstr), GMT_FORMAT, &tm);
     165       10651 :         if (slen == 0) {
     166           0 :                 return "";
     167             :         }
     168             : 
     169       10651 :         fname = talloc_asprintf_append_buffer(
     170             :                 fname, " {%s}", tstr);
     171       10651 :         if (fname == NULL) {
     172           0 :                 return "";
     173             :         }
     174       10651 :         return fname;
     175             : }
     176             : 
     177             : /**
     178             :  * Return a debug string of the path name of an fsp using the talloc_tos().
     179             :  */
     180      138533 : const char *fsp_str_dbg(const struct files_struct *fsp)
     181             : {
     182      138533 :         const char *name = NULL;
     183             : 
     184      138533 :         name = smb_fname_str_dbg(fsp->fsp_name);
     185      138533 :         if (name == NULL) {
     186           0 :                 return "";
     187             :         }
     188             : 
     189      138533 :         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    67056135 : struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
     221             :                                      const struct smb_filename *in)
     222             : {
     223      144150 :         struct smb_filename *out;
     224    67056135 :         size_t base_len = 0;
     225    67056135 :         size_t stream_len = 0;
     226    67056135 :         int num = 0;
     227             : 
     228             :         /* stream_name must always be NULL if there is no stream. */
     229    67056135 :         if (in->stream_name) {
     230       49837 :                 SMB_ASSERT(in->stream_name[0] != '\0');
     231             :         }
     232             : 
     233    67056135 :         if (in->base_name != NULL) {
     234    67056135 :                 base_len = strlen(in->base_name) + 1;
     235    67056135 :                 num += 1;
     236             :         }
     237    67056135 :         if (in->stream_name != NULL) {
     238       49837 :                 stream_len = strlen(in->stream_name) + 1;
     239       49837 :                 num += 1;
     240             :         }
     241             : 
     242    67056135 :         out = talloc_pooled_object(mem_ctx, struct smb_filename,
     243             :                                 num, stream_len + base_len);
     244    67056135 :         if (out == NULL) {
     245           0 :                 return NULL;
     246             :         }
     247    67056135 :         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    67056135 :         if (in->base_name != NULL) {
     255    67056135 :                 out->base_name = talloc_memdup(
     256             :                                 out, in->base_name, base_len);
     257    67056135 :                 talloc_set_name_const(out->base_name,
     258    66911985 :                                       out->base_name);
     259             :         }
     260    67056135 :         if (in->stream_name != NULL) {
     261       49837 :                 out->stream_name = talloc_memdup(
     262             :                                 out, in->stream_name, stream_len);
     263       49837 :                 talloc_set_name_const(out->stream_name,
     264       49821 :                                       out->stream_name);
     265             :         }
     266    67056135 :         out->flags = in->flags;
     267    67056135 :         out->st = in->st;
     268    67056135 :         out->twrp = in->twrp;
     269    67056135 :         return out;
     270             : }
     271             : 
     272    39575545 : 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    39575545 :         if (smb_fname->stream_name) {
     276       84500 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
     277             :         }
     278             : 
     279    39575545 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
     280       86981 :                 SMB_ASSERT(smb_fname->stream_name == NULL);
     281             :         }
     282    39575545 : }
     283             : 
     284             : /****************************************************************************
     285             :  Simple check to determine if a smb_fname is a real named stream or the
     286             :  default stream.
     287             :  ***************************************************************************/
     288             : 
     289      679509 : bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
     290             : {
     291      679509 :         assert_valid_stream_smb_fname(smb_fname);
     292             : 
     293      679509 :         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    38344209 : bool is_named_stream(const struct smb_filename *smb_fname)
     308             : {
     309    38344209 :         assert_valid_stream_smb_fname(smb_fname);
     310             : 
     311    38344209 :         if (smb_fname->stream_name == NULL) {
     312    38136379 :                 return false;
     313             :         }
     314             : 
     315       67417 :         if (strequal_m(smb_fname->stream_name, "::$DATA")) {
     316         348 :                 return false;
     317             :         }
     318             : 
     319       67041 :         return true;
     320             : }
     321             : 
     322             : /****************************************************************************
     323             :  Returns true if the filename's stream == "::$DATA"
     324             :  ***************************************************************************/
     325      551827 : bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
     326             : {
     327      551827 :         assert_valid_stream_smb_fname(smb_fname);
     328             : 
     329      551827 :         if (smb_fname->stream_name == NULL) {
     330      540888 :                 return false;
     331             :         }
     332             : 
     333        9417 :         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