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 : }
|