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