Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB transaction2 handling
4 : Copyright (C) Jeremy Allison 1994-2007
5 : Copyright (C) Stefan (metze) Metzmacher 2003
6 : Copyright (C) Volker Lendecke 2005-2007
7 : Copyright (C) Steve French 2005
8 : Copyright (C) James Peach 2006-2007
9 :
10 : Extensively modified by Andrew Tridgell, 1995
11 :
12 : This program is free software; you can redistribute it and/or modify
13 : it under the terms of the GNU General Public License as published by
14 : the Free Software Foundation; either version 3 of the License, or
15 : (at your option) any later version.
16 :
17 : This program is distributed in the hope that it will be useful,
18 : but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : GNU General Public License for more details.
21 :
22 : You should have received a copy of the GNU General Public License
23 : along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include "ntioctl.h"
28 : #include "system/filesys.h"
29 : #include "lib/util/time_basic.h"
30 : #include "version.h"
31 : #include "smbd/smbd.h"
32 : #include "smbd/globals.h"
33 : #include "../libcli/auth/libcli_auth.h"
34 : #include "../librpc/gen_ndr/xattr.h"
35 : #include "../librpc/gen_ndr/ndr_security.h"
36 : #include "../librpc/gen_ndr/ndr_smb3posix.h"
37 : #include "libcli/security/security.h"
38 : #include "trans2.h"
39 : #include "auth.h"
40 : #include "smbprofile.h"
41 : #include "rpc_server/srv_pipe_hnd.h"
42 : #include "printing.h"
43 : #include "lib/util_ea.h"
44 : #include "lib/readdir_attr.h"
45 : #include "messages.h"
46 : #include "libcli/smb/smb2_posix.h"
47 : #include "lib/util/string_wrappers.h"
48 : #include "source3/lib/substitute.h"
49 : #include "source3/lib/adouble.h"
50 :
51 : #define DIR_ENTRY_SAFETY_MARGIN 4096
52 :
53 : static uint32_t generate_volume_serial_number(
54 : const struct loadparm_substitution *lp_sub,
55 : int snum);
56 :
57 : /****************************************************************************
58 : Check if an open file handle is a symlink.
59 : ****************************************************************************/
60 :
61 797164 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
62 : {
63 :
64 797164 : if (!VALID_STAT(fsp->fsp_name->st)) {
65 0 : return NT_STATUS_ACCESS_DENIED;
66 : }
67 797164 : if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
68 108 : return NT_STATUS_ACCESS_DENIED;
69 : }
70 797056 : if (fsp_get_pathref_fd(fsp) == -1) {
71 172 : return NT_STATUS_ACCESS_DENIED;
72 : }
73 796884 : return NT_STATUS_OK;
74 : }
75 :
76 6627 : NTSTATUS check_access_fsp(struct files_struct *fsp,
77 : uint32_t access_mask)
78 : {
79 6627 : if (!fsp->fsp_flags.is_fsa) {
80 134 : return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
81 : fsp,
82 : false,
83 : access_mask);
84 : }
85 6493 : if (!(fsp->access_mask & access_mask)) {
86 40 : return NT_STATUS_ACCESS_DENIED;
87 : }
88 6453 : return NT_STATUS_OK;
89 : }
90 :
91 : /********************************************************************
92 : Roundup a value to the nearest allocation roundup size boundary.
93 : Only do this for Windows clients.
94 : ********************************************************************/
95 :
96 1730244 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
97 : {
98 1730244 : uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
99 :
100 : /* Only roundup for Windows clients. */
101 1730244 : enum remote_arch_types ra_type = get_remote_arch();
102 1730244 : if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
103 0 : val = SMB_ROUNDUP(val,rval);
104 : }
105 1730244 : return val;
106 : }
107 :
108 : /****************************************************************************
109 : Utility functions for dealing with extended attributes.
110 : ****************************************************************************/
111 :
112 : /****************************************************************************
113 : Refuse to allow clients to overwrite our private xattrs.
114 : ****************************************************************************/
115 :
116 724219 : bool samba_private_attr_name(const char *unix_ea_name)
117 : {
118 724219 : bool prohibited = false;
119 :
120 724219 : prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
121 724219 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
122 724219 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
123 724219 : prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
124 724219 : prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
125 :
126 724219 : if (prohibited) {
127 711052 : return true;
128 : }
129 :
130 12211 : if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
131 : strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
132 106 : return true;
133 : }
134 11037 : return false;
135 : }
136 :
137 : /****************************************************************************
138 : Get one EA value. Fill in a struct ea_struct.
139 : ****************************************************************************/
140 :
141 15142 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
142 : files_struct *fsp,
143 : const char *ea_name,
144 : struct ea_struct *pea)
145 : {
146 : /* Get the value of this xattr. Max size is 64k. */
147 15142 : size_t attr_size = 256;
148 15142 : char *val = NULL;
149 575 : ssize_t sizeret;
150 15142 : size_t max_xattr_size = 0;
151 575 : NTSTATUS status;
152 :
153 15142 : if (fsp == NULL) {
154 0 : return NT_STATUS_INVALID_HANDLE;
155 : }
156 15142 : status = refuse_symlink_fsp(fsp);
157 15142 : if (!NT_STATUS_IS_OK(status)) {
158 0 : return status;
159 : }
160 :
161 15142 : max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
162 :
163 15256 : again:
164 :
165 15256 : val = talloc_realloc(mem_ctx, val, char, attr_size);
166 15256 : if (!val) {
167 0 : return NT_STATUS_NO_MEMORY;
168 : }
169 :
170 15256 : sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
171 15256 : if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
172 114 : attr_size = max_xattr_size;
173 114 : goto again;
174 : }
175 :
176 15142 : if (sizeret == -1) {
177 2608 : return map_nt_error_from_unix(errno);
178 : }
179 :
180 12534 : DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
181 12534 : dump_data(10, (uint8_t *)val, sizeret);
182 :
183 12534 : pea->flags = 0;
184 12534 : if (strnequal(ea_name, "user.", 5)) {
185 12534 : pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
186 : } else {
187 0 : pea->name = talloc_strdup(mem_ctx, ea_name);
188 : }
189 12534 : if (pea->name == NULL) {
190 0 : TALLOC_FREE(val);
191 0 : return NT_STATUS_NO_MEMORY;
192 : }
193 12534 : pea->value.data = (unsigned char *)val;
194 12534 : pea->value.length = (size_t)sizeret;
195 12534 : return NT_STATUS_OK;
196 : }
197 :
198 750341 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
199 : files_struct *fsp,
200 : char ***pnames,
201 : size_t *pnum_names)
202 : {
203 1071 : char smallbuf[1024];
204 : /* Get a list of all xattrs. Max namesize is 64k. */
205 750341 : size_t ea_namelist_size = 1024;
206 750341 : char *ea_namelist = smallbuf;
207 750341 : char *to_free = NULL;
208 :
209 1071 : char *p;
210 1071 : char **names;
211 1071 : size_t num_names;
212 750341 : ssize_t sizeret = -1;
213 1071 : NTSTATUS status;
214 :
215 750341 : if (pnames) {
216 749071 : *pnames = NULL;
217 : }
218 750341 : *pnum_names = 0;
219 :
220 750341 : if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
221 : /*
222 : * Callers may pass fsp == NULL when passing smb_fname->fsp of a
223 : * symlink. This is ok, handle it here, by just return no EA's
224 : * on a symlink.
225 : */
226 268 : return NT_STATUS_OK;
227 : }
228 :
229 750073 : sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
230 : ea_namelist_size);
231 :
232 750073 : if ((sizeret == -1) && (errno == ERANGE)) {
233 0 : ea_namelist_size = 65536;
234 0 : ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
235 0 : if (ea_namelist == NULL) {
236 0 : return NT_STATUS_NO_MEMORY;
237 : }
238 0 : to_free = ea_namelist;
239 :
240 0 : sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
241 : ea_namelist_size);
242 : }
243 :
244 750073 : if (sizeret == -1) {
245 0 : status = map_nt_error_from_unix(errno);
246 0 : TALLOC_FREE(to_free);
247 0 : return status;
248 : }
249 :
250 750073 : DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
251 :
252 750073 : if (sizeret == 0) {
253 40852 : TALLOC_FREE(to_free);
254 40852 : return NT_STATUS_OK;
255 : }
256 :
257 : /*
258 : * Ensure the result is 0-terminated
259 : */
260 :
261 709221 : if (ea_namelist[sizeret-1] != '\0') {
262 0 : TALLOC_FREE(to_free);
263 0 : return NT_STATUS_INTERNAL_ERROR;
264 : }
265 :
266 : /*
267 : * count the names
268 : */
269 708191 : num_names = 0;
270 :
271 4165528 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
272 3456307 : num_names += 1;
273 : }
274 :
275 709221 : *pnum_names = num_names;
276 :
277 709221 : if (pnames == NULL) {
278 1261 : TALLOC_FREE(to_free);
279 1261 : return NT_STATUS_OK;
280 : }
281 :
282 707960 : names = talloc_array(mem_ctx, char *, num_names);
283 707960 : if (names == NULL) {
284 0 : DEBUG(0, ("talloc failed\n"));
285 0 : TALLOC_FREE(to_free);
286 0 : return NT_STATUS_NO_MEMORY;
287 : }
288 :
289 707960 : if (ea_namelist == smallbuf) {
290 707960 : ea_namelist = talloc_memdup(names, smallbuf, sizeret);
291 707960 : if (ea_namelist == NULL) {
292 0 : TALLOC_FREE(names);
293 0 : return NT_STATUS_NO_MEMORY;
294 : }
295 : } else {
296 0 : talloc_steal(names, ea_namelist);
297 :
298 0 : ea_namelist = talloc_realloc(names, ea_namelist, char,
299 : sizeret);
300 0 : if (ea_namelist == NULL) {
301 0 : TALLOC_FREE(names);
302 0 : return NT_STATUS_NO_MEMORY;
303 : }
304 : }
305 :
306 707960 : num_names = 0;
307 :
308 4157618 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
309 3449658 : names[num_names++] = p;
310 : }
311 :
312 707960 : *pnames = names;
313 :
314 707960 : return NT_STATUS_OK;
315 : }
316 :
317 : /****************************************************************************
318 : Return a linked list of the total EA's. Plus the total size
319 : ****************************************************************************/
320 :
321 743078 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
322 : files_struct *fsp,
323 : size_t *pea_total_len,
324 : struct ea_list **ea_list)
325 : {
326 : /* Get a list of all xattrs. Max namesize is 64k. */
327 994 : size_t i, num_names;
328 994 : char **names;
329 743078 : struct ea_list *ea_list_head = NULL;
330 743078 : bool posix_pathnames = false;
331 994 : NTSTATUS status;
332 :
333 743078 : *pea_total_len = 0;
334 743078 : *ea_list = NULL;
335 :
336 : /* symlink */
337 743078 : if (fsp == NULL) {
338 0 : return NT_STATUS_OK;
339 : }
340 :
341 743078 : if (!lp_ea_support(SNUM(fsp->conn))) {
342 0 : return NT_STATUS_OK;
343 : }
344 :
345 743078 : if (fsp_is_alternate_stream(fsp)) {
346 8 : return NT_STATUS_INVALID_PARAMETER;
347 : }
348 :
349 743070 : posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
350 :
351 743070 : status = get_ea_names_from_fsp(talloc_tos(),
352 : fsp,
353 : &names,
354 : &num_names);
355 :
356 743070 : if (!NT_STATUS_IS_OK(status)) {
357 0 : return status;
358 : }
359 :
360 743070 : if (num_names == 0) {
361 41097 : return NT_STATUS_OK;
362 : }
363 :
364 4136946 : for (i=0; i<num_names; i++) {
365 5395 : struct ea_list *listp;
366 5395 : fstring dos_ea_name;
367 :
368 : /*
369 : * POSIX EA names are divided into several namespaces by
370 : * means of string prefixes. Usually, the system controls
371 : * semantics for each namespace, but the 'user' namespace is
372 : * available for arbitrary use, which comes closest to
373 : * Windows EA semantics. Hence, we map POSIX EAs from the
374 : * 'user' namespace to Windows EAs, and just ignore all the
375 : * other namespaces. Also, a few specific names in the 'user'
376 : * namespace are used by Samba internally. Filter them out as
377 : * well, and only present the EAs that are available for
378 : * arbitrary use.
379 : */
380 3434973 : if (!strnequal(names[i], "user.", 5)
381 706665 : || samba_private_attr_name(names[i]))
382 3428859 : continue;
383 :
384 : /*
385 : * Filter out any underlying POSIX EA names
386 : * that a Windows client can't handle.
387 : */
388 12224 : if (!posix_pathnames &&
389 6110 : is_invalid_windows_ea_name(names[i])) {
390 0 : continue;
391 : }
392 :
393 6114 : listp = talloc(mem_ctx, struct ea_list);
394 6114 : if (listp == NULL) {
395 0 : return NT_STATUS_NO_MEMORY;
396 : }
397 :
398 6689 : status = get_ea_value_fsp(listp,
399 : fsp,
400 6114 : names[i],
401 : &listp->ea);
402 :
403 6114 : if (!NT_STATUS_IS_OK(status)) {
404 0 : TALLOC_FREE(listp);
405 0 : return status;
406 : }
407 :
408 6114 : if (listp->ea.value.length == 0) {
409 : /*
410 : * We can never return a zero length EA.
411 : * Windows reports the EA's as corrupted.
412 : */
413 0 : TALLOC_FREE(listp);
414 0 : continue;
415 6114 : } else if (listp->ea.value.length > 65536) {
416 : /*
417 : * SMB clients may report error with file
418 : * if large EA is presented to them.
419 : */
420 0 : DBG_ERR("EA [%s] on file [%s] exceeds "
421 : "maximum permitted EA size of 64KiB: %zu\n.",
422 : listp->ea.name, fsp_str_dbg(fsp),
423 : listp->ea.value.length);
424 0 : TALLOC_FREE(listp);
425 0 : continue;
426 : }
427 :
428 6114 : push_ascii_fstring(dos_ea_name, listp->ea.name);
429 :
430 6114 : *pea_total_len +=
431 6114 : 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
432 :
433 6114 : DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
434 : "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
435 : (unsigned int)listp->ea.value.length));
436 :
437 6114 : DLIST_ADD_END(ea_list_head, listp);
438 :
439 : }
440 :
441 : /* Add on 4 for total length. */
442 701973 : if (*pea_total_len) {
443 3902 : *pea_total_len += 4;
444 : }
445 :
446 701973 : DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
447 : (unsigned int)*pea_total_len));
448 :
449 701973 : *ea_list = ea_list_head;
450 701973 : return NT_STATUS_OK;
451 : }
452 :
453 : /****************************************************************************
454 : Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
455 : that was filled.
456 : ****************************************************************************/
457 :
458 170 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
459 : connection_struct *conn, struct ea_list *ea_list)
460 : {
461 170 : unsigned int ret_data_size = 4;
462 170 : char *p = pdata;
463 :
464 170 : SMB_ASSERT(total_data_size >= 4);
465 :
466 170 : if (!lp_ea_support(SNUM(conn))) {
467 0 : SIVAL(pdata,4,0);
468 0 : return 4;
469 : }
470 :
471 358 : for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
472 28 : size_t dos_namelen;
473 28 : fstring dos_ea_name;
474 188 : push_ascii_fstring(dos_ea_name, ea_list->ea.name);
475 188 : dos_namelen = strlen(dos_ea_name);
476 188 : if (dos_namelen > 255 || dos_namelen == 0) {
477 : break;
478 : }
479 188 : if (ea_list->ea.value.length > 65535) {
480 0 : break;
481 : }
482 188 : if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
483 0 : break;
484 : }
485 :
486 : /* We know we have room. */
487 188 : SCVAL(p,0,ea_list->ea.flags);
488 188 : SCVAL(p,1,dos_namelen);
489 188 : SSVAL(p,2,ea_list->ea.value.length);
490 188 : strlcpy(p+4, dos_ea_name, dos_namelen+1);
491 188 : if (ea_list->ea.value.length > 0) {
492 139 : memcpy(p + 4 + dos_namelen + 1,
493 111 : ea_list->ea.value.data,
494 : ea_list->ea.value.length);
495 : }
496 :
497 188 : total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
498 188 : p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
499 : }
500 :
501 170 : ret_data_size = PTR_DIFF(p, pdata);
502 170 : DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
503 170 : SIVAL(pdata,0,ret_data_size);
504 170 : return ret_data_size;
505 : }
506 :
507 555278 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
508 : char *pdata,
509 : unsigned int total_data_size,
510 : unsigned int *ret_data_size,
511 : connection_struct *conn,
512 : struct ea_list *ea_list)
513 : {
514 555278 : uint8_t *p = (uint8_t *)pdata;
515 555278 : uint8_t *last_start = NULL;
516 555278 : bool do_store_data = (pdata != NULL);
517 :
518 555278 : *ret_data_size = 0;
519 :
520 555278 : if (!lp_ea_support(SNUM(conn))) {
521 0 : return NT_STATUS_NO_EAS_ON_FILE;
522 : }
523 :
524 557422 : for (; ea_list; ea_list = ea_list->next) {
525 0 : size_t dos_namelen;
526 0 : fstring dos_ea_name;
527 0 : size_t this_size;
528 2144 : size_t pad = 0;
529 :
530 2144 : if (last_start != NULL && do_store_data) {
531 8 : SIVAL(last_start, 0, PTR_DIFF(p, last_start));
532 : }
533 2144 : last_start = p;
534 :
535 2144 : push_ascii_fstring(dos_ea_name, ea_list->ea.name);
536 2144 : dos_namelen = strlen(dos_ea_name);
537 2144 : if (dos_namelen > 255 || dos_namelen == 0) {
538 0 : return NT_STATUS_INTERNAL_ERROR;
539 : }
540 2144 : if (ea_list->ea.value.length > 65535) {
541 0 : return NT_STATUS_INTERNAL_ERROR;
542 : }
543 :
544 2144 : this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
545 :
546 2144 : if (ea_list->next) {
547 1071 : pad = (4 - (this_size % 4)) % 4;
548 1071 : this_size += pad;
549 : }
550 :
551 2144 : if (do_store_data) {
552 18 : if (this_size > total_data_size) {
553 0 : return NT_STATUS_INFO_LENGTH_MISMATCH;
554 : }
555 :
556 : /* We know we have room. */
557 18 : SIVAL(p, 0x00, 0); /* next offset */
558 18 : SCVAL(p, 0x04, ea_list->ea.flags);
559 18 : SCVAL(p, 0x05, dos_namelen);
560 18 : SSVAL(p, 0x06, ea_list->ea.value.length);
561 18 : strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
562 18 : memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
563 18 : if (pad) {
564 0 : memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
565 : '\0',
566 : pad);
567 : }
568 18 : total_data_size -= this_size;
569 : }
570 :
571 2144 : p += this_size;
572 : }
573 :
574 555278 : *ret_data_size = PTR_DIFF(p, pdata);
575 555278 : DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
576 555278 : return NT_STATUS_OK;
577 : }
578 :
579 739031 : unsigned int estimate_ea_size(files_struct *fsp)
580 : {
581 739031 : size_t total_ea_len = 0;
582 473 : TALLOC_CTX *mem_ctx;
583 739031 : struct ea_list *ea_list = NULL;
584 473 : NTSTATUS status;
585 :
586 : /* symlink */
587 739031 : if (fsp == NULL) {
588 0 : return 0;
589 : }
590 :
591 739031 : if (!lp_ea_support(SNUM(fsp->conn))) {
592 0 : return 0;
593 : }
594 :
595 739031 : mem_ctx = talloc_stackframe();
596 :
597 : /* If this is a stream fsp, then we need to instead find the
598 : * estimated ea len from the main file, not the stream
599 : * (streams cannot have EAs), but the estimate isn't just 0 in
600 : * this case! */
601 739031 : fsp = metadata_fsp(fsp);
602 739031 : (void)get_ea_list_from_fsp(mem_ctx,
603 : fsp,
604 : &total_ea_len,
605 : &ea_list);
606 :
607 739031 : if(fsp->conn->sconn->using_smb2) {
608 0 : unsigned int ret_data_size;
609 : /*
610 : * We're going to be using fill_ea_chained_buffer() to
611 : * marshall EA's - this size is significantly larger
612 : * than the SMB1 buffer. Re-calculate the size without
613 : * marshalling.
614 : */
615 555268 : status = fill_ea_chained_buffer(mem_ctx,
616 : NULL,
617 : 0,
618 : &ret_data_size,
619 555268 : fsp->conn,
620 : ea_list);
621 555268 : if (!NT_STATUS_IS_OK(status)) {
622 0 : ret_data_size = 0;
623 : }
624 555268 : total_ea_len = ret_data_size;
625 : }
626 739031 : TALLOC_FREE(mem_ctx);
627 739031 : return total_ea_len;
628 : }
629 :
630 : /****************************************************************************
631 : Ensure the EA name is case insensitive by matching any existing EA name.
632 : ****************************************************************************/
633 :
634 3835 : static void canonicalize_ea_name(files_struct *fsp,
635 : fstring unix_ea_name)
636 : {
637 493 : size_t total_ea_len;
638 3835 : TALLOC_CTX *mem_ctx = talloc_tos();
639 493 : struct ea_list *ea_list;
640 3835 : NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
641 : fsp,
642 : &total_ea_len,
643 : &ea_list);
644 3835 : if (!NT_STATUS_IS_OK(status)) {
645 0 : return;
646 : }
647 :
648 4838 : for (; ea_list; ea_list = ea_list->next) {
649 2116 : if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
650 1113 : DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
651 : &unix_ea_name[5], ea_list->ea.name));
652 1113 : strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
653 1113 : break;
654 : }
655 : }
656 : }
657 :
658 : /****************************************************************************
659 : Set or delete an extended attribute.
660 : ****************************************************************************/
661 :
662 3205 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
663 : struct ea_list *ea_list)
664 : {
665 500 : NTSTATUS status;
666 3205 : bool posix_pathnames = false;
667 :
668 3205 : if (!lp_ea_support(SNUM(conn))) {
669 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
670 : }
671 :
672 3205 : if (fsp == NULL) {
673 0 : return NT_STATUS_INVALID_HANDLE;
674 : }
675 :
676 3205 : posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
677 :
678 3205 : status = refuse_symlink_fsp(fsp);
679 3205 : if (!NT_STATUS_IS_OK(status)) {
680 12 : return status;
681 : }
682 :
683 3193 : status = check_access_fsp(fsp, FILE_WRITE_EA);
684 3193 : if (!NT_STATUS_IS_OK(status)) {
685 0 : return status;
686 : }
687 :
688 : /* Setting EAs on streams isn't supported. */
689 3193 : if (fsp_is_alternate_stream(fsp)) {
690 4 : return NT_STATUS_INVALID_PARAMETER;
691 : }
692 :
693 : /*
694 : * Filter out invalid Windows EA names - before
695 : * we set *any* of them.
696 : */
697 :
698 3189 : if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
699 235 : return STATUS_INVALID_EA_NAME;
700 : }
701 :
702 6787 : for (;ea_list; ea_list = ea_list->next) {
703 493 : int ret;
704 493 : fstring unix_ea_name;
705 :
706 : /*
707 : * Complementing the forward mapping from POSIX EAs to
708 : * Windows EAs in get_ea_list_from_fsp(), here we map in the
709 : * opposite direction from Windows EAs to the 'user' namespace
710 : * of POSIX EAs. Hence, all POSIX EA names the we set here must
711 : * start with a 'user.' prefix.
712 : */
713 3835 : fstrcpy(unix_ea_name, "user.");
714 3835 : fstrcat(unix_ea_name, ea_list->ea.name);
715 :
716 3835 : canonicalize_ea_name(fsp, unix_ea_name);
717 :
718 3835 : DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
719 :
720 3835 : if (samba_private_attr_name(unix_ea_name)) {
721 0 : DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
722 0 : return NT_STATUS_ACCESS_DENIED;
723 : }
724 :
725 3835 : if (ea_list->ea.value.length == 0) {
726 : /* Remove the attribute. */
727 1060 : DBG_DEBUG("deleting ea name %s on "
728 : "file %s by file descriptor.\n",
729 : unix_ea_name, fsp_str_dbg(fsp));
730 1060 : ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
731 : #ifdef ENOATTR
732 : /* Removing a non existent attribute always succeeds. */
733 1060 : if (ret == -1 && errno == ENOATTR) {
734 5 : DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
735 : unix_ea_name));
736 4 : ret = 0;
737 : }
738 : #endif
739 : } else {
740 2775 : DEBUG(10,("set_ea: setting ea name %s on file "
741 : "%s by file descriptor.\n",
742 : unix_ea_name, fsp_str_dbg(fsp)));
743 2775 : ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
744 : ea_list->ea.value.data, ea_list->ea.value.length, 0);
745 : }
746 :
747 3834 : if (ret == -1) {
748 : #ifdef ENOTSUP
749 2 : if (errno == ENOTSUP) {
750 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
751 : }
752 : #endif
753 2 : return map_nt_error_from_unix(errno);
754 : }
755 :
756 : }
757 2952 : return NT_STATUS_OK;
758 : }
759 :
760 : /****************************************************************************
761 : Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
762 : ****************************************************************************/
763 :
764 3024 : struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
765 : {
766 3024 : struct ea_list *ea_list_head = NULL;
767 3024 : size_t offset = 0;
768 3024 : size_t bytes_used = 0;
769 :
770 6794 : while (offset < data_size) {
771 3778 : struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
772 :
773 3778 : if (!eal) {
774 8 : return NULL;
775 : }
776 :
777 3770 : DLIST_ADD_END(ea_list_head, eal);
778 3770 : offset += bytes_used;
779 : }
780 :
781 2508 : return ea_list_head;
782 : }
783 :
784 : /****************************************************************************
785 : Count the total EA size needed.
786 : ****************************************************************************/
787 :
788 166 : static size_t ea_list_size(struct ea_list *ealist)
789 : {
790 28 : fstring dos_ea_name;
791 28 : struct ea_list *listp;
792 166 : size_t ret = 0;
793 :
794 350 : for (listp = ealist; listp; listp = listp->next) {
795 184 : push_ascii_fstring(dos_ea_name, listp->ea.name);
796 184 : ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
797 : }
798 : /* Add on 4 for total length. */
799 166 : if (ret) {
800 166 : ret += 4;
801 : }
802 :
803 166 : return ret;
804 : }
805 :
806 : /****************************************************************************
807 : Return a union of EA's from a file list and a list of names.
808 : The TALLOC context for the two lists *MUST* be identical as we steal
809 : memory from one list to add to another. JRA.
810 : ****************************************************************************/
811 :
812 166 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
813 : {
814 28 : struct ea_list *nlistp, *flistp;
815 :
816 350 : for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
817 340 : for (flistp = file_list; flistp; flistp = flistp->next) {
818 263 : if (strequal(nlistp->ea.name, flistp->ea.name)) {
819 88 : break;
820 : }
821 : }
822 :
823 184 : if (flistp) {
824 : /* Copy the data from this entry. */
825 107 : nlistp->ea.flags = flistp->ea.flags;
826 107 : nlistp->ea.value = flistp->ea.value;
827 : } else {
828 : /* Null entry. */
829 77 : nlistp->ea.flags = 0;
830 77 : ZERO_STRUCT(nlistp->ea.value);
831 : }
832 : }
833 :
834 166 : *total_ea_len = ea_list_size(name_list);
835 166 : return name_list;
836 : }
837 :
838 : /****************************************************************************
839 : Return the filetype for UNIX extensions.
840 : ****************************************************************************/
841 :
842 576 : static uint32_t unix_filetype(mode_t mode)
843 : {
844 576 : if(S_ISREG(mode))
845 280 : return UNIX_TYPE_FILE;
846 296 : else if(S_ISDIR(mode))
847 80 : return UNIX_TYPE_DIR;
848 : #ifdef S_ISLNK
849 216 : else if(S_ISLNK(mode))
850 208 : return UNIX_TYPE_SYMLINK;
851 : #endif
852 : #ifdef S_ISCHR
853 8 : else if(S_ISCHR(mode))
854 0 : return UNIX_TYPE_CHARDEV;
855 : #endif
856 : #ifdef S_ISBLK
857 8 : else if(S_ISBLK(mode))
858 0 : return UNIX_TYPE_BLKDEV;
859 : #endif
860 : #ifdef S_ISFIFO
861 8 : else if(S_ISFIFO(mode))
862 4 : return UNIX_TYPE_FIFO;
863 : #endif
864 : #ifdef S_ISSOCK
865 4 : else if(S_ISSOCK(mode))
866 4 : return UNIX_TYPE_SOCKET;
867 : #endif
868 :
869 0 : DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
870 0 : return UNIX_TYPE_UNKNOWN;
871 : }
872 :
873 : /****************************************************************************
874 : Map wire perms onto standard UNIX permissions. Obey share restrictions.
875 : ****************************************************************************/
876 :
877 3086 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
878 : const SMB_STRUCT_STAT *psbuf,
879 : uint32_t perms,
880 : enum perm_type ptype,
881 : mode_t *ret_perms)
882 : {
883 3086 : mode_t ret = 0;
884 :
885 3086 : if (perms == SMB_MODE_NO_CHANGE) {
886 132 : if (!VALID_STAT(*psbuf)) {
887 0 : return NT_STATUS_INVALID_PARAMETER;
888 : } else {
889 132 : *ret_perms = psbuf->st_ex_mode;
890 132 : return NT_STATUS_OK;
891 : }
892 : }
893 :
894 2954 : ret = wire_perms_to_unix(perms);
895 :
896 2954 : if (ptype == PERM_NEW_FILE) {
897 : /*
898 : * "create mask"/"force create mode" are
899 : * only applied to new files, not existing ones.
900 : */
901 2173 : ret &= lp_create_mask(SNUM(conn));
902 : /* Add in force bits */
903 2173 : ret |= lp_force_create_mode(SNUM(conn));
904 781 : } else if (ptype == PERM_NEW_DIR) {
905 : /*
906 : * "directory mask"/"force directory mode" are
907 : * only applied to new directories, not existing ones.
908 : */
909 701 : ret &= lp_directory_mask(SNUM(conn));
910 : /* Add in force bits */
911 701 : ret |= lp_force_directory_mode(SNUM(conn));
912 : }
913 :
914 2954 : *ret_perms = ret;
915 2954 : return NT_STATUS_OK;
916 : }
917 :
918 : /****************************************************************************
919 : Get a level dependent lanman2 dir entry.
920 : ****************************************************************************/
921 :
922 : struct smbd_dirptr_lanman2_state {
923 : connection_struct *conn;
924 : uint32_t info_level;
925 : bool check_mangled_names;
926 : bool case_sensitive;
927 : };
928 :
929 908548 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
930 : void *private_data,
931 : const char *dname,
932 : const char *mask,
933 : char **_fname)
934 : {
935 908548 : struct smbd_dirptr_lanman2_state *state =
936 : (struct smbd_dirptr_lanman2_state *)private_data;
937 315 : bool ok;
938 315 : char mangled_name[13]; /* mangled 8.3 name. */
939 315 : bool got_match;
940 315 : const char *fname;
941 :
942 : /* Mangle fname if it's an illegal name. */
943 908548 : if (mangle_must_mangle(dname, state->conn->params)) {
944 : /*
945 : * Slow path - ensure we can push the original name as UCS2. If
946 : * not, then just don't return this name.
947 : */
948 0 : NTSTATUS status;
949 106 : size_t ret_len = 0;
950 106 : size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
951 106 : uint8_t *tmp = talloc_array(talloc_tos(),
952 : uint8_t,
953 : len);
954 :
955 106 : status = srvstr_push(NULL,
956 : FLAGS2_UNICODE_STRINGS,
957 : tmp,
958 : dname,
959 : len,
960 : STR_TERMINATE,
961 : &ret_len);
962 :
963 106 : TALLOC_FREE(tmp);
964 :
965 106 : if (!NT_STATUS_IS_OK(status)) {
966 40 : return false;
967 : }
968 :
969 66 : ok = name_to_8_3(dname, mangled_name,
970 66 : true, state->conn->params);
971 66 : if (!ok) {
972 0 : return false;
973 : }
974 66 : fname = mangled_name;
975 : } else {
976 908127 : fname = dname;
977 : }
978 :
979 908823 : got_match = mask_match(fname, mask,
980 908508 : state->case_sensitive);
981 :
982 908508 : if(!got_match && state->check_mangled_names &&
983 5747 : !mangle_is_8_3(fname, false, state->conn->params)) {
984 : /*
985 : * It turns out that NT matches wildcards against
986 : * both long *and* short names. This may explain some
987 : * of the wildcard weirdness from old DOS clients
988 : * that some people have been seeing.... JRA.
989 : */
990 : /* Force the mangling into 8.3. */
991 3348 : ok = name_to_8_3(fname, mangled_name,
992 3348 : false, state->conn->params);
993 3348 : if (!ok) {
994 0 : return false;
995 : }
996 :
997 3348 : got_match = mask_match(mangled_name, mask,
998 3348 : state->case_sensitive);
999 : }
1000 :
1001 908508 : if (!got_match) {
1002 5743 : return false;
1003 : }
1004 :
1005 902765 : *_fname = talloc_strdup(ctx, fname);
1006 902765 : if (*_fname == NULL) {
1007 0 : return false;
1008 : }
1009 :
1010 902450 : return true;
1011 : }
1012 :
1013 625635 : static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1014 : {
1015 625635 : if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1016 625265 : unsigned ea_size = estimate_ea_size(fsp);
1017 625265 : return ea_size;
1018 : }
1019 370 : return IO_REPARSE_TAG_DFS;
1020 : }
1021 :
1022 894407 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1023 : connection_struct *conn,
1024 : uint16_t flags2,
1025 : uint32_t info_level,
1026 : struct ea_list *name_list,
1027 : bool check_mangled_names,
1028 : bool requires_resume_key,
1029 : uint32_t mode,
1030 : const char *fname,
1031 : const struct smb_filename *smb_fname,
1032 : int space_remaining,
1033 : uint8_t align,
1034 : bool do_pad,
1035 : char *base_data,
1036 : char **ppdata,
1037 : char *end_data,
1038 : uint64_t *last_entry_off)
1039 : {
1040 894407 : char *p, *q, *pdata = *ppdata;
1041 894407 : uint32_t reskey=0;
1042 894407 : uint64_t file_size = 0;
1043 894407 : uint64_t allocation_size = 0;
1044 894407 : uint64_t file_id = 0;
1045 894407 : size_t len = 0;
1046 894407 : struct timespec mdate_ts = {0};
1047 894407 : struct timespec adate_ts = {0};
1048 894407 : struct timespec cdate_ts = {0};
1049 894407 : struct timespec create_date_ts = {0};
1050 894407 : time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1051 227 : char *nameptr;
1052 227 : char *last_entry_ptr;
1053 227 : bool was_8_3;
1054 227 : int off;
1055 894407 : int pad = 0;
1056 227 : NTSTATUS status;
1057 894407 : struct readdir_attr_data *readdir_attr_data = NULL;
1058 227 : uint32_t ea_size;
1059 :
1060 894407 : if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1061 833460 : file_size = get_file_size_stat(&smb_fname->st);
1062 : }
1063 894407 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1064 :
1065 : /*
1066 : * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1067 : * a DFS symlink.
1068 : */
1069 894407 : if (smb_fname->fsp != NULL &&
1070 894180 : !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1071 894037 : status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1072 : ctx,
1073 : &readdir_attr_data);
1074 894037 : if (!NT_STATUS_IS_OK(status)) {
1075 893733 : if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1076 : status)) {
1077 0 : return status;
1078 : }
1079 : }
1080 : }
1081 :
1082 894407 : file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1083 :
1084 894407 : mdate_ts = smb_fname->st.st_ex_mtime;
1085 894407 : adate_ts = smb_fname->st.st_ex_atime;
1086 894407 : create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1087 894407 : cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1088 :
1089 894407 : if (lp_dos_filetime_resolution(SNUM(conn))) {
1090 0 : dos_filetime_timespec(&create_date_ts);
1091 0 : dos_filetime_timespec(&mdate_ts);
1092 0 : dos_filetime_timespec(&adate_ts);
1093 0 : dos_filetime_timespec(&cdate_ts);
1094 : }
1095 :
1096 894407 : create_date = convert_timespec_to_time_t(create_date_ts);
1097 894407 : mdate = convert_timespec_to_time_t(mdate_ts);
1098 894407 : adate = convert_timespec_to_time_t(adate_ts);
1099 :
1100 : /* align the record */
1101 894407 : SMB_ASSERT(align >= 1);
1102 :
1103 894407 : off = (int)PTR_DIFF(pdata, base_data);
1104 894407 : pad = (off + (align-1)) & ~(align-1);
1105 894407 : pad -= off;
1106 :
1107 894407 : if (pad && pad > space_remaining) {
1108 0 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1109 : "for padding (wanted %u, had %d)\n",
1110 : (unsigned int)pad,
1111 : space_remaining ));
1112 0 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1113 : }
1114 :
1115 894407 : off += pad;
1116 : /* initialize padding to 0 */
1117 894407 : if (pad) {
1118 643383 : memset(pdata, 0, pad);
1119 : }
1120 894407 : space_remaining -= pad;
1121 :
1122 894407 : DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1123 : space_remaining ));
1124 :
1125 894407 : pdata += pad;
1126 894407 : p = pdata;
1127 894407 : last_entry_ptr = p;
1128 :
1129 894407 : pad = 0;
1130 894407 : off = 0;
1131 :
1132 894407 : switch (info_level) {
1133 8406 : case SMB_FIND_INFO_STANDARD:
1134 8406 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1135 8406 : if(requires_resume_key) {
1136 0 : SIVAL(p,0,reskey);
1137 0 : p += 4;
1138 : }
1139 8406 : srv_put_dos_date2(p,0,create_date);
1140 8406 : srv_put_dos_date2(p,4,adate);
1141 8406 : srv_put_dos_date2(p,8,mdate);
1142 8406 : SIVAL(p,12,(uint32_t)file_size);
1143 8406 : SIVAL(p,16,(uint32_t)allocation_size);
1144 8406 : SSVAL(p,20,mode);
1145 8406 : p += 23;
1146 8406 : nameptr = p;
1147 8406 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1148 8406 : p += ucs2_align(base_data, p, 0);
1149 : }
1150 8406 : status = srvstr_push(base_data, flags2, p,
1151 : fname, PTR_DIFF(end_data, p),
1152 : STR_TERMINATE, &len);
1153 8406 : if (!NT_STATUS_IS_OK(status)) {
1154 40 : return status;
1155 : }
1156 8406 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1157 8406 : if (len > 2) {
1158 8406 : SCVAL(nameptr, -1, len - 2);
1159 : } else {
1160 0 : SCVAL(nameptr, -1, 0);
1161 : }
1162 : } else {
1163 0 : if (len > 1) {
1164 0 : SCVAL(nameptr, -1, len - 1);
1165 : } else {
1166 0 : SCVAL(nameptr, -1, 0);
1167 : }
1168 : }
1169 8406 : p += len;
1170 8406 : break;
1171 :
1172 106206 : case SMB_FIND_EA_SIZE:
1173 106206 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1174 106206 : if (requires_resume_key) {
1175 97800 : SIVAL(p,0,reskey);
1176 97800 : p += 4;
1177 : }
1178 106206 : srv_put_dos_date2(p,0,create_date);
1179 106206 : srv_put_dos_date2(p,4,adate);
1180 106206 : srv_put_dos_date2(p,8,mdate);
1181 106206 : SIVAL(p,12,(uint32_t)file_size);
1182 106206 : SIVAL(p,16,(uint32_t)allocation_size);
1183 106206 : SSVAL(p,20,mode);
1184 : {
1185 106206 : ea_size = estimate_ea_size(smb_fname->fsp);
1186 106206 : SIVAL(p,22,ea_size); /* Extended attributes */
1187 : }
1188 106206 : p += 27;
1189 106206 : nameptr = p - 1;
1190 106206 : status = srvstr_push(base_data, flags2,
1191 : p, fname, PTR_DIFF(end_data, p),
1192 : STR_TERMINATE | STR_NOALIGN, &len);
1193 106206 : if (!NT_STATUS_IS_OK(status)) {
1194 0 : return status;
1195 : }
1196 106206 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1197 106206 : if (len > 2) {
1198 106206 : len -= 2;
1199 : } else {
1200 0 : len = 0;
1201 : }
1202 : } else {
1203 0 : if (len > 1) {
1204 0 : len -= 1;
1205 : } else {
1206 0 : len = 0;
1207 : }
1208 : }
1209 106206 : SCVAL(nameptr,0,len);
1210 106206 : p += len;
1211 106206 : SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1212 106206 : break;
1213 :
1214 18 : case SMB_FIND_EA_LIST:
1215 : {
1216 18 : struct ea_list *file_list = NULL;
1217 18 : size_t ea_len = 0;
1218 :
1219 18 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1220 18 : if (!name_list) {
1221 0 : return NT_STATUS_INVALID_PARAMETER;
1222 : }
1223 18 : if (requires_resume_key) {
1224 18 : SIVAL(p,0,reskey);
1225 18 : p += 4;
1226 : }
1227 18 : srv_put_dos_date2(p,0,create_date);
1228 18 : srv_put_dos_date2(p,4,adate);
1229 18 : srv_put_dos_date2(p,8,mdate);
1230 18 : SIVAL(p,12,(uint32_t)file_size);
1231 18 : SIVAL(p,16,(uint32_t)allocation_size);
1232 18 : SSVAL(p,20,mode);
1233 18 : p += 22; /* p now points to the EA area. */
1234 :
1235 18 : status = get_ea_list_from_fsp(ctx,
1236 18 : smb_fname->fsp,
1237 : &ea_len, &file_list);
1238 18 : if (!NT_STATUS_IS_OK(status)) {
1239 0 : file_list = NULL;
1240 : }
1241 18 : name_list = ea_list_union(name_list, file_list, &ea_len);
1242 :
1243 : /* We need to determine if this entry will fit in the space available. */
1244 : /* Max string size is 255 bytes. */
1245 18 : if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1246 0 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1247 : "(wanted %u, had %d)\n",
1248 : (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1249 : space_remaining ));
1250 0 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1251 : }
1252 :
1253 : /* Push the ea_data followed by the name. */
1254 18 : p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1255 18 : nameptr = p;
1256 18 : status = srvstr_push(base_data, flags2,
1257 : p + 1, fname, PTR_DIFF(end_data, p+1),
1258 : STR_TERMINATE | STR_NOALIGN, &len);
1259 18 : if (!NT_STATUS_IS_OK(status)) {
1260 0 : return status;
1261 : }
1262 18 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1263 18 : if (len > 2) {
1264 18 : len -= 2;
1265 : } else {
1266 0 : len = 0;
1267 : }
1268 : } else {
1269 0 : if (len > 1) {
1270 0 : len -= 1;
1271 : } else {
1272 0 : len = 0;
1273 : }
1274 : }
1275 18 : SCVAL(nameptr,0,len);
1276 18 : p += len + 1;
1277 18 : SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1278 18 : break;
1279 : }
1280 :
1281 113644 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1282 113644 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1283 113644 : was_8_3 = mangle_is_8_3(fname, True, conn->params);
1284 113644 : p += 4;
1285 113644 : SIVAL(p,0,reskey); p += 4;
1286 113644 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1287 113644 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1288 113644 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1289 113644 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1290 113644 : SOFF_T(p,0,file_size); p += 8;
1291 113644 : SOFF_T(p,0,allocation_size); p += 8;
1292 113644 : SIVAL(p,0,mode); p += 4;
1293 113644 : q = p; p += 4; /* q is placeholder for name length. */
1294 113644 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1295 113644 : SIVAL(p, 0, ea_size);
1296 113644 : p += 4;
1297 : /* Clear the short name buffer. This is
1298 : * IMPORTANT as not doing so will trigger
1299 : * a Win2k client bug. JRA.
1300 : */
1301 113644 : if (!was_8_3 && check_mangled_names) {
1302 25 : char mangled_name[13]; /* mangled 8.3 name. */
1303 20088 : if (!name_to_8_3(fname,mangled_name,True,
1304 20088 : conn->params)) {
1305 : /* Error - mangle failed ! */
1306 0 : memset(mangled_name,'\0',12);
1307 : }
1308 20088 : mangled_name[12] = 0;
1309 20088 : status = srvstr_push(base_data, flags2,
1310 : p+2, mangled_name, 24,
1311 : STR_UPPER|STR_UNICODE, &len);
1312 20088 : if (!NT_STATUS_IS_OK(status)) {
1313 0 : return status;
1314 : }
1315 20088 : if (len < 24) {
1316 10899 : memset(p + 2 + len,'\0',24 - len);
1317 : }
1318 20088 : SSVAL(p, 0, len);
1319 : } else {
1320 93556 : memset(p,'\0',26);
1321 : }
1322 113644 : p += 2 + 24;
1323 113644 : status = srvstr_push(base_data, flags2, p,
1324 : fname, PTR_DIFF(end_data, p),
1325 : STR_TERMINATE_ASCII, &len);
1326 113644 : if (!NT_STATUS_IS_OK(status)) {
1327 12 : return status;
1328 : }
1329 113632 : SIVAL(q,0,len);
1330 113632 : p += len;
1331 :
1332 113632 : len = PTR_DIFF(p, pdata);
1333 113632 : pad = (len + (align-1)) & ~(align-1);
1334 : /*
1335 : * offset to the next entry, the caller
1336 : * will overwrite it for the last entry
1337 : * that's why we always include the padding
1338 : */
1339 113632 : SIVAL(pdata,0,pad);
1340 : /*
1341 : * set padding to zero
1342 : */
1343 113632 : if (do_pad) {
1344 50044 : memset(p, 0, pad - len);
1345 50044 : p = pdata + pad;
1346 : } else {
1347 63588 : p = pdata + len;
1348 : }
1349 113498 : break;
1350 :
1351 20700 : case SMB_FIND_FILE_DIRECTORY_INFO:
1352 20700 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1353 20700 : p += 4;
1354 20700 : SIVAL(p,0,reskey); p += 4;
1355 20700 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1356 20700 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1357 20700 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1358 20700 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1359 20700 : SOFF_T(p,0,file_size); p += 8;
1360 20700 : SOFF_T(p,0,allocation_size); p += 8;
1361 20700 : SIVAL(p,0,mode); p += 4;
1362 20700 : status = srvstr_push(base_data, flags2,
1363 : p + 4, fname, PTR_DIFF(end_data, p+4),
1364 : STR_TERMINATE_ASCII, &len);
1365 20700 : if (!NT_STATUS_IS_OK(status)) {
1366 0 : return status;
1367 : }
1368 20700 : SIVAL(p,0,len);
1369 20700 : p += 4 + len;
1370 :
1371 20700 : len = PTR_DIFF(p, pdata);
1372 20700 : pad = (len + (align-1)) & ~(align-1);
1373 : /*
1374 : * offset to the next entry, the caller
1375 : * will overwrite it for the last entry
1376 : * that's why we always include the padding
1377 : */
1378 20700 : SIVAL(pdata,0,pad);
1379 : /*
1380 : * set padding to zero
1381 : */
1382 20700 : if (do_pad) {
1383 8406 : memset(p, 0, pad - len);
1384 8406 : p = pdata + pad;
1385 : } else {
1386 12294 : p = pdata + len;
1387 : }
1388 20700 : break;
1389 :
1390 420921 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1391 420921 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1392 420921 : p += 4;
1393 420921 : SIVAL(p,0,reskey); p += 4;
1394 420921 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1395 420921 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1396 420921 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1397 420921 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1398 420921 : SOFF_T(p,0,file_size); p += 8;
1399 420921 : SOFF_T(p,0,allocation_size); p += 8;
1400 420921 : SIVAL(p,0,mode); p += 4;
1401 420921 : q = p; p += 4; /* q is placeholder for name length. */
1402 420921 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1403 420921 : SIVAL(p, 0, ea_size);
1404 420921 : p +=4;
1405 420921 : status = srvstr_push(base_data, flags2, p,
1406 : fname, PTR_DIFF(end_data, p),
1407 : STR_TERMINATE_ASCII, &len);
1408 420921 : if (!NT_STATUS_IS_OK(status)) {
1409 0 : return status;
1410 : }
1411 420921 : SIVAL(q, 0, len);
1412 420921 : p += len;
1413 :
1414 420921 : len = PTR_DIFF(p, pdata);
1415 420921 : pad = (len + (align-1)) & ~(align-1);
1416 : /*
1417 : * offset to the next entry, the caller
1418 : * will overwrite it for the last entry
1419 : * that's why we always include the padding
1420 : */
1421 420921 : SIVAL(pdata,0,pad);
1422 : /*
1423 : * set padding to zero
1424 : */
1425 420921 : if (do_pad) {
1426 8841 : memset(p, 0, pad - len);
1427 8841 : p = pdata + pad;
1428 : } else {
1429 412080 : p = pdata + len;
1430 : }
1431 420834 : break;
1432 :
1433 131903 : case SMB_FIND_FILE_NAMES_INFO:
1434 131903 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1435 131903 : p += 4;
1436 131903 : SIVAL(p,0,reskey); p += 4;
1437 131903 : p += 4;
1438 : /* this must *not* be null terminated or w2k gets in a loop trying to set an
1439 : acl on a dir (tridge) */
1440 131903 : status = srvstr_push(base_data, flags2, p,
1441 : fname, PTR_DIFF(end_data, p),
1442 : STR_TERMINATE_ASCII, &len);
1443 131903 : if (!NT_STATUS_IS_OK(status)) {
1444 0 : return status;
1445 : }
1446 131903 : SIVAL(p, -4, len);
1447 131903 : p += len;
1448 :
1449 131903 : len = PTR_DIFF(p, pdata);
1450 131903 : pad = (len + (align-1)) & ~(align-1);
1451 : /*
1452 : * offset to the next entry, the caller
1453 : * will overwrite it for the last entry
1454 : * that's why we always include the padding
1455 : */
1456 131903 : SIVAL(pdata,0,pad);
1457 : /*
1458 : * set padding to zero
1459 : */
1460 131903 : if (do_pad) {
1461 6 : memset(p, 0, pad - len);
1462 6 : p = pdata + pad;
1463 : } else {
1464 131897 : p = pdata + len;
1465 : }
1466 131897 : break;
1467 :
1468 19638 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1469 19638 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1470 19638 : p += 4;
1471 19638 : SIVAL(p,0,reskey); p += 4;
1472 19638 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1473 19638 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1474 19638 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1475 19638 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1476 19638 : SOFF_T(p,0,file_size); p += 8;
1477 19638 : SOFF_T(p,0,allocation_size); p += 8;
1478 19638 : SIVAL(p,0,mode); p += 4;
1479 19638 : q = p; p += 4; /* q is placeholder for name length. */
1480 19638 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1481 19638 : SIVAL(p, 0, ea_size);
1482 19638 : p += 4;
1483 19638 : SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1484 19638 : SBVAL(p,0,file_id); p += 8;
1485 19638 : status = srvstr_push(base_data, flags2, p,
1486 : fname, PTR_DIFF(end_data, p),
1487 : STR_TERMINATE_ASCII, &len);
1488 19638 : if (!NT_STATUS_IS_OK(status)) {
1489 0 : return status;
1490 : }
1491 19638 : SIVAL(q, 0, len);
1492 19638 : p += len;
1493 :
1494 19638 : len = PTR_DIFF(p, pdata);
1495 19638 : pad = (len + (align-1)) & ~(align-1);
1496 : /*
1497 : * offset to the next entry, the caller
1498 : * will overwrite it for the last entry
1499 : * that's why we always include the padding
1500 : */
1501 19638 : SIVAL(pdata,0,pad);
1502 : /*
1503 : * set padding to zero
1504 : */
1505 19638 : if (do_pad) {
1506 8406 : memset(p, 0, pad - len);
1507 8406 : p = pdata + pad;
1508 : } else {
1509 11232 : p = pdata + len;
1510 : }
1511 19638 : break;
1512 :
1513 71530 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1514 71530 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1515 71530 : was_8_3 = mangle_is_8_3(fname, True, conn->params);
1516 71530 : p += 4;
1517 71530 : SIVAL(p,0,reskey); p += 4;
1518 71530 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1519 71530 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1520 71530 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1521 71530 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1522 71530 : SOFF_T(p,0,file_size); p += 8;
1523 71530 : SOFF_T(p,0,allocation_size); p += 8;
1524 71530 : SIVAL(p,0,mode); p += 4;
1525 71530 : q = p; p += 4; /* q is placeholder for name length */
1526 71530 : if (readdir_attr_data &&
1527 98 : readdir_attr_data->type == RDATTR_AAPL) {
1528 : /*
1529 : * OS X specific SMB2 extension negotiated via
1530 : * AAPL create context: return max_access in
1531 : * ea_size field.
1532 : */
1533 98 : ea_size = readdir_attr_data->attr_data.aapl.max_access;
1534 : } else {
1535 71432 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1536 : }
1537 71530 : SIVAL(p,0,ea_size); /* Extended attributes */
1538 71530 : p += 4;
1539 :
1540 71530 : if (readdir_attr_data &&
1541 98 : readdir_attr_data->type == RDATTR_AAPL) {
1542 : /*
1543 : * OS X specific SMB2 extension negotiated via
1544 : * AAPL create context: return resource fork
1545 : * length and compressed FinderInfo in
1546 : * shortname field.
1547 : *
1548 : * According to documentation short_name_len
1549 : * should be 0, but on the wire behaviour
1550 : * shows its set to 24 by clients.
1551 : */
1552 98 : SSVAL(p, 0, 24);
1553 :
1554 : /* Resourefork length */
1555 98 : SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1556 :
1557 : /* Compressed FinderInfo */
1558 98 : memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1559 71432 : } else if (!was_8_3 && check_mangled_names) {
1560 0 : char mangled_name[13]; /* mangled 8.3 name. */
1561 22221 : if (!name_to_8_3(fname,mangled_name,True,
1562 22221 : conn->params)) {
1563 : /* Error - mangle failed ! */
1564 0 : memset(mangled_name,'\0',12);
1565 : }
1566 22221 : mangled_name[12] = 0;
1567 22221 : status = srvstr_push(base_data, flags2,
1568 : p+2, mangled_name, 24,
1569 : STR_UPPER|STR_UNICODE, &len);
1570 22221 : if (!NT_STATUS_IS_OK(status)) {
1571 0 : return status;
1572 : }
1573 22221 : SSVAL(p, 0, len);
1574 22221 : if (len < 24) {
1575 20585 : memset(p + 2 + len,'\0',24 - len);
1576 : }
1577 22221 : SSVAL(p, 0, len);
1578 : } else {
1579 : /* Clear the short name buffer. This is
1580 : * IMPORTANT as not doing so will trigger
1581 : * a Win2k client bug. JRA.
1582 : */
1583 49211 : memset(p,'\0',26);
1584 : }
1585 71530 : p += 26;
1586 :
1587 : /* Reserved ? */
1588 71530 : if (readdir_attr_data &&
1589 98 : readdir_attr_data->type == RDATTR_AAPL) {
1590 : /*
1591 : * OS X specific SMB2 extension negotiated via
1592 : * AAPL create context: return UNIX mode in
1593 : * reserved field.
1594 : */
1595 98 : uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1596 98 : SSVAL(p, 0, aapl_mode);
1597 : } else {
1598 71432 : SSVAL(p, 0, 0);
1599 : }
1600 71530 : p += 2;
1601 :
1602 71530 : SBVAL(p,0,file_id); p += 8;
1603 71530 : status = srvstr_push(base_data, flags2, p,
1604 : fname, PTR_DIFF(end_data, p),
1605 : STR_TERMINATE_ASCII, &len);
1606 71530 : if (!NT_STATUS_IS_OK(status)) {
1607 28 : return status;
1608 : }
1609 71502 : SIVAL(q,0,len);
1610 71502 : p += len;
1611 :
1612 71502 : len = PTR_DIFF(p, pdata);
1613 71502 : pad = (len + (align-1)) & ~(align-1);
1614 : /*
1615 : * offset to the next entry, the caller
1616 : * will overwrite it for the last entry
1617 : * that's why we always include the padding
1618 : */
1619 71502 : SIVAL(pdata,0,pad);
1620 : /*
1621 : * set padding to zero
1622 : */
1623 71502 : if (do_pad) {
1624 8406 : memset(p, 0, pad - len);
1625 8406 : p = pdata + pad;
1626 : } else {
1627 63096 : p = pdata + len;
1628 : }
1629 71502 : break;
1630 :
1631 : /* CIFS UNIX Extension. */
1632 :
1633 10 : case SMB_FIND_FILE_UNIX:
1634 : case SMB_FIND_FILE_UNIX_INFO2:
1635 10 : p+= 4;
1636 10 : SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1637 :
1638 : /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1639 :
1640 10 : if (info_level == SMB_FIND_FILE_UNIX) {
1641 6 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1642 6 : p = store_file_unix_basic(conn, p,
1643 : NULL, &smb_fname->st);
1644 6 : status = srvstr_push(base_data, flags2, p,
1645 : fname, PTR_DIFF(end_data, p),
1646 : STR_TERMINATE, &len);
1647 6 : if (!NT_STATUS_IS_OK(status)) {
1648 0 : return status;
1649 : }
1650 : } else {
1651 4 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1652 4 : p = store_file_unix_basic_info2(conn, p,
1653 : NULL, &smb_fname->st);
1654 4 : nameptr = p;
1655 4 : p += 4;
1656 4 : status = srvstr_push(base_data, flags2, p, fname,
1657 : PTR_DIFF(end_data, p), 0, &len);
1658 4 : if (!NT_STATUS_IS_OK(status)) {
1659 0 : return status;
1660 : }
1661 4 : SIVAL(nameptr, 0, len);
1662 : }
1663 :
1664 10 : p += len;
1665 :
1666 10 : len = PTR_DIFF(p, pdata);
1667 10 : pad = (len + (align-1)) & ~(align-1);
1668 : /*
1669 : * offset to the next entry, the caller
1670 : * will overwrite it for the last entry
1671 : * that's why we always include the padding
1672 : */
1673 10 : SIVAL(pdata,0,pad);
1674 : /*
1675 : * set padding to zero
1676 : */
1677 10 : if (do_pad) {
1678 10 : memset(p, 0, pad - len);
1679 10 : p = pdata + pad;
1680 : } else {
1681 0 : p = pdata + len;
1682 : }
1683 : /* End of SMB_QUERY_FILE_UNIX_BASIC */
1684 :
1685 10 : break;
1686 :
1687 : /* SMB2 UNIX Extension. */
1688 :
1689 1431 : case SMB2_FILE_POSIX_INFORMATION:
1690 : {
1691 1431 : struct smb3_file_posix_information info = {};
1692 0 : uint8_t buf[sizeof(info)];
1693 1431 : struct ndr_push ndr = {
1694 : .data = buf,
1695 : .alloc_size = sizeof(buf),
1696 : .fixed_buf_size = true,
1697 : };
1698 0 : enum ndr_err_code ndr_err;
1699 :
1700 1431 : p+= 4;
1701 1431 : SIVAL(p,0,reskey); p+= 4;
1702 :
1703 1431 : DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1704 :
1705 1431 : if (!(conn->sconn->using_smb2)) {
1706 0 : return NT_STATUS_INVALID_LEVEL;
1707 : }
1708 :
1709 1431 : smb3_file_posix_information_init(
1710 1431 : conn, &smb_fname->st, 0, mode, &info);
1711 :
1712 1431 : ndr_err = ndr_push_smb3_file_posix_information(
1713 : &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1714 1431 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1715 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1716 : }
1717 :
1718 1431 : memcpy(p, buf, ndr.offset);
1719 1431 : p += ndr.offset;
1720 :
1721 1431 : nameptr = p;
1722 1431 : p += 4;
1723 1431 : status = srvstr_push(base_data, flags2, p, fname,
1724 : PTR_DIFF(end_data, p), 0, &len);
1725 1431 : if (!NT_STATUS_IS_OK(status)) {
1726 0 : return status;
1727 : }
1728 1431 : SIVAL(nameptr, 0, len);
1729 :
1730 1431 : p += len;
1731 :
1732 1431 : len = PTR_DIFF(p, pdata);
1733 1431 : pad = (len + (align-1)) & ~(align-1);
1734 : /*
1735 : * offset to the next entry, the caller
1736 : * will overwrite it for the last entry
1737 : * that's why we always include the padding
1738 : */
1739 1431 : SIVAL(pdata,0,pad);
1740 1431 : break;
1741 : }
1742 :
1743 0 : default:
1744 0 : return NT_STATUS_INVALID_LEVEL;
1745 : }
1746 :
1747 894367 : if (PTR_DIFF(p,pdata) > space_remaining) {
1748 668 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1749 : "(wanted %u, had %d)\n",
1750 : (unsigned int)PTR_DIFF(p,pdata),
1751 : space_remaining ));
1752 668 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1753 : }
1754 :
1755 : /* Setup the last entry pointer, as an offset from base_data */
1756 893699 : *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1757 : /* Advance the data pointer to the next slot */
1758 893699 : *ppdata = p;
1759 :
1760 893699 : return NT_STATUS_OK;
1761 : }
1762 :
1763 921969 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1764 : connection_struct *conn,
1765 : struct dptr_struct *dirptr,
1766 : uint16_t flags2,
1767 : const char *path_mask,
1768 : uint32_t dirtype,
1769 : int info_level,
1770 : int requires_resume_key,
1771 : bool dont_descend,
1772 : bool ask_sharemode,
1773 : bool get_dosmode,
1774 : uint8_t align,
1775 : bool do_pad,
1776 : char **ppdata,
1777 : char *base_data,
1778 : char *end_data,
1779 : int space_remaining,
1780 : struct smb_filename **_smb_fname,
1781 : int *_last_entry_off,
1782 : struct ea_list *name_list,
1783 : struct file_id *file_id)
1784 : {
1785 316 : const char *p;
1786 921969 : const char *mask = NULL;
1787 921969 : uint32_t mode = 0;
1788 921969 : char *fname = NULL;
1789 921969 : struct smb_filename *smb_fname = NULL;
1790 316 : struct smbd_dirptr_lanman2_state state;
1791 316 : bool ok;
1792 921969 : uint64_t last_entry_off = 0;
1793 316 : NTSTATUS status;
1794 316 : enum mangled_names_options mangled_names;
1795 316 : bool marshall_with_83_names;
1796 :
1797 921969 : mangled_names = lp_mangled_names(conn->params);
1798 :
1799 921969 : ZERO_STRUCT(state);
1800 921969 : state.conn = conn;
1801 921969 : state.info_level = info_level;
1802 921969 : if (mangled_names != MANGLED_NAMES_NO) {
1803 920373 : state.check_mangled_names = true;
1804 : }
1805 921969 : state.case_sensitive = dptr_case_sensitive(dirptr);
1806 :
1807 921969 : p = strrchr_m(path_mask,'/');
1808 921969 : if(p != NULL) {
1809 0 : if(p[1] == '\0') {
1810 0 : mask = "*.*";
1811 : } else {
1812 0 : mask = p+1;
1813 : }
1814 : } else {
1815 921653 : mask = path_mask;
1816 : }
1817 :
1818 921969 : ok = smbd_dirptr_get_entry(ctx,
1819 : dirptr,
1820 : mask,
1821 : dirtype,
1822 : dont_descend,
1823 : ask_sharemode,
1824 : get_dosmode,
1825 : smbd_dirptr_lanman2_match_fn,
1826 : &state,
1827 : &fname,
1828 : &smb_fname,
1829 : &mode);
1830 921969 : if (!ok) {
1831 27562 : return NT_STATUS_END_OF_FILE;
1832 : }
1833 :
1834 894407 : marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1835 :
1836 894407 : status = smbd_marshall_dir_entry(ctx,
1837 : conn,
1838 : flags2,
1839 : info_level,
1840 : name_list,
1841 : marshall_with_83_names,
1842 : requires_resume_key,
1843 : mode,
1844 : fname,
1845 : smb_fname,
1846 : space_remaining,
1847 : align,
1848 : do_pad,
1849 : base_data,
1850 : ppdata,
1851 : end_data,
1852 : &last_entry_off);
1853 894407 : if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1854 40 : DEBUG(1,("Conversion error: illegal character: %s\n",
1855 : smb_fname_str_dbg(smb_fname)));
1856 : }
1857 :
1858 894407 : if (file_id != NULL) {
1859 695646 : *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1860 : }
1861 :
1862 894407 : if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1863 668 : smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1864 : }
1865 :
1866 894407 : if (!NT_STATUS_IS_OK(status)) {
1867 708 : TALLOC_FREE(smb_fname);
1868 708 : TALLOC_FREE(fname);
1869 708 : return status;
1870 : }
1871 :
1872 893699 : smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1873 :
1874 893699 : if (_smb_fname != NULL) {
1875 : /*
1876 : * smb_fname is already talloc'ed off ctx.
1877 : * We just need to make sure we don't return
1878 : * any stream_name, and replace base_name
1879 : * with fname in case base_name got mangled.
1880 : * This allows us to preserve any smb_fname->fsp
1881 : * for asynchronous handle lookups.
1882 : */
1883 694950 : TALLOC_FREE(smb_fname->stream_name);
1884 :
1885 : /*
1886 : * smbd_dirptr_set_last_name_sent() above consumed
1887 : * base_name
1888 : */
1889 694950 : smb_fname->base_name = talloc_strdup(smb_fname, fname);
1890 :
1891 694950 : if (smb_fname->base_name == NULL) {
1892 0 : TALLOC_FREE(smb_fname);
1893 0 : TALLOC_FREE(fname);
1894 0 : return NT_STATUS_NO_MEMORY;
1895 : }
1896 694950 : *_smb_fname = smb_fname;
1897 : } else {
1898 198749 : TALLOC_FREE(smb_fname);
1899 : }
1900 893699 : TALLOC_FREE(fname);
1901 :
1902 893699 : *_last_entry_off = last_entry_off;
1903 893699 : return NT_STATUS_OK;
1904 : }
1905 :
1906 112 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1907 : {
1908 0 : const struct loadparm_substitution *lp_sub =
1909 112 : loadparm_s3_global_substitution();
1910 :
1911 112 : E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1912 112 : return objid;
1913 : }
1914 :
1915 40 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
1916 : {
1917 40 : SMB_ASSERT(extended_info != NULL);
1918 :
1919 40 : extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1920 40 : extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1921 : | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1922 : | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1923 : #ifdef SAMBA_VERSION_REVISION
1924 : extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1925 : #endif
1926 40 : extended_info->samba_subversion = 0;
1927 : #ifdef SAMBA_VERSION_RC_RELEASE
1928 : extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1929 : #else
1930 : #ifdef SAMBA_VERSION_PRE_RELEASE
1931 40 : extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1932 : #endif
1933 : #endif
1934 : #ifdef SAMBA_VERSION_VENDOR_PATCH
1935 : extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1936 : #endif
1937 40 : extended_info->samba_gitcommitdate = 0;
1938 : #ifdef SAMBA_VERSION_COMMIT_TIME
1939 : unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1940 : #endif
1941 :
1942 40 : memset(extended_info->samba_version_string, 0,
1943 : sizeof(extended_info->samba_version_string));
1944 :
1945 40 : snprintf (extended_info->samba_version_string,
1946 : sizeof(extended_info->samba_version_string),
1947 : "%s", samba_version_string());
1948 40 : }
1949 :
1950 0 : static bool fsinfo_unix_valid_level(connection_struct *conn,
1951 : uint16_t info_level)
1952 : {
1953 0 : if (conn->sconn->using_smb2 &&
1954 : info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
1955 0 : return true;
1956 : }
1957 : #if defined(SMB1SERVER)
1958 : if (lp_smb1_unix_extensions() &&
1959 : info_level == SMB_QUERY_POSIX_FS_INFO) {
1960 : return true;
1961 : }
1962 : #endif
1963 0 : return false;
1964 : }
1965 :
1966 3424 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1967 : connection_struct *conn,
1968 : TALLOC_CTX *mem_ctx,
1969 : uint16_t info_level,
1970 : uint16_t flags2,
1971 : unsigned int max_data_bytes,
1972 : size_t *fixed_portion,
1973 : struct smb_filename *fname,
1974 : char **ppdata,
1975 : int *ret_data_len)
1976 : {
1977 0 : const struct loadparm_substitution *lp_sub =
1978 3424 : loadparm_s3_global_substitution();
1979 0 : char *pdata, *end_data;
1980 3424 : int data_len = 0;
1981 3424 : size_t len = 0;
1982 3424 : const char *vname = volume_label(talloc_tos(), SNUM(conn));
1983 3424 : int snum = SNUM(conn);
1984 3424 : const char *fstype = lp_fstype(SNUM(conn));
1985 3424 : const char *filename = NULL;
1986 3424 : const uint64_t bytes_per_sector = 512;
1987 3424 : uint32_t additional_flags = 0;
1988 0 : struct smb_filename smb_fname;
1989 0 : SMB_STRUCT_STAT st;
1990 3424 : NTSTATUS status = NT_STATUS_OK;
1991 0 : uint64_t df_ret;
1992 0 : uint32_t serial;
1993 :
1994 3424 : if (fname == NULL || fname->base_name == NULL) {
1995 1373 : filename = ".";
1996 : } else {
1997 2051 : filename = fname->base_name;
1998 : }
1999 :
2000 3424 : if (IS_IPC(conn)) {
2001 240 : if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2002 0 : DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2003 : "info level (0x%x) on IPC$.\n",
2004 : (unsigned int)info_level));
2005 0 : return NT_STATUS_ACCESS_DENIED;
2006 : }
2007 : }
2008 :
2009 3424 : DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2010 :
2011 3424 : smb_fname = (struct smb_filename) {
2012 : .base_name = discard_const_p(char, filename),
2013 3424 : .flags = fname ? fname->flags : 0,
2014 3424 : .twrp = fname ? fname->twrp : 0,
2015 : };
2016 :
2017 3424 : if(info_level != SMB_FS_QUOTA_INFORMATION
2018 3420 : && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2019 0 : DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2020 0 : return map_nt_error_from_unix(errno);
2021 : }
2022 :
2023 3424 : st = smb_fname.st;
2024 :
2025 3424 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2026 0 : return NT_STATUS_INVALID_PARAMETER;
2027 : }
2028 :
2029 3424 : *ppdata = (char *)SMB_REALLOC(
2030 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2031 3424 : if (*ppdata == NULL) {
2032 0 : return NT_STATUS_NO_MEMORY;
2033 : }
2034 :
2035 3424 : pdata = *ppdata;
2036 3424 : memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2037 3424 : end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2038 :
2039 3424 : *fixed_portion = 0;
2040 :
2041 3424 : switch (info_level) {
2042 0 : case SMB_INFO_ALLOCATION:
2043 : {
2044 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2045 0 : data_len = 18;
2046 0 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2047 : &dfree, &dsize);
2048 0 : if (df_ret == (uint64_t)-1) {
2049 0 : return map_nt_error_from_unix(errno);
2050 : }
2051 :
2052 0 : block_size = lp_block_size(snum);
2053 0 : if (bsize < block_size) {
2054 0 : uint64_t factor = block_size/bsize;
2055 0 : bsize = block_size;
2056 0 : dsize /= factor;
2057 0 : dfree /= factor;
2058 : }
2059 0 : if (bsize > block_size) {
2060 0 : uint64_t factor = bsize/block_size;
2061 0 : bsize = block_size;
2062 0 : dsize *= factor;
2063 0 : dfree *= factor;
2064 : }
2065 0 : sectors_per_unit = bsize/bytes_per_sector;
2066 :
2067 0 : DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2068 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2069 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2070 :
2071 : /*
2072 : * For large drives, return max values and not modulo.
2073 : */
2074 0 : dsize = MIN(dsize, UINT32_MAX);
2075 0 : dfree = MIN(dfree, UINT32_MAX);
2076 :
2077 0 : SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2078 0 : SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2079 0 : SIVAL(pdata,l1_cUnit,dsize);
2080 0 : SIVAL(pdata,l1_cUnitAvail,dfree);
2081 0 : SSVAL(pdata,l1_cbSector,bytes_per_sector);
2082 0 : break;
2083 : }
2084 :
2085 0 : case SMB_INFO_VOLUME:
2086 : /* Return volume name */
2087 : /*
2088 : * Add volume serial number - hash of a combination of
2089 : * the called hostname and the service name.
2090 : */
2091 0 : serial = generate_volume_serial_number(lp_sub, snum);
2092 0 : SIVAL(pdata,0,serial);
2093 : /*
2094 : * Win2k3 and previous mess this up by sending a name length
2095 : * one byte short. I believe only older clients (OS/2 Win9x) use
2096 : * this call so try fixing this by adding a terminating null to
2097 : * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2098 : */
2099 0 : status = srvstr_push(
2100 : pdata, flags2,
2101 : pdata+l2_vol_szVolLabel, vname,
2102 : PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2103 : STR_NOALIGN|STR_TERMINATE, &len);
2104 0 : if (!NT_STATUS_IS_OK(status)) {
2105 0 : return status;
2106 : }
2107 0 : SCVAL(pdata,l2_vol_cch,len);
2108 0 : data_len = l2_vol_szVolLabel + len;
2109 0 : DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2110 : "name = %s serial = 0x%04"PRIx32"\n",
2111 : (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2112 : (unsigned)len, vname, serial));
2113 0 : break;
2114 :
2115 548 : case SMB_QUERY_FS_ATTRIBUTE_INFO:
2116 : case SMB_FS_ATTRIBUTE_INFORMATION:
2117 :
2118 548 : additional_flags = 0;
2119 : #if defined(HAVE_SYS_QUOTAS)
2120 548 : additional_flags |= FILE_VOLUME_QUOTAS;
2121 : #endif
2122 :
2123 548 : if(lp_nt_acl_support(SNUM(conn))) {
2124 548 : additional_flags |= FILE_PERSISTENT_ACLS;
2125 : }
2126 :
2127 : /* Capabilities are filled in at connection time through STATVFS call */
2128 548 : additional_flags |= conn->fs_capabilities;
2129 548 : additional_flags |= lp_parm_int(conn->params->service,
2130 : "share", "fake_fscaps",
2131 : 0);
2132 :
2133 548 : SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2134 : FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2135 : additional_flags); /* FS ATTRIBUTES */
2136 :
2137 548 : SIVAL(pdata,4,255); /* Max filename component length */
2138 : /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2139 : and will think we can't do long filenames */
2140 548 : status = srvstr_push(pdata, flags2, pdata+12, fstype,
2141 : PTR_DIFF(end_data, pdata+12),
2142 : STR_UNICODE, &len);
2143 548 : if (!NT_STATUS_IS_OK(status)) {
2144 0 : return status;
2145 : }
2146 548 : SIVAL(pdata,8,len);
2147 548 : data_len = 12 + len;
2148 548 : if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2149 : /* the client only requested a portion of the
2150 : file system name */
2151 16 : data_len = max_data_bytes;
2152 16 : status = STATUS_BUFFER_OVERFLOW;
2153 : }
2154 548 : *fixed_portion = 16;
2155 548 : break;
2156 :
2157 0 : case SMB_QUERY_FS_LABEL_INFO:
2158 : case SMB_FS_LABEL_INFORMATION:
2159 0 : status = srvstr_push(pdata, flags2, pdata+4, vname,
2160 : PTR_DIFF(end_data, pdata+4), 0, &len);
2161 0 : if (!NT_STATUS_IS_OK(status)) {
2162 0 : return status;
2163 : }
2164 0 : data_len = 4 + len;
2165 0 : SIVAL(pdata,0,len);
2166 0 : break;
2167 :
2168 130 : case SMB_QUERY_FS_VOLUME_INFO:
2169 : case SMB_FS_VOLUME_INFORMATION:
2170 130 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2171 : pdata, &st.st_ex_btime);
2172 : /*
2173 : * Add volume serial number - hash of a combination of
2174 : * the called hostname and the service name.
2175 : */
2176 130 : serial = generate_volume_serial_number(lp_sub, snum);
2177 130 : SIVAL(pdata,8,serial);
2178 :
2179 : /* Max label len is 32 characters. */
2180 130 : status = srvstr_push(pdata, flags2, pdata+18, vname,
2181 : PTR_DIFF(end_data, pdata+18),
2182 : STR_UNICODE, &len);
2183 130 : if (!NT_STATUS_IS_OK(status)) {
2184 0 : return status;
2185 : }
2186 130 : SIVAL(pdata,12,len);
2187 130 : data_len = 18+len;
2188 :
2189 130 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2190 : "namelen = %d, vol=%s serv=%s "
2191 : "serial=0x%04"PRIx32"\n",
2192 : (int)strlen(vname),vname,
2193 : lp_servicename(talloc_tos(), lp_sub, snum),
2194 : serial));
2195 130 : if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2196 : /* the client only requested a portion of the
2197 : volume label */
2198 0 : data_len = max_data_bytes;
2199 0 : status = STATUS_BUFFER_OVERFLOW;
2200 : }
2201 130 : *fixed_portion = 24;
2202 130 : break;
2203 :
2204 1214 : case SMB_QUERY_FS_SIZE_INFO:
2205 : case SMB_FS_SIZE_INFORMATION:
2206 : {
2207 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2208 1214 : data_len = 24;
2209 1214 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2210 : &dfree, &dsize);
2211 1214 : if (df_ret == (uint64_t)-1) {
2212 0 : return map_nt_error_from_unix(errno);
2213 : }
2214 1214 : block_size = lp_block_size(snum);
2215 1214 : if (bsize < block_size) {
2216 1168 : uint64_t factor = block_size/bsize;
2217 1168 : bsize = block_size;
2218 1168 : dsize /= factor;
2219 1168 : dfree /= factor;
2220 : }
2221 1214 : if (bsize > block_size) {
2222 42 : uint64_t factor = bsize/block_size;
2223 42 : bsize = block_size;
2224 42 : dsize *= factor;
2225 42 : dfree *= factor;
2226 : }
2227 1214 : sectors_per_unit = bsize/bytes_per_sector;
2228 1214 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2229 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2230 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2231 1214 : SBIG_UINT(pdata,0,dsize);
2232 1214 : SBIG_UINT(pdata,8,dfree);
2233 1214 : SIVAL(pdata,16,sectors_per_unit);
2234 1214 : SIVAL(pdata,20,bytes_per_sector);
2235 1214 : *fixed_portion = 24;
2236 1214 : break;
2237 : }
2238 :
2239 432 : case SMB_FS_FULL_SIZE_INFORMATION:
2240 : {
2241 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2242 432 : data_len = 32;
2243 432 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2244 : &dfree, &dsize);
2245 432 : if (df_ret == (uint64_t)-1) {
2246 0 : return map_nt_error_from_unix(errno);
2247 : }
2248 432 : block_size = lp_block_size(snum);
2249 432 : if (bsize < block_size) {
2250 428 : uint64_t factor = block_size/bsize;
2251 428 : bsize = block_size;
2252 428 : dsize /= factor;
2253 428 : dfree /= factor;
2254 : }
2255 432 : if (bsize > block_size) {
2256 4 : uint64_t factor = bsize/block_size;
2257 4 : bsize = block_size;
2258 4 : dsize *= factor;
2259 4 : dfree *= factor;
2260 : }
2261 432 : sectors_per_unit = bsize/bytes_per_sector;
2262 432 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2263 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2264 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2265 432 : SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2266 432 : SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2267 432 : SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2268 432 : SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2269 432 : SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2270 432 : *fixed_portion = 32;
2271 432 : break;
2272 : }
2273 :
2274 44 : case SMB_QUERY_FS_DEVICE_INFO:
2275 : case SMB_FS_DEVICE_INFORMATION:
2276 : {
2277 44 : uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2278 :
2279 44 : if (!CAN_WRITE(conn)) {
2280 0 : characteristics |= FILE_READ_ONLY_DEVICE;
2281 : }
2282 44 : data_len = 8;
2283 44 : SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2284 44 : SIVAL(pdata,4,characteristics);
2285 44 : *fixed_portion = 8;
2286 44 : break;
2287 : }
2288 :
2289 : #ifdef HAVE_SYS_QUOTAS
2290 4 : case SMB_FS_QUOTA_INFORMATION:
2291 : /*
2292 : * what we have to send --metze:
2293 : *
2294 : * Unknown1: 24 NULL bytes
2295 : * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2296 : * Hard Quota Limit: 8 bytes seems like uint64_t or so
2297 : * Quota Flags: 2 byte :
2298 : * Unknown3: 6 NULL bytes
2299 : *
2300 : * 48 bytes total
2301 : *
2302 : * details for Quota Flags:
2303 : *
2304 : * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2305 : * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2306 : * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2307 : * 0x0001 Enable Quotas: enable quota for this fs
2308 : *
2309 : */
2310 : {
2311 : /* we need to fake up a fsp here,
2312 : * because its not send in this call
2313 : */
2314 0 : files_struct fsp;
2315 0 : SMB_NTQUOTA_STRUCT quotas;
2316 :
2317 4 : ZERO_STRUCT(fsp);
2318 4 : ZERO_STRUCT(quotas);
2319 :
2320 4 : fsp.conn = conn;
2321 4 : fsp.fnum = FNUM_FIELD_INVALID;
2322 :
2323 : /* access check */
2324 4 : if (get_current_uid(conn) != 0) {
2325 4 : DEBUG(0,("get_user_quota: access_denied "
2326 : "service [%s] user [%s]\n",
2327 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2328 : conn->session_info->unix_info->unix_name));
2329 4 : return NT_STATUS_ACCESS_DENIED;
2330 : }
2331 :
2332 0 : status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2333 : NULL, "as);
2334 0 : if (!NT_STATUS_IS_OK(status)) {
2335 0 : DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2336 0 : return status;
2337 : }
2338 :
2339 0 : data_len = 48;
2340 :
2341 0 : DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2342 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2343 :
2344 : /* Unknown1 24 NULL bytes*/
2345 0 : SBIG_UINT(pdata,0,(uint64_t)0);
2346 0 : SBIG_UINT(pdata,8,(uint64_t)0);
2347 0 : SBIG_UINT(pdata,16,(uint64_t)0);
2348 :
2349 : /* Default Soft Quota 8 bytes */
2350 0 : SBIG_UINT(pdata,24,quotas.softlim);
2351 :
2352 : /* Default Hard Quota 8 bytes */
2353 0 : SBIG_UINT(pdata,32,quotas.hardlim);
2354 :
2355 : /* Quota flag 2 bytes */
2356 0 : SSVAL(pdata,40,quotas.qflags);
2357 :
2358 : /* Unknown3 6 NULL bytes */
2359 0 : SSVAL(pdata,42,0);
2360 0 : SIVAL(pdata,44,0);
2361 :
2362 0 : break;
2363 : }
2364 : #endif /* HAVE_SYS_QUOTAS */
2365 40 : case SMB_FS_OBJECTID_INFORMATION:
2366 : {
2367 0 : unsigned char objid[16];
2368 0 : struct smb_extended_info extended_info;
2369 40 : memcpy(pdata,create_volume_objectid(conn, objid),16);
2370 40 : samba_extended_info_version (&extended_info);
2371 40 : SIVAL(pdata,16,extended_info.samba_magic);
2372 40 : SIVAL(pdata,20,extended_info.samba_version);
2373 40 : SIVAL(pdata,24,extended_info.samba_subversion);
2374 40 : SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2375 40 : memcpy(pdata+36,extended_info.samba_version_string,28);
2376 40 : data_len = 64;
2377 40 : break;
2378 : }
2379 :
2380 8 : case SMB_FS_SECTOR_SIZE_INFORMATION:
2381 : {
2382 8 : data_len = 28;
2383 : /*
2384 : * These values match a physical Windows Server 2012
2385 : * share backed by NTFS atop spinning rust.
2386 : */
2387 8 : DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2388 : /* logical_bytes_per_sector */
2389 8 : SIVAL(pdata, 0, bytes_per_sector);
2390 : /* phys_bytes_per_sector_atomic */
2391 8 : SIVAL(pdata, 4, bytes_per_sector);
2392 : /* phys_bytes_per_sector_perf */
2393 8 : SIVAL(pdata, 8, bytes_per_sector);
2394 : /* fs_effective_phys_bytes_per_sector_atomic */
2395 8 : SIVAL(pdata, 12, bytes_per_sector);
2396 : /* flags */
2397 8 : SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2398 : | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2399 : /* byte_off_sector_align */
2400 8 : SIVAL(pdata, 20, 0);
2401 : /* byte_off_partition_align */
2402 8 : SIVAL(pdata, 24, 0);
2403 8 : *fixed_portion = 28;
2404 8 : break;
2405 : }
2406 :
2407 :
2408 : #if defined(WITH_SMB1SERVER)
2409 : /*
2410 : * Query the version and capabilities of the CIFS UNIX extensions
2411 : * in use.
2412 : */
2413 :
2414 962 : case SMB_QUERY_CIFS_UNIX_INFO:
2415 : {
2416 962 : bool large_write = lp_min_receive_file_size() &&
2417 0 : !smb1_srv_is_signing_active(xconn);
2418 962 : bool large_read = !smb1_srv_is_signing_active(xconn);
2419 962 : int encrypt_caps = 0;
2420 :
2421 962 : if (!lp_smb1_unix_extensions()) {
2422 0 : return NT_STATUS_INVALID_LEVEL;
2423 : }
2424 :
2425 962 : switch (conn->encrypt_level) {
2426 0 : case SMB_SIGNING_OFF:
2427 0 : encrypt_caps = 0;
2428 0 : break;
2429 797 : case SMB_SIGNING_DESIRED:
2430 : case SMB_SIGNING_IF_REQUIRED:
2431 : case SMB_SIGNING_DEFAULT:
2432 797 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2433 797 : break;
2434 165 : case SMB_SIGNING_REQUIRED:
2435 165 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2436 : CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2437 165 : large_write = false;
2438 165 : large_read = false;
2439 165 : break;
2440 : }
2441 :
2442 962 : data_len = 12;
2443 962 : SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2444 962 : SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2445 :
2446 : /* We have POSIX ACLs, pathname, encryption,
2447 : * large read/write, and locking capability. */
2448 :
2449 962 : SBIG_UINT(pdata,4,((uint64_t)(
2450 : CIFS_UNIX_POSIX_ACLS_CAP|
2451 : CIFS_UNIX_POSIX_PATHNAMES_CAP|
2452 : CIFS_UNIX_FCNTL_LOCKS_CAP|
2453 : CIFS_UNIX_EXTATTR_CAP|
2454 : CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2455 : encrypt_caps|
2456 : (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2457 : (large_write ?
2458 : CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2459 962 : break;
2460 : }
2461 : #endif
2462 :
2463 0 : case SMB_QUERY_POSIX_FS_INFO:
2464 : case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2465 : {
2466 0 : int rc;
2467 0 : struct vfs_statvfs_struct svfs;
2468 :
2469 0 : if (!fsinfo_unix_valid_level(conn, info_level)) {
2470 0 : return NT_STATUS_INVALID_LEVEL;
2471 : }
2472 :
2473 0 : rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2474 :
2475 0 : if (!rc) {
2476 0 : data_len = 56;
2477 0 : SIVAL(pdata,0,svfs.OptimalTransferSize);
2478 0 : SIVAL(pdata,4,svfs.BlockSize);
2479 0 : SBIG_UINT(pdata,8,svfs.TotalBlocks);
2480 0 : SBIG_UINT(pdata,16,svfs.BlocksAvail);
2481 0 : SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2482 0 : SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2483 0 : SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2484 0 : SBIG_UINT(pdata,48,svfs.FsIdentifier);
2485 0 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2486 : #ifdef EOPNOTSUPP
2487 0 : } else if (rc == EOPNOTSUPP) {
2488 0 : return NT_STATUS_INVALID_LEVEL;
2489 : #endif /* EOPNOTSUPP */
2490 : } else {
2491 0 : DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2492 0 : return NT_STATUS_DOS(ERRSRV, ERRerror);
2493 : }
2494 0 : break;
2495 : }
2496 :
2497 42 : case SMB_QUERY_POSIX_WHOAMI:
2498 : {
2499 42 : uint32_t flags = 0;
2500 0 : uint32_t sid_bytes;
2501 0 : uint32_t i;
2502 :
2503 42 : if (!lp_smb1_unix_extensions()) {
2504 0 : return NT_STATUS_INVALID_LEVEL;
2505 : }
2506 :
2507 42 : if (max_data_bytes < 40) {
2508 0 : return NT_STATUS_BUFFER_TOO_SMALL;
2509 : }
2510 :
2511 42 : if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2512 6 : flags |= SMB_WHOAMI_GUEST;
2513 : }
2514 :
2515 : /* NOTE: 8 bytes for UID/GID, irrespective of native
2516 : * platform size. This matches
2517 : * SMB_QUERY_FILE_UNIX_BASIC and friends.
2518 : */
2519 42 : data_len = 4 /* flags */
2520 : + 4 /* flag mask */
2521 : + 8 /* uid */
2522 : + 8 /* gid */
2523 : + 4 /* ngroups */
2524 : + 4 /* num_sids */
2525 : + 4 /* SID bytes */
2526 : + 4 /* pad/reserved */
2527 42 : + (conn->session_info->unix_token->ngroups * 8)
2528 : /* groups list */
2529 42 : + (conn->session_info->security_token->num_sids *
2530 : SID_MAX_SIZE)
2531 : /* SID list */;
2532 :
2533 42 : SIVAL(pdata, 0, flags);
2534 42 : SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2535 42 : SBIG_UINT(pdata, 8,
2536 : (uint64_t)conn->session_info->unix_token->uid);
2537 42 : SBIG_UINT(pdata, 16,
2538 : (uint64_t)conn->session_info->unix_token->gid);
2539 :
2540 :
2541 42 : if (data_len >= max_data_bytes) {
2542 : /* Potential overflow, skip the GIDs and SIDs. */
2543 :
2544 14 : SIVAL(pdata, 24, 0); /* num_groups */
2545 14 : SIVAL(pdata, 28, 0); /* num_sids */
2546 14 : SIVAL(pdata, 32, 0); /* num_sid_bytes */
2547 14 : SIVAL(pdata, 36, 0); /* reserved */
2548 :
2549 14 : data_len = 40;
2550 14 : break;
2551 : }
2552 :
2553 28 : SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2554 28 : SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2555 :
2556 : /* We walk the SID list twice, but this call is fairly
2557 : * infrequent, and I don't expect that it's performance
2558 : * sensitive -- jpeach
2559 : */
2560 28 : for (i = 0, sid_bytes = 0;
2561 346 : i < conn->session_info->security_token->num_sids; ++i) {
2562 318 : sid_bytes += ndr_size_dom_sid(
2563 318 : &conn->session_info->security_token->sids[i],
2564 : 0);
2565 : }
2566 :
2567 : /* SID list byte count */
2568 28 : SIVAL(pdata, 32, sid_bytes);
2569 :
2570 : /* 4 bytes pad/reserved - must be zero */
2571 28 : SIVAL(pdata, 36, 0);
2572 28 : data_len = 40;
2573 :
2574 : /* GID list */
2575 260 : for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2576 232 : SBIG_UINT(pdata, data_len,
2577 : (uint64_t)conn->session_info->unix_token->groups[i]);
2578 232 : data_len += 8;
2579 : }
2580 :
2581 : /* SID list */
2582 28 : for (i = 0;
2583 346 : i < conn->session_info->security_token->num_sids; ++i) {
2584 636 : int sid_len = ndr_size_dom_sid(
2585 318 : &conn->session_info->security_token->sids[i],
2586 : 0);
2587 :
2588 318 : sid_linearize((uint8_t *)(pdata + data_len),
2589 : sid_len,
2590 318 : &conn->session_info->security_token->sids[i]);
2591 318 : data_len += sid_len;
2592 : }
2593 :
2594 28 : break;
2595 : }
2596 :
2597 0 : case SMB_MAC_QUERY_FS_INFO:
2598 : /*
2599 : * Thursby MAC extension... ONLY on NTFS filesystems
2600 : * once we do streams then we don't need this
2601 : */
2602 0 : if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2603 0 : data_len = 88;
2604 0 : SIVAL(pdata,84,0x100); /* Don't support mac... */
2605 0 : break;
2606 : }
2607 :
2608 0 : FALL_THROUGH;
2609 : default:
2610 0 : return NT_STATUS_INVALID_LEVEL;
2611 : }
2612 :
2613 3420 : *ret_data_len = data_len;
2614 3420 : return status;
2615 : }
2616 :
2617 0 : NTSTATUS smb_set_fsquota(connection_struct *conn,
2618 : struct smb_request *req,
2619 : files_struct *fsp,
2620 : const DATA_BLOB *qdata)
2621 : {
2622 0 : const struct loadparm_substitution *lp_sub =
2623 0 : loadparm_s3_global_substitution();
2624 0 : NTSTATUS status;
2625 0 : SMB_NTQUOTA_STRUCT quotas;
2626 :
2627 0 : ZERO_STRUCT(quotas);
2628 :
2629 : /* access check */
2630 0 : if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2631 0 : DBG_NOTICE("access_denied service [%s] user [%s]\n",
2632 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2633 : conn->session_info->unix_info->unix_name);
2634 0 : return NT_STATUS_ACCESS_DENIED;
2635 : }
2636 :
2637 0 : if (!check_fsp_ntquota_handle(conn, req,
2638 : fsp)) {
2639 0 : DBG_WARNING("no valid QUOTA HANDLE\n");
2640 0 : return NT_STATUS_INVALID_HANDLE;
2641 : }
2642 :
2643 : /* note: normally there're 48 bytes,
2644 : * but we didn't use the last 6 bytes for now
2645 : * --metze
2646 : */
2647 0 : if (qdata->length < 42) {
2648 0 : DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2649 : qdata->length);
2650 0 : return NT_STATUS_INVALID_PARAMETER;
2651 : }
2652 :
2653 : /* unknown_1 24 NULL bytes in pdata*/
2654 :
2655 : /* the soft quotas 8 bytes (uint64_t)*/
2656 0 : quotas.softlim = BVAL(qdata->data,24);
2657 :
2658 : /* the hard quotas 8 bytes (uint64_t)*/
2659 0 : quotas.hardlim = BVAL(qdata->data,32);
2660 :
2661 : /* quota_flags 2 bytes **/
2662 0 : quotas.qflags = SVAL(qdata->data,40);
2663 :
2664 : /* unknown_2 6 NULL bytes follow*/
2665 :
2666 : /* now set the quotas */
2667 0 : if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2668 0 : DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2669 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2670 0 : status = map_nt_error_from_unix(errno);
2671 : } else {
2672 0 : status = NT_STATUS_OK;
2673 : }
2674 0 : return status;
2675 : }
2676 :
2677 0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2678 : struct smb_request *req,
2679 : TALLOC_CTX *mem_ctx,
2680 : uint16_t info_level,
2681 : files_struct *fsp,
2682 : const DATA_BLOB *pdata)
2683 : {
2684 0 : switch (info_level) {
2685 0 : case SMB_FS_QUOTA_INFORMATION:
2686 : {
2687 0 : return smb_set_fsquota(conn,
2688 : req,
2689 : fsp,
2690 : pdata);
2691 : }
2692 :
2693 0 : default:
2694 0 : break;
2695 : }
2696 0 : return NT_STATUS_INVALID_LEVEL;
2697 : }
2698 :
2699 : /****************************************************************************
2700 : Store the FILE_UNIX_BASIC info.
2701 : ****************************************************************************/
2702 :
2703 144 : char *store_file_unix_basic(connection_struct *conn,
2704 : char *pdata,
2705 : files_struct *fsp,
2706 : const SMB_STRUCT_STAT *psbuf)
2707 : {
2708 0 : dev_t devno;
2709 :
2710 144 : DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2711 144 : DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2712 :
2713 144 : SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2714 144 : pdata += 8;
2715 :
2716 144 : SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2717 144 : pdata += 8;
2718 :
2719 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2720 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2721 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2722 144 : pdata += 24;
2723 :
2724 144 : SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2725 144 : SIVAL(pdata,4,0);
2726 144 : pdata += 8;
2727 :
2728 144 : SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2729 144 : SIVAL(pdata,4,0);
2730 144 : pdata += 8;
2731 :
2732 144 : SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2733 144 : pdata += 4;
2734 :
2735 144 : if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2736 0 : devno = psbuf->st_ex_rdev;
2737 : } else {
2738 144 : devno = psbuf->st_ex_dev;
2739 : }
2740 :
2741 144 : SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2742 144 : SIVAL(pdata,4,0);
2743 144 : pdata += 8;
2744 :
2745 144 : SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2746 144 : SIVAL(pdata,4,0);
2747 144 : pdata += 8;
2748 :
2749 144 : SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2750 144 : pdata += 8;
2751 :
2752 144 : SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2753 144 : SIVAL(pdata,4,0);
2754 144 : pdata += 8;
2755 :
2756 144 : SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2757 144 : SIVAL(pdata,4,0);
2758 144 : pdata += 8;
2759 :
2760 144 : return pdata;
2761 : }
2762 :
2763 : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2764 : * the chflags(2) (or equivalent) flags.
2765 : *
2766 : * XXX: this really should be behind the VFS interface. To do this, we would
2767 : * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2768 : * Each VFS module could then implement its own mapping as appropriate for the
2769 : * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2770 : */
2771 : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2772 : info2_flags_map[] =
2773 : {
2774 : #ifdef UF_NODUMP
2775 : { UF_NODUMP, EXT_DO_NOT_BACKUP },
2776 : #endif
2777 :
2778 : #ifdef UF_IMMUTABLE
2779 : { UF_IMMUTABLE, EXT_IMMUTABLE },
2780 : #endif
2781 :
2782 : #ifdef UF_APPEND
2783 : { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2784 : #endif
2785 :
2786 : #ifdef UF_HIDDEN
2787 : { UF_HIDDEN, EXT_HIDDEN },
2788 : #endif
2789 :
2790 : /* Do not remove. We need to guarantee that this array has at least one
2791 : * entry to build on HP-UX.
2792 : */
2793 : { 0, 0 }
2794 :
2795 : };
2796 :
2797 24 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2798 : uint32_t *smb_fflags, uint32_t *smb_fmask)
2799 : {
2800 : size_t i;
2801 :
2802 48 : for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2803 24 : *smb_fmask |= info2_flags_map[i].smb_fflag;
2804 24 : if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2805 0 : *smb_fflags |= info2_flags_map[i].smb_fflag;
2806 : }
2807 : }
2808 24 : }
2809 :
2810 128 : bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2811 : const uint32_t smb_fflags,
2812 : const uint32_t smb_fmask,
2813 : int *stat_fflags)
2814 : {
2815 128 : uint32_t max_fmask = 0;
2816 0 : size_t i;
2817 :
2818 128 : *stat_fflags = psbuf->st_ex_flags;
2819 :
2820 : /* For each flags requested in smb_fmask, check the state of the
2821 : * corresponding flag in smb_fflags and set or clear the matching
2822 : * stat flag.
2823 : */
2824 :
2825 256 : for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2826 128 : max_fmask |= info2_flags_map[i].smb_fflag;
2827 128 : if (smb_fmask & info2_flags_map[i].smb_fflag) {
2828 0 : if (smb_fflags & info2_flags_map[i].smb_fflag) {
2829 0 : *stat_fflags |= info2_flags_map[i].stat_fflag;
2830 : } else {
2831 0 : *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2832 : }
2833 : }
2834 : }
2835 :
2836 : /* If smb_fmask is asking to set any bits that are not supported by
2837 : * our flag mappings, we should fail.
2838 : */
2839 128 : if ((smb_fmask & max_fmask) != smb_fmask) {
2840 128 : return False;
2841 : }
2842 :
2843 0 : return True;
2844 : }
2845 :
2846 :
2847 : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2848 : * of file flags and birth (create) time.
2849 : */
2850 24 : char *store_file_unix_basic_info2(connection_struct *conn,
2851 : char *pdata,
2852 : files_struct *fsp,
2853 : const SMB_STRUCT_STAT *psbuf)
2854 : {
2855 24 : uint32_t file_flags = 0;
2856 24 : uint32_t flags_mask = 0;
2857 :
2858 24 : pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2859 :
2860 : /* Create (birth) time 64 bit */
2861 24 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2862 24 : pdata += 8;
2863 :
2864 24 : map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2865 24 : SIVAL(pdata, 0, file_flags); /* flags */
2866 24 : SIVAL(pdata, 4, flags_mask); /* mask */
2867 24 : pdata += 8;
2868 :
2869 24 : return pdata;
2870 : }
2871 :
2872 3598 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
2873 : const struct stream_struct *streams,
2874 : char *data,
2875 : unsigned int max_data_bytes,
2876 : unsigned int *data_size)
2877 : {
2878 0 : unsigned int i;
2879 3598 : unsigned int ofs = 0;
2880 :
2881 3598 : if (max_data_bytes < 32) {
2882 128 : return NT_STATUS_INFO_LENGTH_MISMATCH;
2883 : }
2884 :
2885 7478 : for (i = 0; i < num_streams; i++) {
2886 0 : unsigned int next_offset;
2887 0 : size_t namelen;
2888 0 : smb_ucs2_t *namebuf;
2889 :
2890 4032 : if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2891 4032 : streams[i].name, &namelen) ||
2892 4032 : namelen <= 2)
2893 : {
2894 0 : return NT_STATUS_INVALID_PARAMETER;
2895 : }
2896 :
2897 : /*
2898 : * name_buf is now null-terminated, we need to marshall as not
2899 : * terminated
2900 : */
2901 :
2902 4032 : namelen -= 2;
2903 :
2904 : /*
2905 : * We cannot overflow ...
2906 : */
2907 4032 : if ((ofs + 24 + namelen) > max_data_bytes) {
2908 24 : DEBUG(10, ("refusing to overflow reply at stream %u\n",
2909 : i));
2910 24 : TALLOC_FREE(namebuf);
2911 24 : return STATUS_BUFFER_OVERFLOW;
2912 : }
2913 :
2914 4008 : SIVAL(data, ofs+4, namelen);
2915 4008 : SOFF_T(data, ofs+8, streams[i].size);
2916 4008 : SOFF_T(data, ofs+16, streams[i].alloc_size);
2917 4008 : memcpy(data+ofs+24, namebuf, namelen);
2918 4008 : TALLOC_FREE(namebuf);
2919 :
2920 4008 : next_offset = ofs + 24 + namelen;
2921 :
2922 4008 : if (i == num_streams-1) {
2923 3210 : SIVAL(data, ofs, 0);
2924 : }
2925 : else {
2926 798 : unsigned int align = ndr_align_size(next_offset, 8);
2927 :
2928 798 : if ((next_offset + align) > max_data_bytes) {
2929 0 : DEBUG(10, ("refusing to overflow align "
2930 : "reply at stream %u\n",
2931 : i));
2932 0 : TALLOC_FREE(namebuf);
2933 0 : return STATUS_BUFFER_OVERFLOW;
2934 : }
2935 :
2936 798 : memset(data+next_offset, 0, align);
2937 798 : next_offset += align;
2938 :
2939 798 : SIVAL(data, ofs, next_offset - ofs);
2940 798 : ofs = next_offset;
2941 : }
2942 :
2943 4008 : ofs = next_offset;
2944 : }
2945 :
2946 3446 : DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2947 :
2948 3446 : *data_size = ofs;
2949 :
2950 3446 : return NT_STATUS_OK;
2951 : }
2952 :
2953 24435 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2954 : TALLOC_CTX *mem_ctx,
2955 : struct smb_request *req,
2956 : uint16_t info_level,
2957 : files_struct *fsp,
2958 : struct smb_filename *smb_fname,
2959 : bool delete_pending,
2960 : struct timespec write_time_ts,
2961 : struct ea_list *ea_list,
2962 : uint16_t flags2,
2963 : unsigned int max_data_bytes,
2964 : size_t *fixed_portion,
2965 : char **ppdata,
2966 : unsigned int *pdata_size)
2967 : {
2968 24435 : char *pdata = *ppdata;
2969 743 : char *dstart, *dend;
2970 743 : unsigned int data_size;
2971 743 : struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2972 743 : time_t create_time, mtime, atime, c_time;
2973 24435 : SMB_STRUCT_STAT *psbuf = NULL;
2974 24435 : SMB_STRUCT_STAT *base_sp = NULL;
2975 743 : char *p;
2976 743 : char *base_name;
2977 743 : char *dos_fname;
2978 743 : int mode;
2979 743 : int nlink;
2980 743 : NTSTATUS status;
2981 24435 : uint64_t file_size = 0;
2982 24435 : uint64_t pos = 0;
2983 24435 : uint64_t allocation_size = 0;
2984 24435 : uint64_t file_id = 0;
2985 24435 : uint32_t access_mask = 0;
2986 24435 : size_t len = 0;
2987 :
2988 24435 : if (INFO_LEVEL_IS_UNIX(info_level)) {
2989 8 : bool ok = false;
2990 :
2991 8 : if (lp_smb1_unix_extensions() && req->posix_pathnames) {
2992 8 : DBG_DEBUG("SMB1 unix extensions activated\n");
2993 8 : ok = true;
2994 : }
2995 :
2996 8 : if ((fsp != NULL) &&
2997 8 : (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
2998 0 : DBG_DEBUG("SMB2 posix open\n");
2999 0 : ok = true;
3000 : }
3001 :
3002 8 : if (!ok) {
3003 0 : return NT_STATUS_INVALID_LEVEL;
3004 : }
3005 : }
3006 :
3007 24435 : DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3008 : smb_fname_str_dbg(smb_fname),
3009 : fsp_fnum_dbg(fsp),
3010 : info_level, max_data_bytes));
3011 :
3012 : /*
3013 : * In case of querying a symlink in POSIX context,
3014 : * fsp will be NULL. fdos_mode() deals with it.
3015 : */
3016 24435 : if (fsp != NULL) {
3017 24435 : smb_fname = fsp->fsp_name;
3018 : }
3019 24435 : mode = fdos_mode(fsp);
3020 24435 : psbuf = &smb_fname->st;
3021 :
3022 24435 : if (fsp != NULL) {
3023 24435 : base_sp = fsp->base_fsp ?
3024 24435 : &fsp->base_fsp->fsp_name->st :
3025 23867 : &fsp->fsp_name->st;
3026 : } else {
3027 0 : base_sp = &smb_fname->st;
3028 : }
3029 :
3030 24435 : nlink = psbuf->st_ex_nlink;
3031 :
3032 24435 : if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3033 2724 : nlink = 1;
3034 : }
3035 :
3036 24435 : if ((nlink > 0) && delete_pending) {
3037 233 : nlink -= 1;
3038 : }
3039 :
3040 24435 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3041 0 : return NT_STATUS_INVALID_PARAMETER;
3042 : }
3043 :
3044 24435 : data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3045 24435 : *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3046 24435 : if (*ppdata == NULL) {
3047 0 : return NT_STATUS_NO_MEMORY;
3048 : }
3049 24435 : pdata = *ppdata;
3050 24435 : dstart = pdata;
3051 24435 : dend = dstart + data_size - 1;
3052 :
3053 24435 : if (!is_omit_timespec(&write_time_ts) &&
3054 16858 : !INFO_LEVEL_IS_UNIX(info_level))
3055 : {
3056 16858 : update_stat_ex_mtime(psbuf, write_time_ts);
3057 : }
3058 :
3059 24435 : create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3060 24435 : mtime_ts = psbuf->st_ex_mtime;
3061 24435 : atime_ts = psbuf->st_ex_atime;
3062 24435 : ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3063 :
3064 24435 : if (lp_dos_filetime_resolution(SNUM(conn))) {
3065 0 : dos_filetime_timespec(&create_time_ts);
3066 0 : dos_filetime_timespec(&mtime_ts);
3067 0 : dos_filetime_timespec(&atime_ts);
3068 0 : dos_filetime_timespec(&ctime_ts);
3069 : }
3070 :
3071 24435 : create_time = convert_timespec_to_time_t(create_time_ts);
3072 24435 : mtime = convert_timespec_to_time_t(mtime_ts);
3073 24435 : atime = convert_timespec_to_time_t(atime_ts);
3074 24435 : c_time = convert_timespec_to_time_t(ctime_ts);
3075 :
3076 24435 : p = strrchr_m(smb_fname->base_name,'/');
3077 24435 : if (!p)
3078 12748 : base_name = smb_fname->base_name;
3079 : else
3080 11687 : base_name = p+1;
3081 :
3082 : /* NT expects the name to be in an exact form of the *full*
3083 : filename. See the trans2 torture test */
3084 24435 : if (ISDOT(base_name)) {
3085 390 : dos_fname = talloc_strdup(mem_ctx, "\\");
3086 390 : if (!dos_fname) {
3087 0 : return NT_STATUS_NO_MEMORY;
3088 : }
3089 : } else {
3090 24045 : dos_fname = talloc_asprintf(mem_ctx,
3091 : "\\%s",
3092 : smb_fname->base_name);
3093 24045 : if (!dos_fname) {
3094 0 : return NT_STATUS_NO_MEMORY;
3095 : }
3096 24045 : if (is_named_stream(smb_fname)) {
3097 568 : dos_fname = talloc_asprintf(dos_fname, "%s",
3098 : smb_fname->stream_name);
3099 568 : if (!dos_fname) {
3100 0 : return NT_STATUS_NO_MEMORY;
3101 : }
3102 : }
3103 :
3104 24045 : string_replace(dos_fname, '/', '\\');
3105 : }
3106 :
3107 24435 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3108 :
3109 24435 : if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3110 : /* Do we have this path open ? */
3111 7712 : struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3112 7712 : files_struct *fsp1 = file_find_di_first(
3113 : conn->sconn, fileid, true);
3114 7712 : if (fsp1 && fsp1->initial_allocation_size) {
3115 105 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3116 : }
3117 : }
3118 :
3119 24435 : if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3120 21711 : file_size = get_file_size_stat(psbuf);
3121 : }
3122 :
3123 24435 : if (fsp) {
3124 24435 : pos = fh_get_position_information(fsp->fh);
3125 : }
3126 :
3127 24435 : if (fsp) {
3128 24435 : access_mask = fsp->access_mask;
3129 : } else {
3130 : /* GENERIC_EXECUTE mapping from Windows */
3131 0 : access_mask = 0x12019F;
3132 : }
3133 :
3134 : /* This should be an index number - looks like
3135 : dev/ino to me :-)
3136 :
3137 : I think this causes us to fail the IFSKIT
3138 : BasicFileInformationTest. -tpot */
3139 24435 : file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3140 :
3141 24435 : *fixed_portion = 0;
3142 :
3143 24435 : switch (info_level) {
3144 411 : case SMB_INFO_STANDARD:
3145 411 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3146 411 : data_size = 22;
3147 411 : srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3148 411 : srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3149 411 : srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3150 411 : SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3151 411 : SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3152 411 : SSVAL(pdata,l1_attrFile,mode);
3153 411 : break;
3154 :
3155 8 : case SMB_INFO_QUERY_EA_SIZE:
3156 : {
3157 0 : unsigned int ea_size =
3158 8 : estimate_ea_size(smb_fname->fsp);
3159 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3160 8 : data_size = 26;
3161 8 : srv_put_dos_date2(pdata,0,create_time);
3162 8 : srv_put_dos_date2(pdata,4,atime);
3163 8 : srv_put_dos_date2(pdata,8,mtime); /* write time */
3164 8 : SIVAL(pdata,12,(uint32_t)file_size);
3165 8 : SIVAL(pdata,16,(uint32_t)allocation_size);
3166 8 : SSVAL(pdata,20,mode);
3167 8 : SIVAL(pdata,22,ea_size);
3168 8 : break;
3169 : }
3170 :
3171 8 : case SMB_INFO_IS_NAME_VALID:
3172 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3173 8 : if (fsp) {
3174 : /* os/2 needs this ? really ?*/
3175 8 : return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3176 : }
3177 : /* This is only reached for qpathinfo */
3178 0 : data_size = 0;
3179 0 : break;
3180 :
3181 152 : case SMB_INFO_QUERY_EAS_FROM_LIST:
3182 : {
3183 152 : size_t total_ea_len = 0;
3184 152 : struct ea_list *ea_file_list = NULL;
3185 152 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3186 :
3187 28 : status =
3188 180 : get_ea_list_from_fsp(mem_ctx,
3189 152 : smb_fname->fsp,
3190 : &total_ea_len, &ea_file_list);
3191 152 : if (!NT_STATUS_IS_OK(status)) {
3192 4 : return status;
3193 : }
3194 :
3195 148 : ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3196 :
3197 148 : if (!ea_list || (total_ea_len > data_size)) {
3198 0 : data_size = 4;
3199 0 : SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3200 148 : break;
3201 : }
3202 :
3203 148 : data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3204 148 : break;
3205 : }
3206 :
3207 20 : case SMB_INFO_QUERY_ALL_EAS:
3208 : {
3209 : /* We have data_size bytes to put EA's into. */
3210 20 : size_t total_ea_len = 0;
3211 20 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3212 :
3213 20 : status = get_ea_list_from_fsp(mem_ctx,
3214 20 : smb_fname->fsp,
3215 : &total_ea_len, &ea_list);
3216 20 : if (!NT_STATUS_IS_OK(status)) {
3217 4 : return status;
3218 : }
3219 :
3220 16 : if (!ea_list || (total_ea_len > data_size)) {
3221 12 : data_size = 4;
3222 12 : SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3223 16 : break;
3224 : }
3225 :
3226 4 : data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3227 4 : break;
3228 : }
3229 :
3230 22 : case SMB2_FILE_FULL_EA_INFORMATION:
3231 : {
3232 : /* We have data_size bytes to put EA's into. */
3233 22 : size_t total_ea_len = 0;
3234 22 : struct ea_list *ea_file_list = NULL;
3235 :
3236 22 : DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3237 :
3238 : /*TODO: add filtering and index handling */
3239 :
3240 0 : status =
3241 22 : get_ea_list_from_fsp(mem_ctx,
3242 22 : smb_fname->fsp,
3243 : &total_ea_len, &ea_file_list);
3244 22 : if (!NT_STATUS_IS_OK(status)) {
3245 12 : return status;
3246 : }
3247 22 : if (!ea_file_list) {
3248 12 : return NT_STATUS_NO_EAS_ON_FILE;
3249 : }
3250 :
3251 10 : status = fill_ea_chained_buffer(mem_ctx,
3252 : pdata,
3253 : data_size,
3254 : &data_size,
3255 : conn, ea_file_list);
3256 10 : if (!NT_STATUS_IS_OK(status)) {
3257 0 : return status;
3258 : }
3259 10 : break;
3260 : }
3261 :
3262 4287 : case SMB_FILE_BASIC_INFORMATION:
3263 : case SMB_QUERY_FILE_BASIC_INFO:
3264 :
3265 4287 : if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3266 3731 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3267 3731 : data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3268 : } else {
3269 556 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3270 556 : data_size = 40;
3271 556 : SIVAL(pdata,36,0);
3272 : }
3273 4287 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3274 4287 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3275 4287 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3276 4287 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3277 4287 : SIVAL(pdata,32,mode);
3278 :
3279 4287 : DEBUG(5,("SMB_QFBI - "));
3280 4287 : DEBUG(5,("create: %s ", ctime(&create_time)));
3281 4287 : DEBUG(5,("access: %s ", ctime(&atime)));
3282 4287 : DEBUG(5,("write: %s ", ctime(&mtime)));
3283 4287 : DEBUG(5,("change: %s ", ctime(&c_time)));
3284 4287 : DEBUG(5,("mode: %x\n", mode));
3285 4287 : *fixed_portion = data_size;
3286 4287 : break;
3287 :
3288 2659 : case SMB_FILE_STANDARD_INFORMATION:
3289 : case SMB_QUERY_FILE_STANDARD_INFO:
3290 :
3291 2659 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3292 2659 : data_size = 24;
3293 2659 : SOFF_T(pdata,0,allocation_size);
3294 2659 : SOFF_T(pdata,8,file_size);
3295 2659 : SIVAL(pdata,16,nlink);
3296 2659 : SCVAL(pdata,20,delete_pending?1:0);
3297 2659 : SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3298 2659 : SSVAL(pdata,22,0); /* Padding. */
3299 2659 : *fixed_portion = 24;
3300 2659 : break;
3301 :
3302 40 : case SMB_FILE_EA_INFORMATION:
3303 : case SMB_QUERY_FILE_EA_INFO:
3304 : {
3305 0 : unsigned int ea_size =
3306 40 : estimate_ea_size(smb_fname->fsp);
3307 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3308 40 : data_size = 4;
3309 40 : *fixed_portion = 4;
3310 40 : SIVAL(pdata,0,ea_size);
3311 40 : break;
3312 : }
3313 :
3314 : /* Get the 8.3 name - used if NT SMB was negotiated. */
3315 1730 : case SMB_QUERY_FILE_ALT_NAME_INFO:
3316 : case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3317 : {
3318 0 : char mangled_name[13];
3319 1730 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3320 1730 : if (!name_to_8_3(base_name,mangled_name,
3321 1730 : True,conn->params)) {
3322 0 : return NT_STATUS_NO_MEMORY;
3323 : }
3324 1730 : status = srvstr_push(dstart, flags2,
3325 : pdata+4, mangled_name,
3326 : PTR_DIFF(dend, pdata+4),
3327 : STR_UNICODE, &len);
3328 1730 : if (!NT_STATUS_IS_OK(status)) {
3329 0 : return status;
3330 : }
3331 1730 : data_size = 4 + len;
3332 1730 : SIVAL(pdata,0,len);
3333 1730 : *fixed_portion = 8;
3334 1730 : break;
3335 : }
3336 :
3337 79 : case SMB_QUERY_FILE_NAME_INFO:
3338 : {
3339 : /*
3340 : this must be *exactly* right for ACLs on mapped drives to work
3341 : */
3342 79 : status = srvstr_push(dstart, flags2,
3343 : pdata+4, dos_fname,
3344 : PTR_DIFF(dend, pdata+4),
3345 : STR_UNICODE, &len);
3346 79 : if (!NT_STATUS_IS_OK(status)) {
3347 0 : return status;
3348 : }
3349 79 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3350 79 : data_size = 4 + len;
3351 79 : SIVAL(pdata,0,len);
3352 79 : break;
3353 : }
3354 :
3355 104 : case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3356 : {
3357 104 : char *nfname = NULL;
3358 :
3359 104 : if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3360 8 : return NT_STATUS_INVALID_LEVEL;
3361 : }
3362 :
3363 96 : nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3364 96 : if (nfname == NULL) {
3365 0 : return NT_STATUS_NO_MEMORY;
3366 : }
3367 :
3368 96 : if (ISDOT(nfname)) {
3369 4 : nfname[0] = '\0';
3370 : }
3371 96 : string_replace(nfname, '/', '\\');
3372 :
3373 96 : if (fsp_is_alternate_stream(fsp)) {
3374 32 : const char *s = smb_fname->stream_name;
3375 32 : const char *e = NULL;
3376 0 : size_t n;
3377 :
3378 32 : SMB_ASSERT(s[0] != '\0');
3379 :
3380 : /*
3381 : * smb_fname->stream_name is in form
3382 : * of ':StrEam:$DATA', but we should only
3383 : * append ':StrEam' here.
3384 : */
3385 :
3386 32 : e = strchr(&s[1], ':');
3387 32 : if (e == NULL) {
3388 8 : n = strlen(s);
3389 : } else {
3390 24 : n = PTR_DIFF(e, s);
3391 : }
3392 32 : nfname = talloc_strndup_append(nfname, s, n);
3393 32 : if (nfname == NULL) {
3394 0 : return NT_STATUS_NO_MEMORY;
3395 : }
3396 : }
3397 :
3398 96 : status = srvstr_push(dstart, flags2,
3399 : pdata+4, nfname,
3400 : PTR_DIFF(dend, pdata+4),
3401 : STR_UNICODE, &len);
3402 96 : if (!NT_STATUS_IS_OK(status)) {
3403 0 : return status;
3404 : }
3405 96 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3406 96 : data_size = 4 + len;
3407 96 : SIVAL(pdata,0,len);
3408 96 : *fixed_portion = 8;
3409 96 : break;
3410 : }
3411 :
3412 8 : case SMB_FILE_ALLOCATION_INFORMATION:
3413 : case SMB_QUERY_FILE_ALLOCATION_INFO:
3414 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3415 8 : data_size = 8;
3416 8 : SOFF_T(pdata,0,allocation_size);
3417 8 : break;
3418 :
3419 8 : case SMB_FILE_END_OF_FILE_INFORMATION:
3420 : case SMB_QUERY_FILE_END_OF_FILEINFO:
3421 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3422 8 : data_size = 8;
3423 8 : SOFF_T(pdata,0,file_size);
3424 8 : break;
3425 :
3426 1922 : case SMB_QUERY_FILE_ALL_INFO:
3427 : case SMB_FILE_ALL_INFORMATION:
3428 : {
3429 252 : unsigned int ea_size =
3430 1922 : estimate_ea_size(smb_fname->fsp);
3431 1922 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3432 1922 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3433 1922 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3434 1922 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3435 1922 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3436 1922 : SIVAL(pdata,32,mode);
3437 1922 : SIVAL(pdata,36,0); /* padding. */
3438 1922 : pdata += 40;
3439 1922 : SOFF_T(pdata,0,allocation_size);
3440 1922 : SOFF_T(pdata,8,file_size);
3441 1922 : SIVAL(pdata,16,nlink);
3442 1922 : SCVAL(pdata,20,delete_pending);
3443 1922 : SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3444 1922 : SSVAL(pdata,22,0);
3445 1922 : pdata += 24;
3446 1922 : SIVAL(pdata,0,ea_size);
3447 1922 : pdata += 4; /* EA info */
3448 1922 : status = srvstr_push(dstart, flags2,
3449 : pdata+4, dos_fname,
3450 : PTR_DIFF(dend, pdata+4),
3451 : STR_UNICODE, &len);
3452 1922 : if (!NT_STATUS_IS_OK(status)) {
3453 0 : return status;
3454 : }
3455 1922 : SIVAL(pdata,0,len);
3456 1922 : pdata += 4 + len;
3457 1922 : data_size = PTR_DIFF(pdata,(*ppdata));
3458 1922 : *fixed_portion = 10;
3459 1922 : break;
3460 : }
3461 :
3462 5590 : case SMB2_FILE_ALL_INFORMATION:
3463 : {
3464 0 : unsigned int ea_size =
3465 5590 : estimate_ea_size(smb_fname->fsp);
3466 5590 : DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3467 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3468 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3469 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3470 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3471 5590 : SIVAL(pdata, 0x20, mode);
3472 5590 : SIVAL(pdata, 0x24, 0); /* padding. */
3473 5590 : SBVAL(pdata, 0x28, allocation_size);
3474 5590 : SBVAL(pdata, 0x30, file_size);
3475 5590 : SIVAL(pdata, 0x38, nlink);
3476 5590 : SCVAL(pdata, 0x3C, delete_pending);
3477 5590 : SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3478 5590 : SSVAL(pdata, 0x3E, 0); /* padding */
3479 5590 : SBVAL(pdata, 0x40, file_id);
3480 5590 : SIVAL(pdata, 0x48, ea_size);
3481 5590 : SIVAL(pdata, 0x4C, access_mask);
3482 5590 : SBVAL(pdata, 0x50, pos);
3483 5590 : SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3484 5590 : SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3485 :
3486 5590 : pdata += 0x60;
3487 :
3488 5590 : status = srvstr_push(dstart, flags2,
3489 : pdata+4, dos_fname,
3490 : PTR_DIFF(dend, pdata+4),
3491 : STR_UNICODE, &len);
3492 5590 : if (!NT_STATUS_IS_OK(status)) {
3493 0 : return status;
3494 : }
3495 5590 : SIVAL(pdata,0,len);
3496 5590 : pdata += 4 + len;
3497 5590 : data_size = PTR_DIFF(pdata,(*ppdata));
3498 5590 : *fixed_portion = 104;
3499 5590 : break;
3500 : }
3501 62 : case SMB_FILE_INTERNAL_INFORMATION:
3502 :
3503 62 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3504 62 : SBVAL(pdata, 0, file_id);
3505 62 : data_size = 8;
3506 62 : *fixed_portion = 8;
3507 62 : break;
3508 :
3509 1072 : case SMB_FILE_ACCESS_INFORMATION:
3510 1072 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3511 1072 : SIVAL(pdata, 0, access_mask);
3512 1072 : data_size = 4;
3513 1072 : *fixed_portion = 4;
3514 1072 : break;
3515 :
3516 8 : case SMB_FILE_NAME_INFORMATION:
3517 : /* Pathname with leading '\'. */
3518 : {
3519 0 : size_t byte_len;
3520 8 : byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3521 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3522 8 : SIVAL(pdata,0,byte_len);
3523 8 : data_size = 4 + byte_len;
3524 8 : break;
3525 : }
3526 :
3527 8 : case SMB_FILE_DISPOSITION_INFORMATION:
3528 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3529 8 : data_size = 1;
3530 8 : SCVAL(pdata,0,delete_pending);
3531 8 : *fixed_portion = 1;
3532 8 : break;
3533 :
3534 2103 : case SMB_FILE_POSITION_INFORMATION:
3535 2103 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3536 2103 : data_size = 8;
3537 2103 : SOFF_T(pdata,0,pos);
3538 2103 : *fixed_portion = 8;
3539 2103 : break;
3540 :
3541 40 : case SMB_FILE_MODE_INFORMATION:
3542 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3543 40 : SIVAL(pdata,0,mode);
3544 40 : data_size = 4;
3545 40 : *fixed_portion = 4;
3546 40 : break;
3547 :
3548 40 : case SMB_FILE_ALIGNMENT_INFORMATION:
3549 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3550 40 : SIVAL(pdata,0,0); /* No alignment needed. */
3551 40 : data_size = 4;
3552 40 : *fixed_portion = 4;
3553 40 : break;
3554 :
3555 : /*
3556 : * NT4 server just returns "invalid query" to this - if we try
3557 : * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3558 : * want this. JRA.
3559 : */
3560 : /* The first statement above is false - verified using Thursby
3561 : * client against NT4 -- gcolley.
3562 : */
3563 3662 : case SMB_QUERY_FILE_STREAM_INFO:
3564 : case SMB_FILE_STREAM_INFORMATION: {
3565 3662 : unsigned int num_streams = 0;
3566 3662 : struct stream_struct *streams = NULL;
3567 :
3568 3662 : DEBUG(10,("smbd_do_qfilepathinfo: "
3569 : "SMB_FILE_STREAM_INFORMATION\n"));
3570 :
3571 3662 : if (is_ntfs_stream_smb_fname(smb_fname)) {
3572 64 : return NT_STATUS_INVALID_PARAMETER;
3573 : }
3574 :
3575 3598 : status = vfs_fstreaminfo(fsp,
3576 : mem_ctx,
3577 : &num_streams,
3578 : &streams);
3579 :
3580 3598 : if (!NT_STATUS_IS_OK(status)) {
3581 0 : DEBUG(10, ("could not get stream info: %s\n",
3582 : nt_errstr(status)));
3583 0 : return status;
3584 : }
3585 :
3586 3598 : status = marshall_stream_info(num_streams, streams,
3587 : pdata, max_data_bytes,
3588 : &data_size);
3589 :
3590 3598 : if (!NT_STATUS_IS_OK(status)) {
3591 152 : DEBUG(10, ("marshall_stream_info failed: %s\n",
3592 : nt_errstr(status)));
3593 152 : TALLOC_FREE(streams);
3594 152 : return status;
3595 : }
3596 :
3597 3446 : TALLOC_FREE(streams);
3598 :
3599 3446 : *fixed_portion = 32;
3600 :
3601 3446 : break;
3602 : }
3603 88 : case SMB_QUERY_COMPRESSION_INFO:
3604 : case SMB_FILE_COMPRESSION_INFORMATION:
3605 88 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3606 88 : SOFF_T(pdata,0,file_size);
3607 88 : SIVAL(pdata,8,0); /* ??? */
3608 88 : SIVAL(pdata,12,0); /* ??? */
3609 88 : data_size = 16;
3610 88 : *fixed_portion = 16;
3611 88 : break;
3612 :
3613 244 : case SMB_FILE_NETWORK_OPEN_INFORMATION:
3614 244 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3615 244 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3616 244 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3617 244 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3618 244 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3619 244 : SOFF_T(pdata,32,allocation_size);
3620 244 : SOFF_T(pdata,40,file_size);
3621 244 : SIVAL(pdata,48,mode);
3622 244 : SIVAL(pdata,52,0); /* ??? */
3623 244 : data_size = 56;
3624 244 : *fixed_portion = 56;
3625 244 : break;
3626 :
3627 52 : case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3628 52 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3629 52 : SIVAL(pdata,0,mode);
3630 52 : SIVAL(pdata,4,0);
3631 52 : data_size = 8;
3632 52 : *fixed_portion = 8;
3633 52 : break;
3634 :
3635 : /*
3636 : * SMB2 UNIX Extensions.
3637 : */
3638 0 : case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3639 : {
3640 0 : struct smb3_file_posix_information info = {};
3641 0 : uint8_t buf[sizeof(info)];
3642 0 : struct ndr_push ndr = {
3643 : .data = buf,
3644 : .alloc_size = sizeof(buf),
3645 : .fixed_buf_size = true,
3646 : };
3647 0 : enum ndr_err_code ndr_err;
3648 :
3649 0 : if (!(conn->sconn->using_smb2)) {
3650 0 : return NT_STATUS_INVALID_LEVEL;
3651 : }
3652 0 : if (fsp == NULL) {
3653 0 : return NT_STATUS_INVALID_HANDLE;
3654 : }
3655 0 : if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3656 0 : return NT_STATUS_INVALID_LEVEL;
3657 : }
3658 :
3659 0 : smb3_file_posix_information_init(
3660 0 : conn, &smb_fname->st, 0, mode, &info);
3661 :
3662 0 : ndr_err = ndr_push_smb3_file_posix_information(
3663 : &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3664 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3665 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
3666 : }
3667 :
3668 0 : memcpy(pdata, buf, ndr.offset);
3669 0 : data_size = ndr.offset;
3670 0 : break;
3671 : }
3672 :
3673 8 : default:
3674 8 : return NT_STATUS_INVALID_LEVEL;
3675 : }
3676 :
3677 24175 : *pdata_size = data_size;
3678 24175 : return NT_STATUS_OK;
3679 : }
3680 :
3681 : /****************************************************************************
3682 : Set a hard link (called by UNIX extensions and by NT rename with HARD link
3683 : code.
3684 : ****************************************************************************/
3685 :
3686 51 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3687 : connection_struct *conn,
3688 : struct smb_request *req,
3689 : bool overwrite_if_exists,
3690 : const struct smb_filename *smb_fname_old,
3691 : struct smb_filename *smb_fname_new)
3692 : {
3693 51 : NTSTATUS status = NT_STATUS_OK;
3694 1 : int ret;
3695 1 : bool ok;
3696 51 : struct smb_filename *parent_fname_old = NULL;
3697 51 : struct smb_filename *base_name_old = NULL;
3698 51 : struct smb_filename *parent_fname_new = NULL;
3699 51 : struct smb_filename *base_name_new = NULL;
3700 :
3701 : /* source must already exist. */
3702 51 : if (!VALID_STAT(smb_fname_old->st)) {
3703 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3704 0 : goto out;
3705 : }
3706 :
3707 : /* No links from a directory. */
3708 51 : if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3709 8 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3710 8 : goto out;
3711 : }
3712 :
3713 : /* Setting a hardlink to/from a stream isn't currently supported. */
3714 43 : ok = is_ntfs_stream_smb_fname(smb_fname_old);
3715 43 : if (ok) {
3716 0 : DBG_DEBUG("Old name has streams\n");
3717 0 : status = NT_STATUS_INVALID_PARAMETER;
3718 0 : goto out;
3719 : }
3720 43 : ok = is_ntfs_stream_smb_fname(smb_fname_new);
3721 43 : if (ok) {
3722 0 : DBG_DEBUG("New name has streams\n");
3723 0 : status = NT_STATUS_INVALID_PARAMETER;
3724 0 : goto out;
3725 : }
3726 :
3727 43 : status = parent_pathref(talloc_tos(),
3728 : conn->cwd_fsp,
3729 : smb_fname_old,
3730 : &parent_fname_old,
3731 : &base_name_old);
3732 43 : if (!NT_STATUS_IS_OK(status)) {
3733 0 : goto out;
3734 : }
3735 :
3736 43 : status = parent_pathref(talloc_tos(),
3737 : conn->cwd_fsp,
3738 : smb_fname_new,
3739 : &parent_fname_new,
3740 : &base_name_new);
3741 43 : if (!NT_STATUS_IS_OK(status)) {
3742 0 : goto out;
3743 : }
3744 :
3745 43 : if (VALID_STAT(smb_fname_new->st)) {
3746 0 : if (overwrite_if_exists) {
3747 0 : if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3748 0 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3749 0 : goto out;
3750 : }
3751 0 : status = unlink_internals(conn,
3752 : req,
3753 : FILE_ATTRIBUTE_NORMAL,
3754 : NULL, /* new_dirfsp */
3755 : smb_fname_new);
3756 0 : if (!NT_STATUS_IS_OK(status)) {
3757 0 : goto out;
3758 : }
3759 : } else {
3760 : /* Disallow if newname already exists. */
3761 0 : status = NT_STATUS_OBJECT_NAME_COLLISION;
3762 0 : goto out;
3763 : }
3764 : }
3765 :
3766 43 : DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3767 : smb_fname_old->base_name, smb_fname_new->base_name));
3768 :
3769 43 : ret = SMB_VFS_LINKAT(conn,
3770 : parent_fname_old->fsp,
3771 : base_name_old,
3772 : parent_fname_new->fsp,
3773 : base_name_new,
3774 : 0);
3775 :
3776 43 : if (ret != 0) {
3777 0 : status = map_nt_error_from_unix(errno);
3778 0 : DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3779 : nt_errstr(status), smb_fname_old->base_name,
3780 : smb_fname_new->base_name));
3781 : }
3782 :
3783 43 : out:
3784 :
3785 51 : TALLOC_FREE(parent_fname_old);
3786 51 : TALLOC_FREE(parent_fname_new);
3787 51 : return status;
3788 : }
3789 :
3790 : /****************************************************************************
3791 : Deal with setting the time from any of the setfilepathinfo functions.
3792 : NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3793 : calling this function.
3794 : ****************************************************************************/
3795 :
3796 11038 : NTSTATUS smb_set_file_time(connection_struct *conn,
3797 : files_struct *fsp,
3798 : struct smb_filename *smb_fname,
3799 : struct smb_file_time *ft,
3800 : bool setting_write_time)
3801 : {
3802 11038 : struct files_struct *set_fsp = NULL;
3803 115 : struct timeval_buf tbuf[4];
3804 11038 : uint32_t action =
3805 : FILE_NOTIFY_CHANGE_LAST_ACCESS
3806 : |FILE_NOTIFY_CHANGE_LAST_WRITE
3807 : |FILE_NOTIFY_CHANGE_CREATION;
3808 115 : int ret;
3809 :
3810 11038 : if (!VALID_STAT(smb_fname->st)) {
3811 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3812 : }
3813 :
3814 11038 : if (fsp == NULL) {
3815 : /* A symlink */
3816 0 : return NT_STATUS_OK;
3817 : }
3818 :
3819 11038 : set_fsp = metadata_fsp(fsp);
3820 :
3821 : /* get some defaults (no modifications) if any info is zero or -1. */
3822 11038 : if (is_omit_timespec(&ft->create_time)) {
3823 10194 : action &= ~FILE_NOTIFY_CHANGE_CREATION;
3824 : }
3825 :
3826 11038 : if (is_omit_timespec(&ft->atime)) {
3827 10139 : action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3828 : }
3829 :
3830 11038 : if (is_omit_timespec(&ft->mtime)) {
3831 3120 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3832 : }
3833 :
3834 11038 : if (!setting_write_time) {
3835 : /* ft->mtime comes from change time, not write time. */
3836 6705 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3837 : }
3838 :
3839 : /* Ensure the resolution is the correct for
3840 : * what we can store on this filesystem. */
3841 :
3842 11038 : round_timespec(conn->ts_res, &ft->create_time);
3843 11038 : round_timespec(conn->ts_res, &ft->ctime);
3844 11038 : round_timespec(conn->ts_res, &ft->atime);
3845 11038 : round_timespec(conn->ts_res, &ft->mtime);
3846 :
3847 11038 : DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3848 : timespec_string_buf(&ft->atime, true, &tbuf[0]));
3849 11038 : DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3850 : timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3851 11038 : DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3852 : timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3853 11038 : DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3854 : timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3855 :
3856 11038 : if (setting_write_time) {
3857 : /*
3858 : * This was a Windows setfileinfo on an open file.
3859 : * NT does this a lot. We also need to
3860 : * set the time here, as it can be read by
3861 : * FindFirst/FindNext and with the patch for bug #2045
3862 : * in smbd/fileio.c it ensures that this timestamp is
3863 : * kept sticky even after a write. We save the request
3864 : * away and will set it on file close and after a write. JRA.
3865 : */
3866 :
3867 4333 : DBG_DEBUG("setting pending modtime to %s\n",
3868 : timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3869 :
3870 4333 : if (set_fsp != NULL) {
3871 4333 : set_sticky_write_time_fsp(set_fsp, ft->mtime);
3872 : } else {
3873 0 : set_sticky_write_time_path(
3874 0 : vfs_file_id_from_sbuf(conn, &smb_fname->st),
3875 : ft->mtime);
3876 : }
3877 : }
3878 :
3879 11038 : DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3880 :
3881 11038 : ret = file_ntimes(conn, set_fsp, ft);
3882 11038 : if (ret != 0) {
3883 2 : return map_nt_error_from_unix(errno);
3884 : }
3885 :
3886 11036 : notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3887 11036 : smb_fname->base_name);
3888 11036 : return NT_STATUS_OK;
3889 : }
3890 :
3891 : /****************************************************************************
3892 : Deal with setting the dosmode from any of the setfilepathinfo functions.
3893 : NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3894 : done before calling this function.
3895 : ****************************************************************************/
3896 :
3897 2812 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3898 : struct files_struct *fsp,
3899 : uint32_t dosmode)
3900 : {
3901 2812 : struct files_struct *dos_fsp = NULL;
3902 31 : uint32_t current_dosmode;
3903 31 : int ret;
3904 :
3905 2812 : if (!VALID_STAT(fsp->fsp_name->st)) {
3906 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3907 : }
3908 :
3909 2812 : dos_fsp = metadata_fsp(fsp);
3910 :
3911 2812 : if (dosmode != 0) {
3912 1275 : if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3913 183 : dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3914 : } else {
3915 1092 : dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3916 : }
3917 : }
3918 :
3919 2812 : DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3920 :
3921 : /* check the mode isn't different, before changing it */
3922 2812 : if (dosmode == 0) {
3923 1537 : return NT_STATUS_OK;
3924 : }
3925 1275 : current_dosmode = fdos_mode(dos_fsp);
3926 1275 : if (dosmode == current_dosmode) {
3927 292 : return NT_STATUS_OK;
3928 : }
3929 :
3930 983 : DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3931 : fsp_str_dbg(dos_fsp), dosmode);
3932 :
3933 983 : ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3934 983 : if (ret != 0) {
3935 5 : DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3936 : fsp_str_dbg(dos_fsp), strerror(errno));
3937 5 : return map_nt_error_from_unix(errno);
3938 : }
3939 :
3940 978 : return NT_STATUS_OK;
3941 : }
3942 :
3943 : /****************************************************************************
3944 : Deal with setting the size from any of the setfilepathinfo functions.
3945 : ****************************************************************************/
3946 :
3947 471 : NTSTATUS smb_set_file_size(connection_struct *conn,
3948 : struct smb_request *req,
3949 : files_struct *fsp,
3950 : struct smb_filename *smb_fname,
3951 : const SMB_STRUCT_STAT *psbuf,
3952 : off_t size,
3953 : bool fail_after_createfile)
3954 : {
3955 471 : NTSTATUS status = NT_STATUS_OK;
3956 471 : files_struct *new_fsp = NULL;
3957 :
3958 471 : if (!VALID_STAT(*psbuf)) {
3959 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3960 : }
3961 :
3962 471 : DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3963 : (uint64_t)size,
3964 : get_file_size_stat(psbuf));
3965 :
3966 471 : if (size == get_file_size_stat(psbuf)) {
3967 148 : if (fsp == NULL) {
3968 0 : return NT_STATUS_OK;
3969 : }
3970 148 : if (!fsp->fsp_flags.modified) {
3971 144 : return NT_STATUS_OK;
3972 : }
3973 4 : trigger_write_time_update_immediate(fsp);
3974 4 : return NT_STATUS_OK;
3975 : }
3976 :
3977 323 : DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
3978 : smb_fname_str_dbg(smb_fname), (double)size));
3979 :
3980 323 : if (fsp &&
3981 606 : !fsp->fsp_flags.is_pathref &&
3982 283 : fsp_get_io_fd(fsp) != -1)
3983 : {
3984 : /* Handle based call. */
3985 283 : if (!(fsp->access_mask & FILE_WRITE_DATA)) {
3986 0 : return NT_STATUS_ACCESS_DENIED;
3987 : }
3988 :
3989 283 : if (vfs_set_filelen(fsp, size) == -1) {
3990 8 : return map_nt_error_from_unix(errno);
3991 : }
3992 275 : trigger_write_time_update_immediate(fsp);
3993 275 : return NT_STATUS_OK;
3994 : }
3995 :
3996 40 : status = SMB_VFS_CREATE_FILE(
3997 : conn, /* conn */
3998 : req, /* req */
3999 : NULL, /* dirfsp */
4000 : smb_fname, /* fname */
4001 : FILE_WRITE_DATA, /* access_mask */
4002 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4003 : FILE_SHARE_DELETE),
4004 : FILE_OPEN, /* create_disposition*/
4005 : 0, /* create_options */
4006 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4007 : 0, /* oplock_request */
4008 : NULL, /* lease */
4009 : 0, /* allocation_size */
4010 : 0, /* private_flags */
4011 : NULL, /* sd */
4012 : NULL, /* ea_list */
4013 : &new_fsp, /* result */
4014 : NULL, /* pinfo */
4015 : NULL, NULL); /* create context */
4016 :
4017 40 : if (!NT_STATUS_IS_OK(status)) {
4018 : /* NB. We check for open_was_deferred in the caller. */
4019 28 : return status;
4020 : }
4021 :
4022 : /* See RAW-SFILEINFO-END-OF-FILE */
4023 12 : if (fail_after_createfile) {
4024 4 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4025 4 : return NT_STATUS_INVALID_LEVEL;
4026 : }
4027 :
4028 8 : if (vfs_set_filelen(new_fsp, size) == -1) {
4029 0 : status = map_nt_error_from_unix(errno);
4030 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4031 0 : return status;
4032 : }
4033 :
4034 8 : trigger_write_time_update_immediate(new_fsp);
4035 8 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4036 8 : return NT_STATUS_OK;
4037 : }
4038 :
4039 : /****************************************************************************
4040 : Deal with SMB_INFO_SET_EA.
4041 : ****************************************************************************/
4042 :
4043 2931 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
4044 : const char *pdata,
4045 : int total_data,
4046 : files_struct *fsp,
4047 : struct smb_filename *smb_fname)
4048 : {
4049 2931 : struct ea_list *ea_list = NULL;
4050 2931 : TALLOC_CTX *ctx = NULL;
4051 2931 : NTSTATUS status = NT_STATUS_OK;
4052 :
4053 2931 : if (total_data < 10) {
4054 :
4055 : /* OS/2 workplace shell seems to send SET_EA requests of "null"
4056 : length. They seem to have no effect. Bug #3212. JRA */
4057 :
4058 0 : if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4059 : /* We're done. We only get EA info in this call. */
4060 0 : return NT_STATUS_OK;
4061 : }
4062 :
4063 0 : return NT_STATUS_INVALID_PARAMETER;
4064 : }
4065 :
4066 2931 : if (IVAL(pdata,0) > total_data) {
4067 0 : DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4068 : IVAL(pdata,0), (unsigned int)total_data));
4069 0 : return NT_STATUS_INVALID_PARAMETER;
4070 : }
4071 :
4072 2931 : ctx = talloc_tos();
4073 2931 : ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4074 2931 : if (!ea_list) {
4075 8 : return NT_STATUS_INVALID_PARAMETER;
4076 : }
4077 :
4078 2923 : if (fsp == NULL) {
4079 : /*
4080 : * The only way fsp can be NULL here is if
4081 : * smb_fname points at a symlink and
4082 : * and we're in POSIX context.
4083 : * Ensure this is the case.
4084 : *
4085 : * In this case we cannot set the EA.
4086 : */
4087 0 : SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4088 0 : return NT_STATUS_ACCESS_DENIED;
4089 : }
4090 :
4091 2923 : status = set_ea(conn, fsp, ea_list);
4092 :
4093 2923 : return status;
4094 : }
4095 :
4096 : /****************************************************************************
4097 : Deal with SMB_FILE_FULL_EA_INFORMATION set.
4098 : ****************************************************************************/
4099 :
4100 12 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4101 : const char *pdata,
4102 : int total_data,
4103 : files_struct *fsp)
4104 : {
4105 12 : struct ea_list *ea_list = NULL;
4106 0 : NTSTATUS status;
4107 :
4108 12 : if (fsp == NULL) {
4109 0 : return NT_STATUS_INVALID_HANDLE;
4110 : }
4111 :
4112 12 : if (!lp_ea_support(SNUM(conn))) {
4113 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4114 : "EA's not supported.\n",
4115 : (unsigned int)total_data));
4116 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
4117 : }
4118 :
4119 12 : if (total_data < 10) {
4120 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4121 : "too small.\n",
4122 : (unsigned int)total_data));
4123 0 : return NT_STATUS_INVALID_PARAMETER;
4124 : }
4125 :
4126 12 : ea_list = read_nttrans_ea_list(talloc_tos(),
4127 : pdata,
4128 : total_data);
4129 :
4130 12 : if (!ea_list) {
4131 0 : return NT_STATUS_INVALID_PARAMETER;
4132 : }
4133 :
4134 12 : status = set_ea(conn, fsp, ea_list);
4135 :
4136 12 : DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4137 : smb_fname_str_dbg(fsp->fsp_name),
4138 : nt_errstr(status) ));
4139 :
4140 12 : return status;
4141 : }
4142 :
4143 :
4144 : /****************************************************************************
4145 : Deal with SMB_SET_FILE_DISPOSITION_INFO.
4146 : ****************************************************************************/
4147 :
4148 3878 : NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4149 : const char *pdata,
4150 : int total_data,
4151 : files_struct *fsp,
4152 : struct smb_filename *smb_fname)
4153 : {
4154 3878 : NTSTATUS status = NT_STATUS_OK;
4155 21 : bool delete_on_close;
4156 3878 : uint32_t dosmode = 0;
4157 :
4158 3878 : if (total_data < 1) {
4159 0 : return NT_STATUS_INVALID_PARAMETER;
4160 : }
4161 :
4162 3878 : if (fsp == NULL) {
4163 0 : return NT_STATUS_INVALID_HANDLE;
4164 : }
4165 :
4166 3878 : delete_on_close = (CVAL(pdata,0) ? True : False);
4167 3878 : dosmode = fdos_mode(fsp);
4168 :
4169 3878 : DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4170 : "delete_on_close = %u\n",
4171 : smb_fname_str_dbg(smb_fname),
4172 : (unsigned int)dosmode,
4173 : (unsigned int)delete_on_close ));
4174 :
4175 3878 : if (delete_on_close) {
4176 3823 : status = can_set_delete_on_close(fsp, dosmode);
4177 3823 : if (!NT_STATUS_IS_OK(status)) {
4178 88 : return status;
4179 : }
4180 : }
4181 :
4182 : /* The set is across all open files on this dev/inode pair. */
4183 3790 : if (!set_delete_on_close(fsp, delete_on_close,
4184 3790 : conn->session_info->security_token,
4185 3790 : conn->session_info->unix_token)) {
4186 8 : return NT_STATUS_ACCESS_DENIED;
4187 : }
4188 3782 : return NT_STATUS_OK;
4189 : }
4190 :
4191 : /****************************************************************************
4192 : Deal with SMB_FILE_POSITION_INFORMATION.
4193 : ****************************************************************************/
4194 :
4195 94 : static NTSTATUS smb_file_position_information(connection_struct *conn,
4196 : const char *pdata,
4197 : int total_data,
4198 : files_struct *fsp)
4199 : {
4200 2 : uint64_t position_information;
4201 :
4202 94 : if (total_data < 8) {
4203 0 : return NT_STATUS_INVALID_PARAMETER;
4204 : }
4205 :
4206 94 : if (fsp == NULL) {
4207 : /* Ignore on pathname based set. */
4208 0 : return NT_STATUS_OK;
4209 : }
4210 :
4211 94 : position_information = (uint64_t)IVAL(pdata,0);
4212 94 : position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4213 :
4214 94 : DEBUG(10,("smb_file_position_information: Set file position "
4215 : "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4216 : (double)position_information));
4217 94 : fh_set_position_information(fsp->fh, position_information);
4218 94 : return NT_STATUS_OK;
4219 : }
4220 :
4221 : /****************************************************************************
4222 : Deal with SMB_FILE_MODE_INFORMATION.
4223 : ****************************************************************************/
4224 :
4225 8 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
4226 : const char *pdata,
4227 : int total_data)
4228 : {
4229 0 : uint32_t mode;
4230 :
4231 8 : if (total_data < 4) {
4232 0 : return NT_STATUS_INVALID_PARAMETER;
4233 : }
4234 8 : mode = IVAL(pdata,0);
4235 8 : if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4236 0 : return NT_STATUS_INVALID_PARAMETER;
4237 : }
4238 8 : return NT_STATUS_OK;
4239 : }
4240 :
4241 : /****************************************************************************
4242 : Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4243 : ****************************************************************************/
4244 :
4245 791 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4246 : struct smb_request *req,
4247 : const char *pdata,
4248 : int total_data,
4249 : files_struct *fsp,
4250 : struct smb_filename *smb_fname_src)
4251 : {
4252 0 : bool overwrite;
4253 0 : uint32_t len;
4254 791 : char *newname = NULL;
4255 791 : struct files_struct *dst_dirfsp = NULL;
4256 791 : struct smb_filename *smb_fname_dst = NULL;
4257 791 : const char *dst_original_lcomp = NULL;
4258 791 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4259 791 : NTSTATUS status = NT_STATUS_OK;
4260 791 : TALLOC_CTX *ctx = talloc_tos();
4261 :
4262 791 : if (!fsp) {
4263 0 : return NT_STATUS_INVALID_HANDLE;
4264 : }
4265 :
4266 791 : if (total_data < 20) {
4267 0 : return NT_STATUS_INVALID_PARAMETER;
4268 : }
4269 :
4270 791 : overwrite = (CVAL(pdata,0) ? True : False);
4271 791 : len = IVAL(pdata,16);
4272 :
4273 791 : if (len > (total_data - 20) || (len == 0)) {
4274 0 : return NT_STATUS_INVALID_PARAMETER;
4275 : }
4276 :
4277 791 : (void)srvstr_pull_talloc(ctx,
4278 : pdata,
4279 : req->flags2,
4280 : &newname,
4281 : &pdata[20],
4282 : len,
4283 : STR_TERMINATE);
4284 :
4285 791 : if (newname == NULL) {
4286 0 : return NT_STATUS_INVALID_PARAMETER;
4287 : }
4288 :
4289 : /* SMB2 rename paths are never DFS. */
4290 791 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4291 791 : ucf_flags &= ~UCF_DFS_PATHNAME;
4292 :
4293 791 : status = check_path_syntax(newname,
4294 791 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4295 791 : if (!NT_STATUS_IS_OK(status)) {
4296 0 : return status;
4297 : }
4298 :
4299 791 : DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4300 : newname));
4301 :
4302 791 : if (newname[0] == ':') {
4303 : /* Create an smb_fname to call rename_internals_fsp() with. */
4304 16 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4305 16 : fsp->base_fsp->fsp_name->base_name,
4306 : newname,
4307 : NULL,
4308 16 : fsp->base_fsp->fsp_name->twrp,
4309 16 : fsp->base_fsp->fsp_name->flags);
4310 16 : if (smb_fname_dst == NULL) {
4311 0 : status = NT_STATUS_NO_MEMORY;
4312 0 : goto out;
4313 : }
4314 : } else {
4315 775 : status = filename_convert_dirfsp(ctx,
4316 : conn,
4317 : newname,
4318 : ucf_flags,
4319 : 0, /* Never a TWRP. */
4320 : &dst_dirfsp,
4321 : &smb_fname_dst);
4322 775 : if (!NT_STATUS_IS_OK(status)) {
4323 130 : goto out;
4324 : }
4325 : }
4326 :
4327 : /*
4328 : * Set the original last component, since
4329 : * rename_internals_fsp() requires it.
4330 : */
4331 661 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4332 : conn,
4333 : newname,
4334 : ucf_flags);
4335 661 : if (dst_original_lcomp == NULL) {
4336 0 : status = NT_STATUS_NO_MEMORY;
4337 0 : goto out;
4338 : }
4339 :
4340 661 : DEBUG(10,("smb2_file_rename_information: "
4341 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4342 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4343 : smb_fname_str_dbg(smb_fname_dst)));
4344 661 : status = rename_internals_fsp(conn,
4345 : fsp,
4346 : smb_fname_dst,
4347 : dst_original_lcomp,
4348 : (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4349 : overwrite);
4350 :
4351 791 : out:
4352 791 : TALLOC_FREE(smb_fname_dst);
4353 791 : return status;
4354 : }
4355 :
4356 18 : static NTSTATUS smb2_file_link_information(connection_struct *conn,
4357 : struct smb_request *req,
4358 : const char *pdata,
4359 : int total_data,
4360 : files_struct *fsp,
4361 : struct smb_filename *smb_fname_src)
4362 : {
4363 0 : bool overwrite;
4364 0 : uint32_t len;
4365 18 : char *newname = NULL;
4366 18 : struct files_struct *dst_dirfsp = NULL;
4367 18 : struct smb_filename *smb_fname_dst = NULL;
4368 18 : NTSTATUS status = NT_STATUS_OK;
4369 18 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4370 0 : size_t ret;
4371 18 : TALLOC_CTX *ctx = talloc_tos();
4372 :
4373 18 : if (!fsp) {
4374 0 : return NT_STATUS_INVALID_HANDLE;
4375 : }
4376 :
4377 18 : if (total_data < 20) {
4378 0 : return NT_STATUS_INVALID_PARAMETER;
4379 : }
4380 :
4381 18 : overwrite = (CVAL(pdata,0) ? true : false);
4382 18 : len = IVAL(pdata,16);
4383 :
4384 18 : if (len > (total_data - 20) || (len == 0)) {
4385 0 : return NT_STATUS_INVALID_PARAMETER;
4386 : }
4387 :
4388 18 : ret = srvstr_pull_talloc(ctx,
4389 : pdata,
4390 : req->flags2,
4391 : &newname,
4392 : &pdata[20],
4393 : len,
4394 : STR_TERMINATE);
4395 :
4396 18 : if (ret == (size_t)-1 || newname == NULL) {
4397 0 : return NT_STATUS_INVALID_PARAMETER;
4398 : }
4399 :
4400 : /* SMB2 hardlink paths are never DFS. */
4401 18 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4402 18 : ucf_flags &= ~UCF_DFS_PATHNAME;
4403 :
4404 18 : status = check_path_syntax(newname,
4405 18 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4406 18 : if (!NT_STATUS_IS_OK(status)) {
4407 0 : return status;
4408 : }
4409 :
4410 18 : DBG_DEBUG("got name |%s|\n", newname);
4411 :
4412 18 : status = filename_convert_dirfsp(ctx,
4413 : conn,
4414 : newname,
4415 : ucf_flags,
4416 : 0, /* No TWRP. */
4417 : &dst_dirfsp,
4418 : &smb_fname_dst);
4419 18 : if (!NT_STATUS_IS_OK(status)) {
4420 2 : return status;
4421 : }
4422 :
4423 16 : if (fsp->base_fsp) {
4424 : /* No stream names. */
4425 0 : return NT_STATUS_NOT_SUPPORTED;
4426 : }
4427 :
4428 16 : DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4429 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4430 : smb_fname_str_dbg(smb_fname_dst));
4431 16 : status = hardlink_internals(ctx,
4432 : conn,
4433 : req,
4434 : overwrite,
4435 16 : fsp->fsp_name,
4436 : smb_fname_dst);
4437 :
4438 16 : TALLOC_FREE(smb_fname_dst);
4439 16 : return status;
4440 : }
4441 :
4442 8 : static NTSTATUS smb_file_link_information(connection_struct *conn,
4443 : struct smb_request *req,
4444 : const char *pdata,
4445 : int total_data,
4446 : files_struct *fsp,
4447 : struct smb_filename *smb_fname_src)
4448 : {
4449 0 : bool overwrite;
4450 0 : uint32_t len;
4451 8 : char *newname = NULL;
4452 8 : struct files_struct *dst_dirfsp = NULL;
4453 8 : struct smb_filename *smb_fname_dst = NULL;
4454 8 : NTSTATUS status = NT_STATUS_OK;
4455 8 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4456 8 : NTTIME dst_twrp = 0;
4457 8 : TALLOC_CTX *ctx = talloc_tos();
4458 :
4459 8 : if (!fsp) {
4460 0 : return NT_STATUS_INVALID_HANDLE;
4461 : }
4462 :
4463 8 : if (total_data < 20) {
4464 0 : return NT_STATUS_INVALID_PARAMETER;
4465 : }
4466 :
4467 8 : overwrite = (CVAL(pdata,0) ? true : false);
4468 8 : len = IVAL(pdata,16);
4469 :
4470 8 : if (len > (total_data - 20) || (len == 0)) {
4471 8 : return NT_STATUS_INVALID_PARAMETER;
4472 : }
4473 :
4474 0 : if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4475 0 : srvstr_get_path_posix(ctx,
4476 : pdata,
4477 0 : req->flags2,
4478 : &newname,
4479 : &pdata[20],
4480 : len,
4481 : STR_TERMINATE,
4482 : &status);
4483 0 : ucf_flags |= UCF_POSIX_PATHNAMES;
4484 : } else {
4485 0 : srvstr_get_path(ctx,
4486 : pdata,
4487 0 : req->flags2,
4488 : &newname,
4489 : &pdata[20],
4490 : len,
4491 : STR_TERMINATE,
4492 : &status);
4493 : }
4494 0 : if (!NT_STATUS_IS_OK(status)) {
4495 0 : return status;
4496 : }
4497 :
4498 0 : DEBUG(10,("smb_file_link_information: got name |%s|\n",
4499 : newname));
4500 :
4501 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
4502 0 : extract_snapshot_token(newname, &dst_twrp);
4503 : }
4504 : /* hardlink paths are never DFS. */
4505 0 : ucf_flags &= ~UCF_DFS_PATHNAME;
4506 :
4507 0 : status = filename_convert_dirfsp(ctx,
4508 : conn,
4509 : newname,
4510 : ucf_flags,
4511 : dst_twrp,
4512 : &dst_dirfsp,
4513 : &smb_fname_dst);
4514 0 : if (!NT_STATUS_IS_OK(status)) {
4515 0 : return status;
4516 : }
4517 :
4518 0 : if (fsp->base_fsp) {
4519 : /* No stream names. */
4520 0 : return NT_STATUS_NOT_SUPPORTED;
4521 : }
4522 :
4523 0 : DEBUG(10,("smb_file_link_information: "
4524 : "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4525 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4526 : smb_fname_str_dbg(smb_fname_dst)));
4527 0 : status = hardlink_internals(ctx,
4528 : conn,
4529 : req,
4530 : overwrite,
4531 0 : fsp->fsp_name,
4532 : smb_fname_dst);
4533 :
4534 0 : TALLOC_FREE(smb_fname_dst);
4535 0 : return status;
4536 : }
4537 :
4538 :
4539 : /****************************************************************************
4540 : Deal with SMB_FILE_RENAME_INFORMATION.
4541 : ****************************************************************************/
4542 :
4543 139 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
4544 : struct smb_request *req,
4545 : const char *pdata,
4546 : int total_data,
4547 : files_struct *fsp,
4548 : struct smb_filename *smb_fname_src)
4549 : {
4550 3 : bool overwrite;
4551 3 : uint32_t root_fid;
4552 3 : uint32_t len;
4553 139 : char *newname = NULL;
4554 139 : struct files_struct *dst_dirfsp = NULL;
4555 139 : struct smb_filename *smb_fname_dst = NULL;
4556 139 : const char *dst_original_lcomp = NULL;
4557 139 : NTSTATUS status = NT_STATUS_OK;
4558 3 : char *p;
4559 139 : TALLOC_CTX *ctx = talloc_tos();
4560 :
4561 139 : if (total_data < 13) {
4562 0 : return NT_STATUS_INVALID_PARAMETER;
4563 : }
4564 :
4565 139 : overwrite = (CVAL(pdata,0) != 0);
4566 139 : root_fid = IVAL(pdata,4);
4567 139 : len = IVAL(pdata,8);
4568 :
4569 139 : if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4570 12 : return NT_STATUS_INVALID_PARAMETER;
4571 : }
4572 :
4573 127 : if (req->posix_pathnames) {
4574 0 : srvstr_get_path_posix(ctx,
4575 : pdata,
4576 0 : req->flags2,
4577 : &newname,
4578 : &pdata[12],
4579 : len,
4580 : 0,
4581 : &status);
4582 : } else {
4583 127 : srvstr_get_path(ctx,
4584 : pdata,
4585 127 : req->flags2,
4586 : &newname,
4587 : &pdata[12],
4588 : len,
4589 : 0,
4590 : &status);
4591 : }
4592 127 : if (!NT_STATUS_IS_OK(status)) {
4593 0 : return status;
4594 : }
4595 :
4596 127 : DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4597 : newname));
4598 :
4599 : /* Check the new name has no '/' characters. */
4600 127 : if (strchr_m(newname, '/')) {
4601 8 : return NT_STATUS_NOT_SUPPORTED;
4602 : }
4603 :
4604 119 : if (fsp && fsp->base_fsp) {
4605 : /* newname must be a stream name. */
4606 28 : if (newname[0] != ':') {
4607 0 : return NT_STATUS_NOT_SUPPORTED;
4608 : }
4609 :
4610 : /* Create an smb_fname to call rename_internals_fsp() with. */
4611 28 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4612 28 : fsp->base_fsp->fsp_name->base_name,
4613 : newname,
4614 : NULL,
4615 28 : fsp->base_fsp->fsp_name->twrp,
4616 28 : fsp->base_fsp->fsp_name->flags);
4617 28 : if (smb_fname_dst == NULL) {
4618 0 : status = NT_STATUS_NO_MEMORY;
4619 0 : goto out;
4620 : }
4621 :
4622 : /*
4623 : * Get the original last component, since
4624 : * rename_internals_fsp() requires it.
4625 : */
4626 28 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4627 : conn,
4628 : newname,
4629 : 0);
4630 28 : if (dst_original_lcomp == NULL) {
4631 0 : status = NT_STATUS_NO_MEMORY;
4632 0 : goto out;
4633 : }
4634 :
4635 : } else {
4636 : /*
4637 : * Build up an smb_fname_dst based on the filename passed in.
4638 : * We basically just strip off the last component, and put on
4639 : * the newname instead.
4640 : */
4641 91 : char *base_name = NULL;
4642 91 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4643 91 : NTTIME dst_twrp = 0;
4644 :
4645 : /* newname must *not* be a stream name. */
4646 91 : if (newname[0] == ':') {
4647 0 : return NT_STATUS_NOT_SUPPORTED;
4648 : }
4649 :
4650 : /*
4651 : * Strip off the last component (filename) of the path passed
4652 : * in.
4653 : */
4654 91 : base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4655 91 : if (!base_name) {
4656 0 : return NT_STATUS_NO_MEMORY;
4657 : }
4658 91 : p = strrchr_m(base_name, '/');
4659 91 : if (p) {
4660 80 : p[1] = '\0';
4661 : } else {
4662 11 : base_name = talloc_strdup(ctx, "");
4663 11 : if (!base_name) {
4664 0 : return NT_STATUS_NO_MEMORY;
4665 : }
4666 : }
4667 : /* Append the new name. */
4668 91 : base_name = talloc_asprintf_append(base_name,
4669 : "%s",
4670 : newname);
4671 91 : if (!base_name) {
4672 0 : return NT_STATUS_NO_MEMORY;
4673 : }
4674 :
4675 91 : if (ucf_flags & UCF_GMT_PATHNAME) {
4676 0 : extract_snapshot_token(base_name, &dst_twrp);
4677 : }
4678 :
4679 : /* The newname is *not* a DFS path. */
4680 91 : ucf_flags &= ~UCF_DFS_PATHNAME;
4681 :
4682 91 : status = filename_convert_dirfsp(ctx,
4683 : conn,
4684 : base_name,
4685 : ucf_flags,
4686 : dst_twrp,
4687 : &dst_dirfsp,
4688 : &smb_fname_dst);
4689 :
4690 91 : if (!NT_STATUS_IS_OK(status)) {
4691 0 : goto out;
4692 : }
4693 91 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4694 : conn,
4695 : newname,
4696 : ucf_flags);
4697 91 : if (dst_original_lcomp == NULL) {
4698 0 : status = NT_STATUS_NO_MEMORY;
4699 0 : goto out;
4700 : }
4701 : }
4702 :
4703 119 : if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4704 80 : DEBUG(10,("smb_file_rename_information: "
4705 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4706 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4707 : smb_fname_str_dbg(smb_fname_dst)));
4708 80 : status = rename_internals_fsp(conn,
4709 : fsp,
4710 : smb_fname_dst,
4711 : dst_original_lcomp,
4712 : 0,
4713 : overwrite);
4714 : } else {
4715 39 : DEBUG(10,("smb_file_rename_information: "
4716 : "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4717 : smb_fname_str_dbg(smb_fname_src),
4718 : smb_fname_str_dbg(smb_fname_dst)));
4719 39 : status = rename_internals(ctx,
4720 : conn,
4721 : req,
4722 : NULL, /* src_dirfsp */
4723 : smb_fname_src,
4724 : smb_fname_dst,
4725 : dst_original_lcomp,
4726 : 0,
4727 : overwrite,
4728 : FILE_WRITE_ATTRIBUTES);
4729 : }
4730 119 : out:
4731 119 : TALLOC_FREE(smb_fname_dst);
4732 119 : return status;
4733 : }
4734 :
4735 : /****************************************************************************
4736 : Deal with SMB_SET_FILE_BASIC_INFO.
4737 : ****************************************************************************/
4738 :
4739 2816 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4740 : const char *pdata,
4741 : int total_data,
4742 : files_struct *fsp,
4743 : struct smb_filename *smb_fname)
4744 : {
4745 : /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4746 31 : struct smb_file_time ft;
4747 2816 : uint32_t dosmode = 0;
4748 2816 : NTSTATUS status = NT_STATUS_OK;
4749 :
4750 2816 : init_smb_file_time(&ft);
4751 :
4752 2816 : if (total_data < 36) {
4753 0 : return NT_STATUS_INVALID_PARAMETER;
4754 : }
4755 :
4756 2816 : if (fsp == NULL) {
4757 0 : return NT_STATUS_INVALID_HANDLE;
4758 : }
4759 :
4760 2816 : status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4761 2816 : if (!NT_STATUS_IS_OK(status)) {
4762 4 : return status;
4763 : }
4764 :
4765 : /* Set the attributes */
4766 2812 : dosmode = IVAL(pdata,32);
4767 2812 : status = smb_set_file_dosmode(conn, fsp, dosmode);
4768 2812 : if (!NT_STATUS_IS_OK(status)) {
4769 5 : return status;
4770 : }
4771 :
4772 : /* create time */
4773 2807 : ft.create_time = pull_long_date_full_timespec(pdata);
4774 :
4775 : /* access time */
4776 2807 : ft.atime = pull_long_date_full_timespec(pdata+8);
4777 :
4778 : /* write time. */
4779 2807 : ft.mtime = pull_long_date_full_timespec(pdata+16);
4780 :
4781 : /* change time. */
4782 2807 : ft.ctime = pull_long_date_full_timespec(pdata+24);
4783 :
4784 2807 : DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4785 : smb_fname_str_dbg(smb_fname)));
4786 :
4787 2807 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4788 2807 : if (!NT_STATUS_IS_OK(status)) {
4789 0 : return status;
4790 : }
4791 :
4792 2807 : if (fsp->fsp_flags.modified) {
4793 1068 : trigger_write_time_update_immediate(fsp);
4794 : }
4795 2807 : return NT_STATUS_OK;
4796 : }
4797 :
4798 : /****************************************************************************
4799 : Deal with SMB_INFO_STANDARD.
4800 : ****************************************************************************/
4801 :
4802 8 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
4803 : const char *pdata,
4804 : int total_data,
4805 : files_struct *fsp,
4806 : struct smb_filename *smb_fname)
4807 : {
4808 0 : NTSTATUS status;
4809 0 : struct smb_file_time ft;
4810 :
4811 8 : init_smb_file_time(&ft);
4812 :
4813 8 : if (total_data < 12) {
4814 0 : return NT_STATUS_INVALID_PARAMETER;
4815 : }
4816 :
4817 8 : if (fsp == NULL) {
4818 0 : return NT_STATUS_INVALID_HANDLE;
4819 : }
4820 :
4821 : /* create time */
4822 8 : ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4823 : /* access time */
4824 8 : ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4825 : /* write time */
4826 8 : ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4827 :
4828 8 : DEBUG(10,("smb_set_info_standard: file %s\n",
4829 : smb_fname_str_dbg(smb_fname)));
4830 :
4831 8 : status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4832 8 : if (!NT_STATUS_IS_OK(status)) {
4833 4 : return status;
4834 : }
4835 :
4836 4 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4837 4 : if (!NT_STATUS_IS_OK(status)) {
4838 0 : return status;
4839 : }
4840 :
4841 4 : if (fsp->fsp_flags.modified) {
4842 0 : trigger_write_time_update_immediate(fsp);
4843 : }
4844 4 : return NT_STATUS_OK;
4845 : }
4846 :
4847 : /****************************************************************************
4848 : Deal with SMB_SET_FILE_ALLOCATION_INFO.
4849 : ****************************************************************************/
4850 :
4851 16 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4852 : struct smb_request *req,
4853 : const char *pdata,
4854 : int total_data,
4855 : files_struct *fsp,
4856 : struct smb_filename *smb_fname)
4857 : {
4858 16 : uint64_t allocation_size = 0;
4859 16 : NTSTATUS status = NT_STATUS_OK;
4860 16 : files_struct *new_fsp = NULL;
4861 :
4862 16 : if (!VALID_STAT(smb_fname->st)) {
4863 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4864 : }
4865 :
4866 16 : if (total_data < 8) {
4867 0 : return NT_STATUS_INVALID_PARAMETER;
4868 : }
4869 :
4870 16 : allocation_size = (uint64_t)IVAL(pdata,0);
4871 16 : allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4872 16 : DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4873 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4874 : (double)allocation_size));
4875 :
4876 16 : if (allocation_size) {
4877 6 : allocation_size = smb_roundup(conn, allocation_size);
4878 : }
4879 :
4880 16 : DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4881 : "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4882 : (double)allocation_size));
4883 :
4884 16 : if (fsp &&
4885 20 : !fsp->fsp_flags.is_pathref &&
4886 4 : fsp_get_io_fd(fsp) != -1)
4887 : {
4888 : /* Open file handle. */
4889 4 : if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4890 0 : return NT_STATUS_ACCESS_DENIED;
4891 : }
4892 :
4893 : /* Only change if needed. */
4894 4 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4895 4 : if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4896 0 : return map_nt_error_from_unix(errno);
4897 : }
4898 : }
4899 : /* But always update the time. */
4900 : /*
4901 : * This is equivalent to a write. Ensure it's seen immediately
4902 : * if there are no pending writes.
4903 : */
4904 4 : trigger_write_time_update_immediate(fsp);
4905 4 : return NT_STATUS_OK;
4906 : }
4907 :
4908 : /* Pathname or stat or directory file. */
4909 12 : status = SMB_VFS_CREATE_FILE(
4910 : conn, /* conn */
4911 : req, /* req */
4912 : NULL, /* dirfsp */
4913 : smb_fname, /* fname */
4914 : FILE_WRITE_DATA, /* access_mask */
4915 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4916 : FILE_SHARE_DELETE),
4917 : FILE_OPEN, /* create_disposition*/
4918 : 0, /* create_options */
4919 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4920 : 0, /* oplock_request */
4921 : NULL, /* lease */
4922 : 0, /* allocation_size */
4923 : 0, /* private_flags */
4924 : NULL, /* sd */
4925 : NULL, /* ea_list */
4926 : &new_fsp, /* result */
4927 : NULL, /* pinfo */
4928 : NULL, NULL); /* create context */
4929 :
4930 12 : if (!NT_STATUS_IS_OK(status)) {
4931 : /* NB. We check for open_was_deferred in the caller. */
4932 10 : return status;
4933 : }
4934 :
4935 : /* Only change if needed. */
4936 2 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4937 2 : if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4938 0 : status = map_nt_error_from_unix(errno);
4939 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4940 0 : return status;
4941 : }
4942 : }
4943 :
4944 : /* Changing the allocation size should set the last mod time. */
4945 : /*
4946 : * This is equivalent to a write. Ensure it's seen immediately
4947 : * if there are no pending writes.
4948 : */
4949 2 : trigger_write_time_update_immediate(new_fsp);
4950 2 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4951 2 : return NT_STATUS_OK;
4952 : }
4953 :
4954 : /****************************************************************************
4955 : Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4956 : ****************************************************************************/
4957 :
4958 331 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4959 : struct smb_request *req,
4960 : const char *pdata,
4961 : int total_data,
4962 : files_struct *fsp,
4963 : struct smb_filename *smb_fname,
4964 : bool fail_after_createfile)
4965 : {
4966 1 : off_t size;
4967 :
4968 331 : if (total_data < 8) {
4969 0 : return NT_STATUS_INVALID_PARAMETER;
4970 : }
4971 :
4972 331 : size = IVAL(pdata,0);
4973 331 : size |= (((off_t)IVAL(pdata,4)) << 32);
4974 331 : DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4975 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4976 : (double)size));
4977 :
4978 331 : return smb_set_file_size(conn, req,
4979 : fsp,
4980 : smb_fname,
4981 331 : &smb_fname->st,
4982 : size,
4983 : fail_after_createfile);
4984 : }
4985 :
4986 10826 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
4987 : struct smb_request *req,
4988 : TALLOC_CTX *mem_ctx,
4989 : uint16_t info_level,
4990 : files_struct *fsp,
4991 : struct smb_filename *smb_fname,
4992 : char **ppdata, int total_data,
4993 : int *ret_data_size)
4994 : {
4995 10826 : char *pdata = *ppdata;
4996 10826 : NTSTATUS status = NT_STATUS_OK;
4997 10826 : int data_return_size = 0;
4998 :
4999 10826 : *ret_data_size = 0;
5000 :
5001 10826 : DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5002 : "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5003 : fsp_fnum_dbg(fsp),
5004 : info_level, total_data));
5005 :
5006 10826 : switch (info_level) {
5007 :
5008 8 : case SMB_INFO_STANDARD:
5009 : {
5010 8 : status = smb_set_info_standard(conn,
5011 : pdata,
5012 : total_data,
5013 : fsp,
5014 : smb_fname);
5015 8 : break;
5016 : }
5017 :
5018 2931 : case SMB_INFO_SET_EA:
5019 : {
5020 2931 : status = smb_info_set_ea(conn,
5021 : pdata,
5022 : total_data,
5023 : fsp,
5024 : smb_fname);
5025 2931 : break;
5026 : }
5027 :
5028 2816 : case SMB_SET_FILE_BASIC_INFO:
5029 : case SMB_FILE_BASIC_INFORMATION:
5030 : {
5031 2816 : status = smb_set_file_basic_info(conn,
5032 : pdata,
5033 : total_data,
5034 : fsp,
5035 : smb_fname);
5036 2816 : break;
5037 : }
5038 :
5039 16 : case SMB_FILE_ALLOCATION_INFORMATION:
5040 : case SMB_SET_FILE_ALLOCATION_INFO:
5041 : {
5042 16 : status = smb_set_file_allocation_info(conn, req,
5043 : pdata,
5044 : total_data,
5045 : fsp,
5046 : smb_fname);
5047 16 : break;
5048 : }
5049 :
5050 331 : case SMB_FILE_END_OF_FILE_INFORMATION:
5051 : case SMB_SET_FILE_END_OF_FILE_INFO:
5052 : {
5053 : /*
5054 : * XP/Win7 both fail after the createfile with
5055 : * SMB_SET_FILE_END_OF_FILE_INFO but not
5056 : * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5057 : * The level is known here, so pass it down
5058 : * appropriately.
5059 : */
5060 331 : bool should_fail =
5061 : (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5062 :
5063 331 : status = smb_set_file_end_of_file_info(conn, req,
5064 : pdata,
5065 : total_data,
5066 : fsp,
5067 : smb_fname,
5068 : should_fail);
5069 331 : break;
5070 : }
5071 :
5072 3638 : case SMB_FILE_DISPOSITION_INFORMATION:
5073 : case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5074 : {
5075 : #if 0
5076 : /* JRA - We used to just ignore this on a path ?
5077 : * Shouldn't this be invalid level on a pathname
5078 : * based call ?
5079 : */
5080 : if (tran_call != TRANSACT2_SETFILEINFO) {
5081 : return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5082 : }
5083 : #endif
5084 3638 : status = smb_set_file_disposition_info(conn,
5085 : pdata,
5086 : total_data,
5087 : fsp,
5088 : smb_fname);
5089 3638 : break;
5090 : }
5091 :
5092 94 : case SMB_FILE_POSITION_INFORMATION:
5093 : {
5094 94 : status = smb_file_position_information(conn,
5095 : pdata,
5096 : total_data,
5097 : fsp);
5098 94 : break;
5099 : }
5100 :
5101 12 : case SMB_FILE_FULL_EA_INFORMATION:
5102 : {
5103 12 : status = smb_set_file_full_ea_info(conn,
5104 : pdata,
5105 : total_data,
5106 : fsp);
5107 12 : break;
5108 : }
5109 :
5110 : /* From tridge Samba4 :
5111 : * MODE_INFORMATION in setfileinfo (I have no
5112 : * idea what "mode information" on a file is - it takes a value of 0,
5113 : * 2, 4 or 6. What could it be?).
5114 : */
5115 :
5116 8 : case SMB_FILE_MODE_INFORMATION:
5117 : {
5118 8 : status = smb_file_mode_information(conn,
5119 : pdata,
5120 : total_data);
5121 8 : break;
5122 : }
5123 :
5124 : /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5125 8 : case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5126 : case SMB_FILE_SHORT_NAME_INFORMATION:
5127 16 : return NT_STATUS_NOT_SUPPORTED;
5128 :
5129 139 : case SMB_FILE_RENAME_INFORMATION:
5130 : {
5131 139 : status = smb_file_rename_information(conn, req,
5132 : pdata, total_data,
5133 : fsp, smb_fname);
5134 139 : break;
5135 : }
5136 :
5137 791 : case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5138 : {
5139 : /* SMB2 rename information. */
5140 791 : status = smb2_file_rename_information(conn, req,
5141 : pdata, total_data,
5142 : fsp, smb_fname);
5143 791 : break;
5144 : }
5145 :
5146 26 : case SMB_FILE_LINK_INFORMATION:
5147 : {
5148 26 : if (conn->sconn->using_smb2) {
5149 18 : status = smb2_file_link_information(conn,
5150 : req,
5151 : pdata,
5152 : total_data,
5153 : fsp,
5154 : smb_fname);
5155 : } else {
5156 8 : status = smb_file_link_information(conn,
5157 : req,
5158 : pdata,
5159 : total_data,
5160 : fsp,
5161 : smb_fname);
5162 : }
5163 26 : break;
5164 : }
5165 :
5166 8 : default:
5167 8 : return NT_STATUS_INVALID_LEVEL;
5168 : }
5169 :
5170 10810 : if (!NT_STATUS_IS_OK(status)) {
5171 663 : return status;
5172 : }
5173 :
5174 10147 : *ret_data_size = data_return_size;
5175 10147 : return NT_STATUS_OK;
5176 : }
5177 :
5178 130 : static uint32_t generate_volume_serial_number(
5179 : const struct loadparm_substitution *lp_sub,
5180 : int snum)
5181 : {
5182 130 : int serial = lp_volume_serial_number(snum);
5183 258 : return serial != -1 ? serial:
5184 128 : str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5185 128 : (str_checksum(get_local_machine_name())<<16);
5186 : }
|