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 42047796 : NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
28 : const struct smb_filename *smb_fname,
29 : char **full_name)
30 : {
31 42047796 : 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 42017329 : *full_name = talloc_strdup(ctx, smb_fname->base_name);
39 : }
40 :
41 42047796 : if (!*full_name) {
42 0 : return NT_STATUS_NO_MEMORY;
43 : }
44 :
45 42047796 : 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 23741923 : 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 23741923 : 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 23741923 : if (psbuf)
71 10193573 : smb_fname_loc.st = *psbuf;
72 :
73 : /* Let cp_smb_filename() do the heavy lifting. */
74 23741923 : 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 4190100 : struct smb_filename *cp_smb_filename_nostream(TALLOC_CTX *mem_ctx,
82 : const struct smb_filename *smb_fname_in)
83 : {
84 4190100 : struct smb_filename smb_fname_loc = *smb_fname_in;
85 4190100 : struct smb_filename *smb_fname = NULL;
86 :
87 4190100 : smb_fname_loc.stream_name = NULL;
88 :
89 4190100 : smb_fname = cp_smb_filename(mem_ctx, &smb_fname_loc);
90 4190100 : 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 6228489 : const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
138 : {
139 6228489 : char *fname = NULL;
140 32601 : time_t t;
141 32601 : struct tm tm;
142 6228489 : struct tm *ptm = NULL;
143 32601 : fstring tstr;
144 32601 : ssize_t slen;
145 32601 : NTSTATUS status;
146 :
147 6228489 : if (smb_fname == NULL) {
148 0 : return "";
149 : }
150 6228489 : status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
151 6228489 : if (!NT_STATUS_IS_OK(status)) {
152 0 : return "";
153 : }
154 6228489 : if (smb_fname->twrp == 0) {
155 6210261 : 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 138671 : const char *fsp_str_dbg(const struct files_struct *fsp)
181 : {
182 138671 : const char *name = NULL;
183 :
184 138671 : name = smb_fname_str_dbg(fsp->fsp_name);
185 138671 : if (name == NULL) {
186 0 : return "";
187 : }
188 :
189 138671 : 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 67634292 : struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
221 : const struct smb_filename *in)
222 : {
223 144164 : struct smb_filename *out;
224 67634292 : size_t base_len = 0;
225 67634292 : size_t stream_len = 0;
226 67634292 : int num = 0;
227 :
228 : /* stream_name must always be NULL if there is no stream. */
229 67634292 : if (in->stream_name) {
230 50150 : SMB_ASSERT(in->stream_name[0] != '\0');
231 : }
232 :
233 67634292 : if (in->base_name != NULL) {
234 67634292 : base_len = strlen(in->base_name) + 1;
235 67634292 : num += 1;
236 : }
237 67634292 : if (in->stream_name != NULL) {
238 50150 : stream_len = strlen(in->stream_name) + 1;
239 50150 : num += 1;
240 : }
241 :
242 67634292 : out = talloc_pooled_object(mem_ctx, struct smb_filename,
243 : num, stream_len + base_len);
244 67634292 : if (out == NULL) {
245 0 : return NULL;
246 : }
247 67634292 : 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 67634292 : if (in->base_name != NULL) {
255 67634292 : out->base_name = talloc_memdup(
256 : out, in->base_name, base_len);
257 67634292 : talloc_set_name_const(out->base_name,
258 67490128 : out->base_name);
259 : }
260 67634292 : 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 67634292 : out->flags = in->flags;
267 67634292 : out->st = in->st;
268 67634292 : out->twrp = in->twrp;
269 67634292 : return out;
270 : }
271 :
272 39700258 : 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 39700258 : if (smb_fname->stream_name) {
276 84774 : SMB_ASSERT(smb_fname->stream_name[0] != '\0');
277 : }
278 :
279 39700258 : if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
280 86065 : SMB_ASSERT(smb_fname->stream_name == NULL);
281 : }
282 39700258 : }
283 :
284 : /****************************************************************************
285 : Simple check to determine if a smb_fname is a real named stream or the
286 : default stream.
287 : ***************************************************************************/
288 :
289 684127 : bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
290 : {
291 684127 : assert_valid_stream_smb_fname(smb_fname);
292 :
293 684127 : 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 38461825 : bool is_named_stream(const struct smb_filename *smb_fname)
308 : {
309 38461825 : assert_valid_stream_smb_fname(smb_fname);
310 :
311 38461825 : if (smb_fname->stream_name == NULL) {
312 38253709 : 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 554306 : bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
326 : {
327 554306 : assert_valid_stream_smb_fname(smb_fname);
328 :
329 554306 : if (smb_fname->stream_name == NULL) {
330 543368 : 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 : }
|