LCOV - code coverage report
Current view: top level - source3/lib - filename_util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 126 156 80.8 %
Date: 2021-09-23 10:06:22 Functions: 14 16 87.5 %

          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    90744600 : NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
      28             :                                const struct smb_filename *smb_fname,
      29             :                                char **full_name)
      30             : {
      31    90744600 :         if (smb_fname->stream_name) {
      32             :                 /* stream_name must always be NULL if there is no stream. */
      33       40573 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
      34             : 
      35       40573 :                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
      36        2039 :                                              smb_fname->stream_name);
      37             :         } else {
      38    90704027 :                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
      39             :         }
      40             : 
      41    90744600 :         if (!*full_name) {
      42           0 :                 return NT_STATUS_NO_MEMORY;
      43             :         }
      44             : 
      45    90744600 :         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    48657945 : 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    48657945 :         struct smb_filename smb_fname_loc = { 0, };
      61             : 
      62             :         /* Setup the base_name/stream_name. */
      63    48657945 :         smb_fname_loc.base_name = discard_const_p(char, base_name);
      64    48657945 :         smb_fname_loc.stream_name = discard_const_p(char, stream_name);
      65    48657945 :         smb_fname_loc.flags = flags;
      66    48657945 :         smb_fname_loc.twrp = twrp;
      67             : 
      68             :         /* Copy the psbuf if one was given. */
      69    48657945 :         if (psbuf)
      70    20838790 :                 smb_fname_loc.st = *psbuf;
      71             : 
      72             :         /* Let cp_smb_filename() do the heavy lifting. */
      73    48657945 :         return cp_smb_filename(mem_ctx, &smb_fname_loc);
      74             : }
      75             : 
      76             : /**
      77             :  * Utility function used by VFS calls that must *NOT* operate
      78             :  * on a stream filename, only the base_name.
      79             :  */
      80           0 : struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx,
      81             :                                         const struct smb_filename *smb_fname_in)
      82             : {
      83           0 :         struct smb_filename *smb_fname = cp_smb_filename(mem_ctx,
      84             :                                                         smb_fname_in);
      85           0 :         if (smb_fname == NULL) {
      86           0 :                 return NULL;
      87             :         }
      88           0 :         TALLOC_FREE(smb_fname->stream_name);
      89           0 :         return smb_fname;
      90             : }
      91             : 
      92             : /**
      93             :  * There are a few legitimate users of this.
      94             :  */
      95        4591 : struct smb_filename *synthetic_smb_fname_split(TALLOC_CTX *ctx,
      96             :                                                 const char *fname,
      97             :                                                 bool posix_path)
      98             : {
      99        4591 :         char *stream_name = NULL;
     100        4591 :         char *base_name = NULL;
     101             :         struct smb_filename *ret;
     102             :         bool ok;
     103             : 
     104        4591 :         if (posix_path) {
     105             :                 /* No stream name looked for. */
     106           0 :                 return synthetic_smb_fname(ctx,
     107             :                                 fname,
     108             :                                 NULL,
     109             :                                 NULL,
     110             :                                 0,
     111             :                                 SMB_FILENAME_POSIX_PATH);
     112             :         }
     113             : 
     114        4591 :         ok = split_stream_filename(ctx,
     115             :                                 fname,
     116             :                                 &base_name,
     117             :                                 &stream_name);
     118        4591 :         if (!ok) {
     119           0 :                 return NULL;
     120             :         }
     121             : 
     122        4591 :         ret = synthetic_smb_fname(ctx,
     123             :                                   base_name,
     124             :                                   stream_name,
     125             :                                   NULL,
     126             :                                   0,
     127             :                                   0);
     128        4591 :         TALLOC_FREE(base_name);
     129        4591 :         TALLOC_FREE(stream_name);
     130        4391 :         return ret;
     131             : }
     132             : 
     133             : /**
     134             :  * Return a string using the talloc_tos()
     135             :  */
     136    10570430 : const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
     137             : {
     138    10570430 :         char *fname = NULL;
     139             :         time_t t;
     140             :         struct tm tm;
     141    10570430 :         struct tm *ptm = NULL;
     142             :         fstring tstr;
     143             :         ssize_t slen;
     144             :         NTSTATUS status;
     145             : 
     146    10570430 :         if (smb_fname == NULL) {
     147           0 :                 return "";
     148             :         }
     149    10570430 :         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
     150    10570430 :         if (!NT_STATUS_IS_OK(status)) {
     151           0 :                 return "";
     152             :         }
     153    10570430 :         if (smb_fname->twrp == 0) {
     154    10560676 :                 return fname;
     155             :         }
     156             : 
     157        9754 :         t = nt_time_to_unix(smb_fname->twrp);
     158        9754 :         ptm = gmtime_r(&t, &tm);
     159        9754 :         if (ptm == NULL) {
     160           0 :                 return "";
     161             :         }
     162             : 
     163        9754 :         slen = strftime(tstr, sizeof(tstr), GMT_FORMAT, &tm);
     164        9754 :         if (slen == 0) {
     165           0 :                 return "";
     166             :         }
     167             : 
     168        9754 :         fname = talloc_asprintf_append_buffer(
     169             :                 fname, " {%s}", tstr);
     170        9754 :         if (fname == NULL) {
     171           0 :                 return "";
     172             :         }
     173        9754 :         return fname;
     174             : }
     175             : 
     176             : /**
     177             :  * Return a debug string of the path name of an fsp using the talloc_tos().
     178             :  */
     179         337 : const char *fsp_str_dbg(const struct files_struct *fsp)
     180             : {
     181         337 :         const char *name = NULL;
     182             : 
     183         337 :         name = smb_fname_str_dbg(fsp->fsp_name);
     184         337 :         if (name == NULL) {
     185           0 :                 return "";
     186             :         }
     187             : 
     188         337 :         return name;
     189             : }
     190             : 
     191             : /**
     192             :  * Create a debug string for the fnum of an fsp.
     193             :  *
     194             :  * This is allocated to talloc_tos() or a string constant
     195             :  * in certain corner cases. The returned string should
     196             :  * hence not be free'd directly but only via the talloc stack.
     197             :  */
     198           0 : const char *fsp_fnum_dbg(const struct files_struct *fsp)
     199             : {
     200             :         char *str;
     201             : 
     202           0 :         if (fsp == NULL) {
     203           0 :                 return "fnum [fsp is NULL]";
     204             :         }
     205             : 
     206           0 :         if (fsp->fnum == FNUM_FIELD_INVALID) {
     207           0 :                 return "fnum [invalid value]";
     208             :         }
     209             : 
     210           0 :         str = talloc_asprintf(talloc_tos(), "fnum %llu",
     211           0 :                               (unsigned long long)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   149433501 : struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
     221             :                                      const struct smb_filename *in)
     222             : {
     223             :         struct smb_filename *out;
     224   149433501 :         size_t base_len = 0;
     225   149433501 :         size_t stream_len = 0;
     226   149433501 :         int num = 0;
     227             : 
     228             :         /* stream_name must always be NULL if there is no stream. */
     229   149433501 :         if (in->stream_name) {
     230       81105 :                 SMB_ASSERT(in->stream_name[0] != '\0');
     231             :         }
     232             : 
     233   149433501 :         if (in->base_name != NULL) {
     234   149433501 :                 base_len = strlen(in->base_name) + 1;
     235   149433501 :                 num += 1;
     236             :         }
     237   149433501 :         if (in->stream_name != NULL) {
     238       81105 :                 stream_len = strlen(in->stream_name) + 1;
     239       81105 :                 num += 1;
     240             :         }
     241             : 
     242   149433501 :         out = talloc_pooled_object(mem_ctx, struct smb_filename,
     243             :                                 num, stream_len + base_len);
     244   149433501 :         if (out == NULL) {
     245           0 :                 return NULL;
     246             :         }
     247   149433501 :         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   149433501 :         if (in->base_name != NULL) {
     255   149433501 :                 out->base_name = talloc_memdup(
     256             :                                 out, in->base_name, base_len);
     257   149433501 :                 talloc_set_name_const(out->base_name,
     258   148755490 :                                       out->base_name);
     259             :         }
     260   149433501 :         if (in->stream_name != NULL) {
     261       81105 :                 out->stream_name = talloc_memdup(
     262             :                                 out, in->stream_name, stream_len);
     263       81105 :                 talloc_set_name_const(out->stream_name,
     264       81069 :                                       out->stream_name);
     265             :         }
     266   149433501 :         out->flags = in->flags;
     267   149433501 :         out->st = in->st;
     268   149433501 :         out->twrp = in->twrp;
     269   149433501 :         return out;
     270             : }
     271             : 
     272   115388777 : 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   115388777 :         if (smb_fname->stream_name) {
     276       91006 :                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
     277             :         }
     278             : 
     279   115388777 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
     280       19968 :                 SMB_ASSERT(smb_fname->stream_name == NULL);
     281             :         }
     282   115388777 : }
     283             : 
     284             : /****************************************************************************
     285             :  Simple check to determine if a smb_fname is a real named stream or the
     286             :  default stream.
     287             :  ***************************************************************************/
     288             : 
     289    22246137 : bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
     290             : {
     291    22246137 :         assert_valid_stream_smb_fname(smb_fname);
     292             : 
     293    22246137 :         if (smb_fname->stream_name == NULL) {
     294    22040928 :                 return false;
     295             :         }
     296             : 
     297       30092 :         return true;
     298             : }
     299             : 
     300             : /****************************************************************************
     301             :  Simple check to determine if a smb_fname is pointing to a normal file or
     302             :  a named stream that is not the default stream "::$DATA".
     303             : 
     304             :   foo           -> false
     305             :   foo::$DATA    -> false
     306             :   foo:bar       -> true
     307             :   foo:bar:$DATA -> true
     308             : 
     309             :  ***************************************************************************/
     310             : 
     311    82648398 : bool is_named_stream(const struct smb_filename *smb_fname)
     312             : {
     313    82648398 :         assert_valid_stream_smb_fname(smb_fname);
     314             : 
     315    82648398 :         if (smb_fname->stream_name == NULL) {
     316    81939634 :                 return false;
     317             :         }
     318             : 
     319       46985 :         if (strequal_m(smb_fname->stream_name, "::$DATA")) {
     320         288 :                 return false;
     321             :         }
     322             : 
     323       46697 :         return true;
     324             : }
     325             : 
     326             : /****************************************************************************
     327             :  Returns true if the filename's stream == "::$DATA"
     328             :  ***************************************************************************/
     329    10494242 : bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
     330             : {
     331    10494242 :         assert_valid_stream_smb_fname(smb_fname);
     332             : 
     333    10494242 :         if (smb_fname->stream_name == NULL) {
     334    10394346 :                 return false;
     335             :         }
     336             : 
     337       13929 :         return strequal_m(smb_fname->stream_name, "::$DATA");
     338             : }
     339             : 
     340             : /****************************************************************************
     341             :  Filter out Windows invalid EA names (list probed from Windows 2012).
     342             : ****************************************************************************/
     343             : 
     344             : static char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
     345             : 
     346       10463 : bool is_invalid_windows_ea_name(const char *name)
     347             : {
     348             :         int i;
     349             :         /* EA name is pulled as ascii so we can examine
     350             :            individual bytes here. */
     351      107632 :         for (i = 0; name[i] != 0; i++) {
     352       97409 :                 int val = (name[i] & 0xff);
     353       97409 :                 if (val < ' ' || strchr(bad_ea_name_chars, val)) {
     354         192 :                         return true;
     355             :                 }
     356             :         }
     357        9119 :         return false;
     358             : }
     359             : 
     360        3509 : bool ea_list_has_invalid_name(struct ea_list *ea_list)
     361             : {
     362        8064 :         for (;ea_list; ea_list = ea_list->next) {
     363        4795 :                 if (is_invalid_windows_ea_name(ea_list->ea.name)) {
     364         192 :                         return true;
     365             :                 }
     366             :         }
     367        2798 :         return false;
     368             : }
     369             : 
     370             : /****************************************************************************
     371             :  Split an incoming name into tallocd filename and stream components.
     372             :  Returns true on success, false on out of memory.
     373             : ****************************************************************************/
     374             : 
     375        4624 : bool split_stream_filename(TALLOC_CTX *ctx,
     376             :                                 const char *filename_in,
     377             :                                 char **filename_out,
     378             :                                 char **streamname_out)
     379             : {
     380        4624 :         const char *stream_name = NULL;
     381        4624 :         char *stream_out = NULL;
     382        4624 :         char *file_out = NULL;
     383             : 
     384        4624 :         stream_name = strchr_m(filename_in, ':');
     385             : 
     386        4624 :         if (stream_name) {
     387          25 :                 stream_out = talloc_strdup(ctx, stream_name);
     388          25 :                 if (stream_out == NULL) {
     389           0 :                         return false;
     390             :                 }
     391          25 :                 file_out = talloc_strndup(ctx,
     392             :                                         filename_in,
     393          25 :                                         PTR_DIFF(stream_name, filename_in));
     394             :         } else {
     395        4599 :                 file_out = talloc_strdup(ctx, filename_in);
     396             :         }
     397             : 
     398        4624 :         if (file_out == NULL) {
     399           0 :                 TALLOC_FREE(stream_out);
     400           0 :                 return false;
     401             :         }
     402             : 
     403        4624 :         if (filename_out) {
     404        4624 :                 *filename_out = file_out;
     405             :         }
     406        4624 :         if (streamname_out) {
     407        4624 :                 *streamname_out = stream_out;
     408             :         }
     409        4419 :         return true;
     410             : }

Generated by: LCOV version 1.13