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