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 718602 : NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
28 : const struct smb_filename *smb_fname,
29 : char **full_name)
30 : {
31 718602 : if (smb_fname->stream_name) {
32 : /* stream_name must always be NULL if there is no stream. */
33 739 : SMB_ASSERT(smb_fname->stream_name[0] != '\0');
34 :
35 739 : *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
36 368 : smb_fname->stream_name);
37 : } else {
38 717863 : *full_name = talloc_strdup(ctx, smb_fname->base_name);
39 : }
40 :
41 718602 : if (!*full_name) {
42 0 : return NT_STATUS_NO_MEMORY;
43 : }
44 :
45 718602 : 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 506668 : 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 506668 : 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 506668 : if (psbuf)
71 196361 : smb_fname_loc.st = *psbuf;
72 :
73 : /* Let cp_smb_filename() do the heavy lifting. */
74 506668 : 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 75774 : struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx,
82 : const struct smb_filename *smb_fname_in)
83 : {
84 75774 : struct smb_filename smb_fname_loc = *smb_fname_in;
85 75774 : struct smb_filename *smb_fname = NULL;
86 :
87 75774 : smb_fname_loc.stream_name = NULL;
88 :
89 75774 : smb_fname = cp_smb_filename(mem_ctx, &smb_fname_loc);
90 75774 : return smb_fname;
91 : }
92 :
93 : /**
94 : * There are a few legitimate users of this.
95 : */
96 1929 : struct smb_filename *synthetic_smb_fname_split(TALLOC_CTX *ctx,
97 : const char *fname,
98 : bool posix_path)
99 : {
100 1929 : char *stream_name = NULL;
101 1929 : char *base_name = NULL;
102 : struct smb_filename *ret;
103 : bool ok;
104 :
105 1929 : 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 1929 : ok = split_stream_filename(ctx,
116 : fname,
117 : &base_name,
118 : &stream_name);
119 1929 : if (!ok) {
120 0 : return NULL;
121 : }
122 :
123 1929 : ret = synthetic_smb_fname(ctx,
124 : base_name,
125 : stream_name,
126 : NULL,
127 : 0,
128 : 0);
129 1929 : TALLOC_FREE(base_name);
130 1929 : TALLOC_FREE(stream_name);
131 1929 : return ret;
132 : }
133 :
134 : /**
135 : * Return a string using the talloc_tos()
136 : */
137 130654 : const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
138 : {
139 130654 : char *fname = NULL;
140 : time_t t;
141 : struct tm tm;
142 130654 : struct tm *ptm = NULL;
143 : fstring tstr;
144 : ssize_t slen;
145 : NTSTATUS status;
146 :
147 130654 : if (smb_fname == NULL) {
148 0 : return "";
149 : }
150 130654 : status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
151 130654 : if (!NT_STATUS_IS_OK(status)) {
152 0 : return "";
153 : }
154 130654 : if (smb_fname->twrp == 0) {
155 130653 : return fname;
156 : }
157 :
158 1 : t = nt_time_to_unix(smb_fname->twrp);
159 1 : ptm = gmtime_r(&t, &tm);
160 1 : if (ptm == NULL) {
161 0 : return "";
162 : }
163 :
164 1 : slen = strftime(tstr, sizeof(tstr), GMT_FORMAT, &tm);
165 1 : if (slen == 0) {
166 0 : return "";
167 : }
168 :
169 1 : fname = talloc_asprintf_append_buffer(
170 : fname, " {%s}", tstr);
171 1 : if (fname == NULL) {
172 0 : return "";
173 : }
174 1 : return fname;
175 : }
176 :
177 : /**
178 : * Return a debug string of the path name of an fsp using the talloc_tos().
179 : */
180 1427 : const char *fsp_str_dbg(const struct files_struct *fsp)
181 : {
182 1427 : const char *name = NULL;
183 :
184 1427 : name = smb_fname_str_dbg(fsp->fsp_name);
185 1427 : if (name == NULL) {
186 0 : return "";
187 : }
188 :
189 1427 : 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 : 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 1313417 : struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
221 : const struct smb_filename *in)
222 : {
223 : struct smb_filename *out;
224 1313417 : size_t base_len = 0;
225 1313417 : size_t stream_len = 0;
226 1313417 : int num = 0;
227 :
228 : /* stream_name must always be NULL if there is no stream. */
229 1313417 : if (in->stream_name) {
230 903 : SMB_ASSERT(in->stream_name[0] != '\0');
231 : }
232 :
233 1313417 : if (in->base_name != NULL) {
234 1313417 : base_len = strlen(in->base_name) + 1;
235 1313417 : num += 1;
236 : }
237 1313417 : if (in->stream_name != NULL) {
238 903 : stream_len = strlen(in->stream_name) + 1;
239 903 : num += 1;
240 : }
241 :
242 1313417 : out = talloc_pooled_object(mem_ctx, struct smb_filename,
243 : num, stream_len + base_len);
244 1313417 : if (out == NULL) {
245 0 : return NULL;
246 : }
247 1313417 : 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 1313417 : if (in->base_name != NULL) {
255 1313417 : out->base_name = talloc_memdup(
256 : out, in->base_name, base_len);
257 1313417 : talloc_set_name_const(out->base_name,
258 1313417 : out->base_name);
259 : }
260 1313417 : if (in->stream_name != NULL) {
261 903 : out->stream_name = talloc_memdup(
262 : out, in->stream_name, stream_len);
263 903 : talloc_set_name_const(out->stream_name,
264 903 : out->stream_name);
265 : }
266 1313417 : out->flags = in->flags;
267 1313417 : out->st = in->st;
268 1313417 : out->twrp = in->twrp;
269 1313417 : return out;
270 : }
271 :
272 1180981 : 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 1180981 : if (smb_fname->stream_name) {
276 753 : SMB_ASSERT(smb_fname->stream_name[0] != '\0');
277 : }
278 :
279 1180981 : if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
280 0 : SMB_ASSERT(smb_fname->stream_name == NULL);
281 : }
282 1180981 : }
283 :
284 : /****************************************************************************
285 : Simple check to determine if a smb_fname is a real named stream or the
286 : default stream.
287 : ***************************************************************************/
288 :
289 136088 : bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
290 : {
291 136088 : assert_valid_stream_smb_fname(smb_fname);
292 :
293 136088 : 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 1031980 : bool is_named_stream(const struct smb_filename *smb_fname)
308 : {
309 1031980 : assert_valid_stream_smb_fname(smb_fname);
310 :
311 1031980 : if (smb_fname->stream_name == NULL) {
312 1031364 : return false;
313 : }
314 :
315 616 : if (strequal_m(smb_fname->stream_name, "::$DATA")) {
316 0 : return false;
317 : }
318 :
319 616 : return true;
320 : }
321 :
322 : /****************************************************************************
323 : Returns true if the filename's stream == "::$DATA"
324 : ***************************************************************************/
325 12913 : bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
326 : {
327 12913 : assert_valid_stream_smb_fname(smb_fname);
328 :
329 12913 : if (smb_fname->stream_name == NULL) {
330 12849 : return false;
331 : }
332 :
333 64 : 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 char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
341 :
342 7 : bool is_invalid_windows_ea_name(const char *name)
343 : {
344 : int i;
345 : /* EA name is pulled as ascii so we can examine
346 : individual bytes here. */
347 66 : for (i = 0; name[i] != 0; i++) {
348 59 : int val = (name[i] & 0xff);
349 59 : if (val < ' ' || strchr(bad_ea_name_chars, val)) {
350 0 : return true;
351 : }
352 : }
353 7 : return false;
354 : }
355 :
356 2 : bool ea_list_has_invalid_name(struct ea_list *ea_list)
357 : {
358 6 : for (;ea_list; ea_list = ea_list->next) {
359 4 : if (is_invalid_windows_ea_name(ea_list->ea.name)) {
360 0 : return true;
361 : }
362 : }
363 2 : 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 1929 : bool split_stream_filename(TALLOC_CTX *ctx,
372 : const char *filename_in,
373 : char **filename_out,
374 : char **streamname_out)
375 : {
376 1929 : const char *stream_name = NULL;
377 1929 : char *stream_out = NULL;
378 1929 : char *file_out = NULL;
379 :
380 1929 : stream_name = strchr_m(filename_in, ':');
381 :
382 1929 : if (stream_name) {
383 1 : stream_out = talloc_strdup(ctx, stream_name);
384 1 : if (stream_out == NULL) {
385 0 : return false;
386 : }
387 1 : file_out = talloc_strndup(ctx,
388 : filename_in,
389 1 : PTR_DIFF(stream_name, filename_in));
390 : } else {
391 1928 : file_out = talloc_strdup(ctx, filename_in);
392 : }
393 :
394 1929 : if (file_out == NULL) {
395 0 : TALLOC_FREE(stream_out);
396 0 : return false;
397 : }
398 :
399 1929 : if (filename_out) {
400 1929 : *filename_out = file_out;
401 : }
402 1929 : if (streamname_out) {
403 1929 : *streamname_out = stream_out;
404 : }
405 1929 : return true;
406 : }
|