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