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 799248 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
63 : {
64 :
65 799248 : if (!VALID_STAT(fsp->fsp_name->st)) {
66 0 : return NT_STATUS_ACCESS_DENIED;
67 : }
68 799248 : if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
69 108 : return NT_STATUS_ACCESS_DENIED;
70 : }
71 799140 : if (fsp_get_pathref_fd(fsp) == -1) {
72 172 : return NT_STATUS_ACCESS_DENIED;
73 : }
74 798968 : 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 430519 : NTSTATUS check_any_access_fsp(struct files_struct *fsp,
83 : uint32_t access_requested)
84 : {
85 430519 : const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
86 430519 : uint32_t ro_access_granted = 0;
87 430519 : uint32_t access_granted = 0;
88 1177 : NTSTATUS status;
89 :
90 430519 : if (fsp->fsp_flags.is_fsa) {
91 293284 : 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 430519 : if ((access_granted & access_requested) == 0) {
120 623 : return NT_STATUS_ACCESS_DENIED;
121 : }
122 :
123 429896 : if (fsp->fsp_name->twrp == 0) {
124 427893 : 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 1733946 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
141 : {
142 1733946 : uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
143 :
144 : /* Only roundup for Windows clients. */
145 1733946 : enum remote_arch_types ra_type = get_remote_arch();
146 1733946 : if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
147 0 : val = SMB_ROUNDUP(val,rval);
148 : }
149 1733946 : 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 724301 : bool samba_private_attr_name(const char *unix_ea_name)
161 : {
162 724301 : bool prohibited = false;
163 :
164 724301 : prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
165 724301 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
166 724301 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
167 724301 : prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
168 724301 : prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
169 :
170 724301 : if (prohibited) {
171 711134 : 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 15137 : 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 15137 : size_t attr_size = 256;
192 15137 : char *val = NULL;
193 575 : ssize_t sizeret;
194 15137 : size_t max_xattr_size = 0;
195 575 : NTSTATUS status;
196 :
197 15137 : if (fsp == NULL) {
198 0 : return NT_STATUS_INVALID_HANDLE;
199 : }
200 15137 : status = refuse_symlink_fsp(fsp);
201 15137 : if (!NT_STATUS_IS_OK(status)) {
202 0 : return status;
203 : }
204 :
205 15137 : max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
206 :
207 15251 : again:
208 :
209 15251 : val = talloc_realloc(mem_ctx, val, char, attr_size);
210 15251 : if (!val) {
211 0 : return NT_STATUS_NO_MEMORY;
212 : }
213 :
214 15251 : sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
215 15251 : if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
216 114 : attr_size = max_xattr_size;
217 114 : goto again;
218 : }
219 :
220 15137 : if (sizeret == -1) {
221 2608 : 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 42840 : TALLOC_FREE(to_free);
298 42840 : return NT_STATUS_OK;
299 : }
300 :
301 : /*
302 : * Ensure the result is 0-terminated
303 : */
304 :
305 709316 : 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 708286 : num_names = 0;
314 :
315 4165878 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
316 3456562 : num_names += 1;
317 : }
318 :
319 709316 : *pnum_names = num_names;
320 :
321 709316 : if (pnames == NULL) {
322 1260 : TALLOC_FREE(to_free);
323 1260 : return NT_STATUS_OK;
324 : }
325 :
326 708056 : names = talloc_array(mem_ctx, char *, num_names);
327 708056 : 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 708056 : if (ea_namelist == smallbuf) {
334 708056 : ea_namelist = talloc_memdup(names, smallbuf, sizeret);
335 708056 : 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 708056 : num_names = 0;
351 :
352 4157974 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
353 3449918 : names[num_names++] = p;
354 : }
355 :
356 708056 : *pnames = names;
357 :
358 708056 : 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 43085 : return NT_STATUS_OK;
406 : }
407 :
408 4137304 : 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 3435234 : if (!strnequal(names[i], "user.", 5)
425 706748 : || samba_private_attr_name(names[i]))
426 3429120 : 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 702070 : if (*pea_total_len) {
487 3902 : *pea_total_len += 4;
488 : }
489 :
490 702070 : DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
491 : (unsigned int)*pea_total_len));
492 :
493 702070 : *ea_list = ea_list_head;
494 702070 : 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(fsp->conn->sconn->using_smb2) {
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 910524 : 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 910524 : 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 910524 : 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 910103 : fname = dname;
1021 : }
1022 :
1023 910799 : got_match = mask_match(fname, mask,
1024 910484 : state->case_sensitive);
1025 :
1026 910484 : if(!got_match && state->check_mangled_names &&
1027 6006 : !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 3527 : ok = name_to_8_3(fname, mangled_name,
1036 3527 : false, state->conn->params);
1037 3527 : if (!ok) {
1038 0 : return false;
1039 : }
1040 :
1041 3527 : got_match = mask_match(mangled_name, mask,
1042 3527 : state->case_sensitive);
1043 : }
1044 :
1045 910484 : if (!got_match) {
1046 6002 : 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 644348 : 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->sconn->using_smb2)) {
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->sconn->using_smb2 &&
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 3429 : 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 3429 : loadparm_s3_global_substitution();
2025 0 : char *pdata, *end_data;
2026 3429 : int data_len = 0;
2027 3429 : size_t len = 0;
2028 3429 : const char *vname = volume_label(talloc_tos(), SNUM(conn));
2029 3429 : int snum = SNUM(conn);
2030 3429 : const char *fstype = lp_fstype(SNUM(conn));
2031 3429 : const char *filename = NULL;
2032 3429 : const uint64_t bytes_per_sector = 512;
2033 3429 : uint32_t additional_flags = 0;
2034 0 : struct smb_filename smb_fname;
2035 0 : SMB_STRUCT_STAT st;
2036 3429 : NTSTATUS status = NT_STATUS_OK;
2037 0 : uint64_t df_ret;
2038 0 : uint32_t serial;
2039 :
2040 3429 : if (fname == NULL || fname->base_name == NULL) {
2041 1377 : filename = ".";
2042 : } else {
2043 2052 : filename = fname->base_name;
2044 : }
2045 :
2046 3429 : if (IS_IPC(conn)) {
2047 242 : 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 3429 : DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2056 :
2057 3429 : smb_fname = (struct smb_filename) {
2058 : .base_name = discard_const_p(char, filename),
2059 3429 : .flags = fname ? fname->flags : 0,
2060 3429 : .twrp = fname ? fname->twrp : 0,
2061 : };
2062 :
2063 3429 : if(info_level != SMB_FS_QUOTA_INFORMATION
2064 3425 : && 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 3429 : st = smb_fname.st;
2070 :
2071 3429 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2072 0 : return NT_STATUS_INVALID_PARAMETER;
2073 : }
2074 :
2075 3429 : *ppdata = (char *)SMB_REALLOC(
2076 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2077 3429 : if (*ppdata == NULL) {
2078 0 : return NT_STATUS_NO_MEMORY;
2079 : }
2080 :
2081 3429 : pdata = *ppdata;
2082 3429 : memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2083 3429 : end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2084 :
2085 3429 : *fixed_portion = 0;
2086 :
2087 3429 : 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 966 : case SMB_QUERY_CIFS_UNIX_INFO:
2461 : {
2462 966 : bool large_write = lp_min_receive_file_size() &&
2463 0 : !smb1_srv_is_signing_active(xconn);
2464 966 : bool large_read = !smb1_srv_is_signing_active(xconn);
2465 966 : int encrypt_caps = 0;
2466 :
2467 966 : if (!lp_smb1_unix_extensions()) {
2468 0 : return NT_STATUS_INVALID_LEVEL;
2469 : }
2470 :
2471 966 : switch (conn->encrypt_level) {
2472 0 : case SMB_SIGNING_OFF:
2473 0 : encrypt_caps = 0;
2474 0 : break;
2475 800 : case SMB_SIGNING_DESIRED:
2476 : case SMB_SIGNING_IF_REQUIRED:
2477 : case SMB_SIGNING_DEFAULT:
2478 800 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2479 800 : break;
2480 166 : case SMB_SIGNING_REQUIRED:
2481 166 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2482 : CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2483 166 : large_write = false;
2484 166 : large_read = false;
2485 166 : break;
2486 : }
2487 :
2488 966 : data_len = 12;
2489 966 : SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2490 966 : SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2491 :
2492 : /* We have POSIX ACLs, pathname, encryption,
2493 : * large read/write, and locking capability. */
2494 :
2495 966 : 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 966 : 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 332 : i < conn->session_info->security_token->num_sids; ++i) {
2608 304 : sid_bytes += ndr_size_dom_sid(
2609 304 : &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 250 : for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2622 222 : SBIG_UINT(pdata, data_len,
2623 : (uint64_t)conn->session_info->unix_token->groups[i]);
2624 222 : data_len += 8;
2625 : }
2626 :
2627 : /* SID list */
2628 28 : for (i = 0;
2629 332 : i < conn->session_info->security_token->num_sids; ++i) {
2630 608 : int sid_len = ndr_size_dom_sid(
2631 304 : &conn->session_info->security_token->sids[i],
2632 : 0);
2633 :
2634 304 : sid_linearize((uint8_t *)(pdata + data_len),
2635 : sid_len,
2636 304 : &conn->session_info->security_token->sids[i]);
2637 304 : 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 3425 : *ret_data_len = data_len;
2660 3425 : 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->sconn->using_smb2 &&
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 || !fsp->conn->sconn->using_smb2) {
3411 8 : return NT_STATUS_INVALID_LEVEL;
3412 : }
3413 :
3414 96 : nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3415 96 : if (nfname == NULL) {
3416 0 : return NT_STATUS_NO_MEMORY;
3417 : }
3418 :
3419 96 : if (ISDOT(nfname)) {
3420 4 : nfname[0] = '\0';
3421 : }
3422 96 : string_replace(nfname, '/', '\\');
3423 :
3424 96 : if (fsp_is_alternate_stream(fsp)) {
3425 32 : const char *s = smb_fname->stream_name;
3426 32 : const char *e = NULL;
3427 0 : size_t n;
3428 :
3429 32 : SMB_ASSERT(s[0] != '\0');
3430 :
3431 : /*
3432 : * smb_fname->stream_name is in form
3433 : * of ':StrEam:$DATA', but we should only
3434 : * append ':StrEam' here.
3435 : */
3436 :
3437 32 : e = strchr(&s[1], ':');
3438 32 : if (e == NULL) {
3439 8 : n = strlen(s);
3440 : } else {
3441 24 : n = PTR_DIFF(e, s);
3442 : }
3443 32 : nfname = talloc_strndup_append(nfname, s, n);
3444 32 : if (nfname == NULL) {
3445 0 : return NT_STATUS_NO_MEMORY;
3446 : }
3447 : }
3448 :
3449 96 : status = srvstr_push(dstart, flags2,
3450 : pdata+4, nfname,
3451 : PTR_DIFF(dend, pdata+4),
3452 : STR_UNICODE, &len);
3453 96 : if (!NT_STATUS_IS_OK(status)) {
3454 0 : return status;
3455 : }
3456 96 : DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3457 96 : data_size = 4 + len;
3458 96 : SIVAL(pdata,0,len);
3459 96 : *fixed_portion = 8;
3460 96 : break;
3461 : }
3462 :
3463 8 : case SMB_FILE_ALLOCATION_INFORMATION:
3464 : case SMB_QUERY_FILE_ALLOCATION_INFO:
3465 8 : DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3466 8 : data_size = 8;
3467 8 : SOFF_T(pdata,0,allocation_size);
3468 8 : break;
3469 :
3470 8 : case SMB_FILE_END_OF_FILE_INFORMATION:
3471 : case SMB_QUERY_FILE_END_OF_FILEINFO:
3472 8 : DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3473 8 : data_size = 8;
3474 8 : SOFF_T(pdata,0,file_size);
3475 8 : break;
3476 :
3477 1990 : case SMB_QUERY_FILE_ALL_INFO:
3478 : case SMB_FILE_ALL_INFORMATION:
3479 : {
3480 252 : unsigned int ea_size =
3481 1990 : estimate_ea_size(smb_fname->fsp);
3482 1990 : DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3483 1990 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3484 1990 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3485 1990 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3486 1990 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3487 1990 : SIVAL(pdata,32,mode);
3488 1990 : SIVAL(pdata,36,0); /* padding. */
3489 1990 : pdata += 40;
3490 1990 : SOFF_T(pdata,0,allocation_size);
3491 1990 : SOFF_T(pdata,8,file_size);
3492 1990 : SIVAL(pdata,16,nlink);
3493 1990 : SCVAL(pdata,20,delete_pending);
3494 1990 : SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3495 1990 : SSVAL(pdata,22,0);
3496 1990 : pdata += 24;
3497 1990 : SIVAL(pdata,0,ea_size);
3498 1990 : pdata += 4; /* EA info */
3499 1990 : status = srvstr_push(dstart, flags2,
3500 : pdata+4, dos_fname,
3501 : PTR_DIFF(dend, pdata+4),
3502 : STR_UNICODE, &len);
3503 1990 : if (!NT_STATUS_IS_OK(status)) {
3504 0 : return status;
3505 : }
3506 1990 : SIVAL(pdata,0,len);
3507 1990 : pdata += 4 + len;
3508 1990 : data_size = PTR_DIFF(pdata,(*ppdata));
3509 1990 : *fixed_portion = 10;
3510 1990 : break;
3511 : }
3512 :
3513 6018 : case SMB2_FILE_ALL_INFORMATION:
3514 : {
3515 0 : unsigned int ea_size =
3516 6018 : estimate_ea_size(smb_fname->fsp);
3517 6018 : DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3518 6018 : put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3519 6018 : put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3520 6018 : put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3521 6018 : put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3522 6018 : SIVAL(pdata, 0x20, mode);
3523 6018 : SIVAL(pdata, 0x24, 0); /* padding. */
3524 6018 : SBVAL(pdata, 0x28, allocation_size);
3525 6018 : SBVAL(pdata, 0x30, file_size);
3526 6018 : SIVAL(pdata, 0x38, nlink);
3527 6018 : SCVAL(pdata, 0x3C, delete_pending);
3528 6018 : SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3529 6018 : SSVAL(pdata, 0x3E, 0); /* padding */
3530 6018 : SBVAL(pdata, 0x40, file_id);
3531 6018 : SIVAL(pdata, 0x48, ea_size);
3532 6018 : SIVAL(pdata, 0x4C, access_mask);
3533 6018 : SBVAL(pdata, 0x50, pos);
3534 6018 : SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3535 6018 : SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3536 :
3537 6018 : pdata += 0x60;
3538 :
3539 6018 : status = srvstr_push(dstart, flags2,
3540 : pdata+4, dos_fname,
3541 : PTR_DIFF(dend, pdata+4),
3542 : STR_UNICODE, &len);
3543 6018 : if (!NT_STATUS_IS_OK(status)) {
3544 0 : return status;
3545 : }
3546 6018 : SIVAL(pdata,0,len);
3547 6018 : pdata += 4 + len;
3548 6018 : data_size = PTR_DIFF(pdata,(*ppdata));
3549 6018 : *fixed_portion = 104;
3550 6018 : break;
3551 : }
3552 62 : case SMB_FILE_INTERNAL_INFORMATION:
3553 :
3554 62 : DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3555 62 : SBVAL(pdata, 0, file_id);
3556 62 : data_size = 8;
3557 62 : *fixed_portion = 8;
3558 62 : break;
3559 :
3560 1073 : case SMB_FILE_ACCESS_INFORMATION:
3561 1073 : DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3562 1073 : SIVAL(pdata, 0, access_mask);
3563 1073 : data_size = 4;
3564 1073 : *fixed_portion = 4;
3565 1073 : break;
3566 :
3567 8 : case SMB_FILE_NAME_INFORMATION:
3568 : /* Pathname with leading '\'. */
3569 : {
3570 0 : size_t byte_len;
3571 8 : byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3572 8 : DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3573 8 : SIVAL(pdata,0,byte_len);
3574 8 : data_size = 4 + byte_len;
3575 8 : break;
3576 : }
3577 :
3578 8 : case SMB_FILE_DISPOSITION_INFORMATION:
3579 8 : DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3580 8 : data_size = 1;
3581 8 : SCVAL(pdata,0,delete_pending);
3582 8 : *fixed_portion = 1;
3583 8 : break;
3584 :
3585 2103 : case SMB_FILE_POSITION_INFORMATION:
3586 2103 : DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3587 2103 : data_size = 8;
3588 2103 : SOFF_T(pdata,0,pos);
3589 2103 : *fixed_portion = 8;
3590 2103 : break;
3591 :
3592 40 : case SMB_FILE_MODE_INFORMATION:
3593 40 : DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3594 40 : SIVAL(pdata,0,mode);
3595 40 : data_size = 4;
3596 40 : *fixed_portion = 4;
3597 40 : break;
3598 :
3599 40 : case SMB_FILE_ALIGNMENT_INFORMATION:
3600 40 : DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3601 40 : SIVAL(pdata,0,0); /* No alignment needed. */
3602 40 : data_size = 4;
3603 40 : *fixed_portion = 4;
3604 40 : break;
3605 :
3606 : /*
3607 : * NT4 server just returns "invalid query" to this - if we try
3608 : * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3609 : * want this. JRA.
3610 : */
3611 : /* The first statement above is false - verified using Thursby
3612 : * client against NT4 -- gcolley.
3613 : */
3614 3839 : case SMB_QUERY_FILE_STREAM_INFO:
3615 : case SMB_FILE_STREAM_INFORMATION: {
3616 3839 : unsigned int num_streams = 0;
3617 3839 : struct stream_struct *streams = NULL;
3618 :
3619 3839 : DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3620 :
3621 3839 : if (is_ntfs_stream_smb_fname(smb_fname)) {
3622 64 : return NT_STATUS_INVALID_PARAMETER;
3623 : }
3624 :
3625 3775 : status = vfs_fstreaminfo(fsp,
3626 : mem_ctx,
3627 : &num_streams,
3628 : &streams);
3629 :
3630 3775 : if (!NT_STATUS_IS_OK(status)) {
3631 0 : DBG_DEBUG("could not get stream info: %s\n",
3632 : nt_errstr(status));
3633 0 : return status;
3634 : }
3635 :
3636 3775 : status = marshall_stream_info(num_streams, streams,
3637 : pdata, max_data_bytes,
3638 : &data_size);
3639 :
3640 3775 : if (!NT_STATUS_IS_OK(status)) {
3641 152 : DBG_DEBUG("marshall_stream_info failed: %s\n",
3642 : nt_errstr(status));
3643 152 : TALLOC_FREE(streams);
3644 152 : return status;
3645 : }
3646 :
3647 3623 : TALLOC_FREE(streams);
3648 :
3649 3623 : *fixed_portion = 32;
3650 :
3651 3623 : break;
3652 : }
3653 88 : case SMB_QUERY_COMPRESSION_INFO:
3654 : case SMB_FILE_COMPRESSION_INFORMATION:
3655 88 : DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3656 88 : SOFF_T(pdata,0,file_size);
3657 88 : SIVAL(pdata,8,0); /* ??? */
3658 88 : SIVAL(pdata,12,0); /* ??? */
3659 88 : data_size = 16;
3660 88 : *fixed_portion = 16;
3661 88 : break;
3662 :
3663 244 : case SMB_FILE_NETWORK_OPEN_INFORMATION:
3664 244 : DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3665 244 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3666 244 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3667 244 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3668 244 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3669 244 : SOFF_T(pdata,32,allocation_size);
3670 244 : SOFF_T(pdata,40,file_size);
3671 244 : SIVAL(pdata,48,mode);
3672 244 : SIVAL(pdata,52,0); /* ??? */
3673 244 : data_size = 56;
3674 244 : *fixed_portion = 56;
3675 244 : break;
3676 :
3677 52 : case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3678 52 : DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3679 52 : SIVAL(pdata,0,mode);
3680 52 : SIVAL(pdata,4,0);
3681 52 : data_size = 8;
3682 52 : *fixed_portion = 8;
3683 52 : break;
3684 :
3685 : /*
3686 : * SMB2 UNIX Extensions.
3687 : */
3688 0 : case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3689 : {
3690 0 : struct smb3_file_posix_information info = {};
3691 0 : uint8_t buf[sizeof(info)];
3692 0 : struct ndr_push ndr = {
3693 : .data = buf,
3694 : .alloc_size = sizeof(buf),
3695 : .fixed_buf_size = true,
3696 : };
3697 0 : enum ndr_err_code ndr_err;
3698 :
3699 0 : if (!(conn->sconn->using_smb2)) {
3700 0 : return NT_STATUS_INVALID_LEVEL;
3701 : }
3702 0 : if (fsp == NULL) {
3703 0 : return NT_STATUS_INVALID_HANDLE;
3704 : }
3705 0 : if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3706 0 : return NT_STATUS_INVALID_LEVEL;
3707 : }
3708 :
3709 0 : smb3_file_posix_information_init(
3710 0 : conn, &smb_fname->st, 0, mode, &info);
3711 :
3712 0 : ndr_err = ndr_push_smb3_file_posix_information(
3713 : &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3714 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3715 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
3716 : }
3717 :
3718 0 : memcpy(pdata, buf, ndr.offset);
3719 0 : data_size = ndr.offset;
3720 0 : break;
3721 : }
3722 :
3723 8 : default:
3724 8 : return NT_STATUS_INVALID_LEVEL;
3725 : }
3726 :
3727 25730 : *pdata_size = data_size;
3728 25730 : return NT_STATUS_OK;
3729 : }
3730 :
3731 : /****************************************************************************
3732 : Set a hard link (called by UNIX extensions and by NT rename with HARD link
3733 : code.
3734 : ****************************************************************************/
3735 :
3736 52 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3737 : connection_struct *conn,
3738 : struct smb_request *req,
3739 : bool overwrite_if_exists,
3740 : const struct smb_filename *smb_fname_old,
3741 : struct smb_filename *smb_fname_new)
3742 : {
3743 52 : NTSTATUS status = NT_STATUS_OK;
3744 1 : int ret;
3745 1 : bool ok;
3746 52 : struct smb_filename *parent_fname_old = NULL;
3747 52 : struct smb_filename *base_name_old = NULL;
3748 52 : struct smb_filename *parent_fname_new = NULL;
3749 52 : struct smb_filename *base_name_new = NULL;
3750 :
3751 : /* source must already exist. */
3752 52 : if (!VALID_STAT(smb_fname_old->st)) {
3753 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3754 0 : goto out;
3755 : }
3756 :
3757 : /* No links from a directory. */
3758 52 : if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3759 8 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3760 8 : goto out;
3761 : }
3762 :
3763 : /* Setting a hardlink to/from a stream isn't currently supported. */
3764 44 : ok = is_ntfs_stream_smb_fname(smb_fname_old);
3765 44 : if (ok) {
3766 0 : DBG_DEBUG("Old name has streams\n");
3767 0 : status = NT_STATUS_INVALID_PARAMETER;
3768 0 : goto out;
3769 : }
3770 44 : ok = is_ntfs_stream_smb_fname(smb_fname_new);
3771 44 : if (ok) {
3772 0 : DBG_DEBUG("New name has streams\n");
3773 0 : status = NT_STATUS_INVALID_PARAMETER;
3774 0 : goto out;
3775 : }
3776 :
3777 44 : if (smb_fname_old->twrp != 0) {
3778 1 : status = NT_STATUS_NOT_SAME_DEVICE;
3779 1 : goto out;
3780 : }
3781 :
3782 43 : status = parent_pathref(talloc_tos(),
3783 : conn->cwd_fsp,
3784 : smb_fname_old,
3785 : &parent_fname_old,
3786 : &base_name_old);
3787 43 : if (!NT_STATUS_IS_OK(status)) {
3788 0 : goto out;
3789 : }
3790 :
3791 43 : status = parent_pathref(talloc_tos(),
3792 : conn->cwd_fsp,
3793 : smb_fname_new,
3794 : &parent_fname_new,
3795 : &base_name_new);
3796 43 : if (!NT_STATUS_IS_OK(status)) {
3797 0 : goto out;
3798 : }
3799 :
3800 43 : if (VALID_STAT(smb_fname_new->st)) {
3801 0 : if (overwrite_if_exists) {
3802 0 : if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3803 0 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3804 0 : goto out;
3805 : }
3806 0 : status = unlink_internals(conn,
3807 : req,
3808 : FILE_ATTRIBUTE_NORMAL,
3809 : NULL, /* new_dirfsp */
3810 : smb_fname_new);
3811 0 : if (!NT_STATUS_IS_OK(status)) {
3812 0 : goto out;
3813 : }
3814 : } else {
3815 : /* Disallow if newname already exists. */
3816 0 : status = NT_STATUS_OBJECT_NAME_COLLISION;
3817 0 : goto out;
3818 : }
3819 : }
3820 :
3821 43 : DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3822 : smb_fname_old->base_name, smb_fname_new->base_name));
3823 :
3824 43 : ret = SMB_VFS_LINKAT(conn,
3825 : parent_fname_old->fsp,
3826 : base_name_old,
3827 : parent_fname_new->fsp,
3828 : base_name_new,
3829 : 0);
3830 :
3831 43 : if (ret != 0) {
3832 0 : status = map_nt_error_from_unix(errno);
3833 0 : DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3834 : nt_errstr(status), smb_fname_old->base_name,
3835 : smb_fname_new->base_name));
3836 : }
3837 :
3838 43 : out:
3839 :
3840 52 : TALLOC_FREE(parent_fname_old);
3841 52 : TALLOC_FREE(parent_fname_new);
3842 52 : return status;
3843 : }
3844 :
3845 : /****************************************************************************
3846 : Deal with setting the time from any of the setfilepathinfo functions.
3847 : NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3848 : calling this function.
3849 : ****************************************************************************/
3850 :
3851 11060 : NTSTATUS smb_set_file_time(connection_struct *conn,
3852 : files_struct *fsp,
3853 : struct smb_filename *smb_fname,
3854 : struct smb_file_time *ft,
3855 : bool setting_write_time)
3856 : {
3857 11060 : struct files_struct *set_fsp = NULL;
3858 115 : struct timeval_buf tbuf[4];
3859 11060 : uint32_t action =
3860 : FILE_NOTIFY_CHANGE_LAST_ACCESS
3861 : |FILE_NOTIFY_CHANGE_LAST_WRITE
3862 : |FILE_NOTIFY_CHANGE_CREATION;
3863 115 : int ret;
3864 :
3865 11060 : if (!VALID_STAT(smb_fname->st)) {
3866 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3867 : }
3868 :
3869 11060 : if (fsp == NULL) {
3870 : /* A symlink */
3871 0 : return NT_STATUS_OK;
3872 : }
3873 :
3874 11060 : set_fsp = metadata_fsp(fsp);
3875 :
3876 : /* get some defaults (no modifications) if any info is zero or -1. */
3877 11060 : if (is_omit_timespec(&ft->create_time)) {
3878 10216 : action &= ~FILE_NOTIFY_CHANGE_CREATION;
3879 : }
3880 :
3881 11060 : if (is_omit_timespec(&ft->atime)) {
3882 10161 : action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3883 : }
3884 :
3885 11060 : if (is_omit_timespec(&ft->mtime)) {
3886 3118 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3887 : }
3888 :
3889 11060 : if (!setting_write_time) {
3890 : /* ft->mtime comes from change time, not write time. */
3891 6729 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3892 : }
3893 :
3894 : /* Ensure the resolution is the correct for
3895 : * what we can store on this filesystem. */
3896 :
3897 11060 : round_timespec(conn->ts_res, &ft->create_time);
3898 11060 : round_timespec(conn->ts_res, &ft->ctime);
3899 11060 : round_timespec(conn->ts_res, &ft->atime);
3900 11060 : round_timespec(conn->ts_res, &ft->mtime);
3901 :
3902 11060 : DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3903 : timespec_string_buf(&ft->atime, true, &tbuf[0]));
3904 11060 : DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3905 : timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3906 11060 : DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3907 : timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3908 11060 : DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3909 : timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3910 :
3911 11060 : if (setting_write_time) {
3912 : /*
3913 : * This was a Windows setfileinfo on an open file.
3914 : * NT does this a lot. We also need to
3915 : * set the time here, as it can be read by
3916 : * FindFirst/FindNext and with the patch for bug #2045
3917 : * in smbd/fileio.c it ensures that this timestamp is
3918 : * kept sticky even after a write. We save the request
3919 : * away and will set it on file close and after a write. JRA.
3920 : */
3921 :
3922 4331 : DBG_DEBUG("setting pending modtime to %s\n",
3923 : timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3924 :
3925 4331 : if (set_fsp != NULL) {
3926 4331 : set_sticky_write_time_fsp(set_fsp, ft->mtime);
3927 : } else {
3928 0 : set_sticky_write_time_path(
3929 0 : vfs_file_id_from_sbuf(conn, &smb_fname->st),
3930 : ft->mtime);
3931 : }
3932 : }
3933 :
3934 11060 : DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3935 :
3936 11060 : ret = file_ntimes(conn, set_fsp, ft);
3937 11060 : if (ret != 0) {
3938 0 : return map_nt_error_from_unix(errno);
3939 : }
3940 :
3941 11060 : notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3942 11060 : smb_fname->base_name);
3943 11060 : return NT_STATUS_OK;
3944 : }
3945 :
3946 : /****************************************************************************
3947 : Deal with setting the dosmode from any of the setfilepathinfo functions.
3948 : NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3949 : done before calling this function.
3950 : ****************************************************************************/
3951 :
3952 2810 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3953 : struct files_struct *fsp,
3954 : uint32_t dosmode)
3955 : {
3956 2810 : struct files_struct *dos_fsp = NULL;
3957 31 : uint32_t current_dosmode;
3958 31 : int ret;
3959 :
3960 2810 : if (!VALID_STAT(fsp->fsp_name->st)) {
3961 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3962 : }
3963 :
3964 2810 : dos_fsp = metadata_fsp(fsp);
3965 :
3966 2810 : if (dosmode != 0) {
3967 1273 : if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3968 183 : dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3969 : } else {
3970 1090 : dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3971 : }
3972 : }
3973 :
3974 2810 : DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3975 :
3976 : /* check the mode isn't different, before changing it */
3977 2810 : if (dosmode == 0) {
3978 1537 : return NT_STATUS_OK;
3979 : }
3980 1273 : current_dosmode = fdos_mode(dos_fsp);
3981 1273 : if (dosmode == current_dosmode) {
3982 291 : return NT_STATUS_OK;
3983 : }
3984 :
3985 982 : DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3986 : fsp_str_dbg(dos_fsp), dosmode);
3987 :
3988 982 : ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3989 982 : if (ret != 0) {
3990 5 : DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3991 : fsp_str_dbg(dos_fsp), strerror(errno));
3992 5 : return map_nt_error_from_unix(errno);
3993 : }
3994 :
3995 977 : return NT_STATUS_OK;
3996 : }
3997 :
3998 : /****************************************************************************
3999 : Deal with setting the size from any of the setfilepathinfo functions.
4000 : ****************************************************************************/
4001 :
4002 472 : NTSTATUS smb_set_file_size(connection_struct *conn,
4003 : struct smb_request *req,
4004 : files_struct *fsp,
4005 : struct smb_filename *smb_fname,
4006 : const SMB_STRUCT_STAT *psbuf,
4007 : off_t size,
4008 : bool fail_after_createfile)
4009 : {
4010 472 : NTSTATUS status = NT_STATUS_OK;
4011 472 : files_struct *new_fsp = NULL;
4012 :
4013 472 : if (!VALID_STAT(*psbuf)) {
4014 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4015 : }
4016 :
4017 472 : DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4018 : (uint64_t)size,
4019 : get_file_size_stat(psbuf));
4020 :
4021 472 : if (size == get_file_size_stat(psbuf)) {
4022 148 : if (fsp == NULL) {
4023 0 : return NT_STATUS_OK;
4024 : }
4025 148 : if (!fsp->fsp_flags.modified) {
4026 144 : return NT_STATUS_OK;
4027 : }
4028 4 : trigger_write_time_update_immediate(fsp);
4029 4 : return NT_STATUS_OK;
4030 : }
4031 :
4032 324 : DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4033 : smb_fname_str_dbg(smb_fname), (double)size));
4034 :
4035 324 : if (fsp &&
4036 608 : !fsp->fsp_flags.is_pathref &&
4037 284 : fsp_get_io_fd(fsp) != -1)
4038 : {
4039 : /* Handle based call. */
4040 284 : status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4041 284 : if (!NT_STATUS_IS_OK(status)) {
4042 1 : return status;
4043 : }
4044 :
4045 283 : if (vfs_set_filelen(fsp, size) == -1) {
4046 8 : return map_nt_error_from_unix(errno);
4047 : }
4048 275 : trigger_write_time_update_immediate(fsp);
4049 275 : return NT_STATUS_OK;
4050 : }
4051 :
4052 40 : status = SMB_VFS_CREATE_FILE(
4053 : conn, /* conn */
4054 : req, /* req */
4055 : NULL, /* dirfsp */
4056 : smb_fname, /* fname */
4057 : FILE_WRITE_DATA, /* access_mask */
4058 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4059 : FILE_SHARE_DELETE),
4060 : FILE_OPEN, /* create_disposition*/
4061 : 0, /* create_options */
4062 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4063 : 0, /* oplock_request */
4064 : NULL, /* lease */
4065 : 0, /* allocation_size */
4066 : 0, /* private_flags */
4067 : NULL, /* sd */
4068 : NULL, /* ea_list */
4069 : &new_fsp, /* result */
4070 : NULL, /* pinfo */
4071 : NULL, NULL); /* create context */
4072 :
4073 40 : if (!NT_STATUS_IS_OK(status)) {
4074 : /* NB. We check for open_was_deferred in the caller. */
4075 28 : return status;
4076 : }
4077 :
4078 : /* See RAW-SFILEINFO-END-OF-FILE */
4079 12 : if (fail_after_createfile) {
4080 4 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4081 4 : return NT_STATUS_INVALID_LEVEL;
4082 : }
4083 :
4084 8 : if (vfs_set_filelen(new_fsp, size) == -1) {
4085 0 : status = map_nt_error_from_unix(errno);
4086 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4087 0 : return status;
4088 : }
4089 :
4090 8 : trigger_write_time_update_immediate(new_fsp);
4091 8 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4092 8 : return NT_STATUS_OK;
4093 : }
4094 :
4095 : /****************************************************************************
4096 : Deal with SMB_INFO_SET_EA.
4097 : ****************************************************************************/
4098 :
4099 2931 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
4100 : const char *pdata,
4101 : int total_data,
4102 : files_struct *fsp,
4103 : struct smb_filename *smb_fname)
4104 : {
4105 2931 : struct ea_list *ea_list = NULL;
4106 2931 : TALLOC_CTX *ctx = NULL;
4107 2931 : NTSTATUS status = NT_STATUS_OK;
4108 :
4109 2931 : if (total_data < 10) {
4110 :
4111 : /* OS/2 workplace shell seems to send SET_EA requests of "null"
4112 : length. They seem to have no effect. Bug #3212. JRA */
4113 :
4114 0 : if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4115 : /* We're done. We only get EA info in this call. */
4116 0 : return NT_STATUS_OK;
4117 : }
4118 :
4119 0 : return NT_STATUS_INVALID_PARAMETER;
4120 : }
4121 :
4122 2931 : if (IVAL(pdata,0) > total_data) {
4123 0 : DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4124 : IVAL(pdata,0), (unsigned int)total_data));
4125 0 : return NT_STATUS_INVALID_PARAMETER;
4126 : }
4127 :
4128 2931 : ctx = talloc_tos();
4129 2931 : ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4130 2931 : if (!ea_list) {
4131 8 : return NT_STATUS_INVALID_PARAMETER;
4132 : }
4133 :
4134 2923 : if (fsp == NULL) {
4135 : /*
4136 : * The only way fsp can be NULL here is if
4137 : * smb_fname points at a symlink and
4138 : * and we're in POSIX context.
4139 : * Ensure this is the case.
4140 : *
4141 : * In this case we cannot set the EA.
4142 : */
4143 0 : SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4144 0 : return NT_STATUS_ACCESS_DENIED;
4145 : }
4146 :
4147 2923 : status = set_ea(conn, fsp, ea_list);
4148 :
4149 2923 : return status;
4150 : }
4151 :
4152 : /****************************************************************************
4153 : Deal with SMB_FILE_FULL_EA_INFORMATION set.
4154 : ****************************************************************************/
4155 :
4156 12 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4157 : const char *pdata,
4158 : int total_data,
4159 : files_struct *fsp)
4160 : {
4161 12 : struct ea_list *ea_list = NULL;
4162 0 : NTSTATUS status;
4163 :
4164 12 : if (fsp == NULL) {
4165 0 : return NT_STATUS_INVALID_HANDLE;
4166 : }
4167 :
4168 12 : if (!lp_ea_support(SNUM(conn))) {
4169 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4170 : "EA's not supported.\n",
4171 : (unsigned int)total_data));
4172 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
4173 : }
4174 :
4175 12 : if (total_data < 10) {
4176 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4177 : "too small.\n",
4178 : (unsigned int)total_data));
4179 0 : return NT_STATUS_INVALID_PARAMETER;
4180 : }
4181 :
4182 12 : ea_list = read_nttrans_ea_list(talloc_tos(),
4183 : pdata,
4184 : total_data);
4185 :
4186 12 : if (!ea_list) {
4187 0 : return NT_STATUS_INVALID_PARAMETER;
4188 : }
4189 :
4190 12 : status = set_ea(conn, fsp, ea_list);
4191 :
4192 12 : DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4193 : smb_fname_str_dbg(fsp->fsp_name),
4194 : nt_errstr(status) ));
4195 :
4196 12 : return status;
4197 : }
4198 :
4199 :
4200 : /****************************************************************************
4201 : Deal with SMB_SET_FILE_DISPOSITION_INFO.
4202 : ****************************************************************************/
4203 :
4204 3879 : NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4205 : const char *pdata,
4206 : int total_data,
4207 : files_struct *fsp,
4208 : struct smb_filename *smb_fname)
4209 : {
4210 3879 : NTSTATUS status = NT_STATUS_OK;
4211 21 : bool delete_on_close;
4212 3879 : uint32_t dosmode = 0;
4213 :
4214 3879 : if (total_data < 1) {
4215 0 : return NT_STATUS_INVALID_PARAMETER;
4216 : }
4217 :
4218 3879 : if (fsp == NULL) {
4219 0 : return NT_STATUS_INVALID_HANDLE;
4220 : }
4221 :
4222 3879 : delete_on_close = (CVAL(pdata,0) ? True : False);
4223 3879 : dosmode = fdos_mode(fsp);
4224 :
4225 3879 : DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4226 : "delete_on_close = %u\n",
4227 : smb_fname_str_dbg(smb_fname),
4228 : (unsigned int)dosmode,
4229 : (unsigned int)delete_on_close ));
4230 :
4231 3879 : if (delete_on_close) {
4232 3824 : status = can_set_delete_on_close(fsp, dosmode);
4233 3824 : if (!NT_STATUS_IS_OK(status)) {
4234 89 : return status;
4235 : }
4236 : }
4237 :
4238 : /* The set is across all open files on this dev/inode pair. */
4239 3790 : if (!set_delete_on_close(fsp, delete_on_close,
4240 3790 : conn->session_info->security_token,
4241 3790 : conn->session_info->unix_token)) {
4242 8 : return NT_STATUS_ACCESS_DENIED;
4243 : }
4244 3782 : return NT_STATUS_OK;
4245 : }
4246 :
4247 : /****************************************************************************
4248 : Deal with SMB_FILE_POSITION_INFORMATION.
4249 : ****************************************************************************/
4250 :
4251 94 : static NTSTATUS smb_file_position_information(connection_struct *conn,
4252 : const char *pdata,
4253 : int total_data,
4254 : files_struct *fsp)
4255 : {
4256 2 : uint64_t position_information;
4257 :
4258 94 : if (total_data < 8) {
4259 0 : return NT_STATUS_INVALID_PARAMETER;
4260 : }
4261 :
4262 94 : if (fsp == NULL) {
4263 : /* Ignore on pathname based set. */
4264 0 : return NT_STATUS_OK;
4265 : }
4266 :
4267 94 : position_information = (uint64_t)IVAL(pdata,0);
4268 94 : position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4269 :
4270 94 : DEBUG(10,("smb_file_position_information: Set file position "
4271 : "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4272 : (double)position_information));
4273 94 : fh_set_position_information(fsp->fh, position_information);
4274 94 : return NT_STATUS_OK;
4275 : }
4276 :
4277 : /****************************************************************************
4278 : Deal with SMB_FILE_MODE_INFORMATION.
4279 : ****************************************************************************/
4280 :
4281 8 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
4282 : const char *pdata,
4283 : int total_data)
4284 : {
4285 0 : uint32_t mode;
4286 :
4287 8 : if (total_data < 4) {
4288 0 : return NT_STATUS_INVALID_PARAMETER;
4289 : }
4290 8 : mode = IVAL(pdata,0);
4291 8 : if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4292 0 : return NT_STATUS_INVALID_PARAMETER;
4293 : }
4294 8 : return NT_STATUS_OK;
4295 : }
4296 :
4297 : /****************************************************************************
4298 : Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4299 : ****************************************************************************/
4300 :
4301 792 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4302 : struct smb_request *req,
4303 : const char *pdata,
4304 : int total_data,
4305 : files_struct *fsp,
4306 : struct smb_filename *smb_fname_src)
4307 : {
4308 0 : bool overwrite;
4309 0 : uint32_t len;
4310 792 : char *newname = NULL;
4311 792 : struct files_struct *dst_dirfsp = NULL;
4312 792 : struct smb_filename *smb_fname_dst = NULL;
4313 792 : const char *dst_original_lcomp = NULL;
4314 792 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4315 792 : NTSTATUS status = NT_STATUS_OK;
4316 792 : TALLOC_CTX *ctx = talloc_tos();
4317 :
4318 792 : if (!fsp) {
4319 0 : return NT_STATUS_INVALID_HANDLE;
4320 : }
4321 :
4322 792 : if (total_data < 20) {
4323 0 : return NT_STATUS_INVALID_PARAMETER;
4324 : }
4325 :
4326 792 : overwrite = (CVAL(pdata,0) ? True : False);
4327 792 : len = IVAL(pdata,16);
4328 :
4329 792 : if (len > (total_data - 20) || (len == 0)) {
4330 0 : return NT_STATUS_INVALID_PARAMETER;
4331 : }
4332 :
4333 792 : (void)srvstr_pull_talloc(ctx,
4334 : pdata,
4335 : req->flags2,
4336 : &newname,
4337 : &pdata[20],
4338 : len,
4339 : STR_TERMINATE);
4340 :
4341 792 : if (newname == NULL) {
4342 0 : return NT_STATUS_INVALID_PARAMETER;
4343 : }
4344 :
4345 : /* SMB2 rename paths are never DFS. */
4346 792 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4347 792 : ucf_flags &= ~UCF_DFS_PATHNAME;
4348 :
4349 792 : status = check_path_syntax(newname,
4350 792 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4351 792 : if (!NT_STATUS_IS_OK(status)) {
4352 0 : return status;
4353 : }
4354 :
4355 792 : DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4356 : newname));
4357 :
4358 792 : if (newname[0] == ':') {
4359 : /* Create an smb_fname to call rename_internals_fsp() with. */
4360 16 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4361 16 : fsp->base_fsp->fsp_name->base_name,
4362 : newname,
4363 : NULL,
4364 16 : fsp->base_fsp->fsp_name->twrp,
4365 16 : fsp->base_fsp->fsp_name->flags);
4366 16 : if (smb_fname_dst == NULL) {
4367 0 : status = NT_STATUS_NO_MEMORY;
4368 0 : goto out;
4369 : }
4370 : } else {
4371 776 : status = filename_convert_dirfsp(ctx,
4372 : conn,
4373 : newname,
4374 : ucf_flags,
4375 : 0, /* Never a TWRP. */
4376 : &dst_dirfsp,
4377 : &smb_fname_dst);
4378 776 : if (!NT_STATUS_IS_OK(status)) {
4379 130 : goto out;
4380 : }
4381 : }
4382 :
4383 : /*
4384 : * Set the original last component, since
4385 : * rename_internals_fsp() requires it.
4386 : */
4387 662 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4388 : conn,
4389 : newname,
4390 : ucf_flags);
4391 662 : if (dst_original_lcomp == NULL) {
4392 0 : status = NT_STATUS_NO_MEMORY;
4393 0 : goto out;
4394 : }
4395 :
4396 662 : DEBUG(10,("smb2_file_rename_information: "
4397 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4398 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4399 : smb_fname_str_dbg(smb_fname_dst)));
4400 662 : status = rename_internals_fsp(conn,
4401 : fsp,
4402 : smb_fname_dst,
4403 : dst_original_lcomp,
4404 : (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4405 : overwrite);
4406 :
4407 792 : out:
4408 792 : TALLOC_FREE(smb_fname_dst);
4409 792 : return status;
4410 : }
4411 :
4412 19 : static NTSTATUS smb2_file_link_information(connection_struct *conn,
4413 : struct smb_request *req,
4414 : const char *pdata,
4415 : int total_data,
4416 : files_struct *fsp,
4417 : struct smb_filename *smb_fname_src)
4418 : {
4419 0 : bool overwrite;
4420 0 : uint32_t len;
4421 19 : char *newname = NULL;
4422 19 : struct files_struct *dst_dirfsp = NULL;
4423 19 : struct smb_filename *smb_fname_dst = NULL;
4424 19 : NTSTATUS status = NT_STATUS_OK;
4425 19 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4426 0 : size_t ret;
4427 19 : TALLOC_CTX *ctx = talloc_tos();
4428 :
4429 19 : if (!fsp) {
4430 0 : return NT_STATUS_INVALID_HANDLE;
4431 : }
4432 :
4433 19 : if (total_data < 20) {
4434 0 : return NT_STATUS_INVALID_PARAMETER;
4435 : }
4436 :
4437 19 : overwrite = (CVAL(pdata,0) ? true : false);
4438 19 : len = IVAL(pdata,16);
4439 :
4440 19 : if (len > (total_data - 20) || (len == 0)) {
4441 0 : return NT_STATUS_INVALID_PARAMETER;
4442 : }
4443 :
4444 19 : ret = srvstr_pull_talloc(ctx,
4445 : pdata,
4446 : req->flags2,
4447 : &newname,
4448 : &pdata[20],
4449 : len,
4450 : STR_TERMINATE);
4451 :
4452 19 : if (ret == (size_t)-1 || newname == NULL) {
4453 0 : return NT_STATUS_INVALID_PARAMETER;
4454 : }
4455 :
4456 : /* SMB2 hardlink paths are never DFS. */
4457 19 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4458 19 : ucf_flags &= ~UCF_DFS_PATHNAME;
4459 :
4460 19 : status = check_path_syntax(newname,
4461 19 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4462 19 : if (!NT_STATUS_IS_OK(status)) {
4463 0 : return status;
4464 : }
4465 :
4466 19 : DBG_DEBUG("got name |%s|\n", newname);
4467 :
4468 19 : status = filename_convert_dirfsp(ctx,
4469 : conn,
4470 : newname,
4471 : ucf_flags,
4472 : 0, /* No TWRP. */
4473 : &dst_dirfsp,
4474 : &smb_fname_dst);
4475 19 : if (!NT_STATUS_IS_OK(status)) {
4476 2 : return status;
4477 : }
4478 :
4479 17 : if (fsp->base_fsp) {
4480 : /* No stream names. */
4481 0 : return NT_STATUS_NOT_SUPPORTED;
4482 : }
4483 :
4484 17 : DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4485 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4486 : smb_fname_str_dbg(smb_fname_dst));
4487 17 : status = hardlink_internals(ctx,
4488 : conn,
4489 : req,
4490 : overwrite,
4491 17 : fsp->fsp_name,
4492 : smb_fname_dst);
4493 :
4494 17 : TALLOC_FREE(smb_fname_dst);
4495 17 : return status;
4496 : }
4497 :
4498 8 : static NTSTATUS smb_file_link_information(connection_struct *conn,
4499 : struct smb_request *req,
4500 : const char *pdata,
4501 : int total_data,
4502 : files_struct *fsp,
4503 : struct smb_filename *smb_fname_src)
4504 : {
4505 0 : bool overwrite;
4506 0 : uint32_t len;
4507 8 : char *newname = NULL;
4508 8 : struct files_struct *dst_dirfsp = NULL;
4509 8 : struct smb_filename *smb_fname_dst = NULL;
4510 8 : NTSTATUS status = NT_STATUS_OK;
4511 8 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4512 8 : NTTIME dst_twrp = 0;
4513 8 : TALLOC_CTX *ctx = talloc_tos();
4514 :
4515 8 : if (!fsp) {
4516 0 : return NT_STATUS_INVALID_HANDLE;
4517 : }
4518 :
4519 8 : if (total_data < 20) {
4520 0 : return NT_STATUS_INVALID_PARAMETER;
4521 : }
4522 :
4523 8 : overwrite = (CVAL(pdata,0) ? true : false);
4524 8 : len = IVAL(pdata,16);
4525 :
4526 8 : if (len > (total_data - 20) || (len == 0)) {
4527 8 : return NT_STATUS_INVALID_PARAMETER;
4528 : }
4529 :
4530 0 : if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4531 0 : srvstr_get_path_posix(ctx,
4532 : pdata,
4533 0 : req->flags2,
4534 : &newname,
4535 : &pdata[20],
4536 : len,
4537 : STR_TERMINATE,
4538 : &status);
4539 0 : ucf_flags |= UCF_POSIX_PATHNAMES;
4540 : } else {
4541 0 : srvstr_get_path(ctx,
4542 : pdata,
4543 0 : req->flags2,
4544 : &newname,
4545 : &pdata[20],
4546 : len,
4547 : STR_TERMINATE,
4548 : &status);
4549 : }
4550 0 : if (!NT_STATUS_IS_OK(status)) {
4551 0 : return status;
4552 : }
4553 :
4554 0 : DEBUG(10,("smb_file_link_information: got name |%s|\n",
4555 : newname));
4556 :
4557 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
4558 0 : extract_snapshot_token(newname, &dst_twrp);
4559 : }
4560 : /* hardlink paths are never DFS. */
4561 0 : ucf_flags &= ~UCF_DFS_PATHNAME;
4562 :
4563 0 : status = filename_convert_dirfsp(ctx,
4564 : conn,
4565 : newname,
4566 : ucf_flags,
4567 : dst_twrp,
4568 : &dst_dirfsp,
4569 : &smb_fname_dst);
4570 0 : if (!NT_STATUS_IS_OK(status)) {
4571 0 : return status;
4572 : }
4573 :
4574 0 : if (fsp->base_fsp) {
4575 : /* No stream names. */
4576 0 : return NT_STATUS_NOT_SUPPORTED;
4577 : }
4578 :
4579 0 : DEBUG(10,("smb_file_link_information: "
4580 : "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4581 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4582 : smb_fname_str_dbg(smb_fname_dst)));
4583 0 : status = hardlink_internals(ctx,
4584 : conn,
4585 : req,
4586 : overwrite,
4587 0 : fsp->fsp_name,
4588 : smb_fname_dst);
4589 :
4590 0 : TALLOC_FREE(smb_fname_dst);
4591 0 : return status;
4592 : }
4593 :
4594 :
4595 : /****************************************************************************
4596 : Deal with SMB_FILE_RENAME_INFORMATION.
4597 : ****************************************************************************/
4598 :
4599 139 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
4600 : struct smb_request *req,
4601 : const char *pdata,
4602 : int total_data,
4603 : files_struct *fsp,
4604 : struct smb_filename *smb_fname_src)
4605 : {
4606 3 : bool overwrite;
4607 3 : uint32_t root_fid;
4608 3 : uint32_t len;
4609 139 : char *newname = NULL;
4610 139 : struct files_struct *dst_dirfsp = NULL;
4611 139 : struct smb_filename *smb_fname_dst = NULL;
4612 139 : const char *dst_original_lcomp = NULL;
4613 139 : NTSTATUS status = NT_STATUS_OK;
4614 3 : char *p;
4615 139 : TALLOC_CTX *ctx = talloc_tos();
4616 :
4617 139 : if (total_data < 13) {
4618 0 : return NT_STATUS_INVALID_PARAMETER;
4619 : }
4620 :
4621 139 : overwrite = (CVAL(pdata,0) != 0);
4622 139 : root_fid = IVAL(pdata,4);
4623 139 : len = IVAL(pdata,8);
4624 :
4625 139 : if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4626 12 : return NT_STATUS_INVALID_PARAMETER;
4627 : }
4628 :
4629 127 : if (req->posix_pathnames) {
4630 0 : srvstr_get_path_posix(ctx,
4631 : pdata,
4632 0 : req->flags2,
4633 : &newname,
4634 : &pdata[12],
4635 : len,
4636 : 0,
4637 : &status);
4638 : } else {
4639 127 : srvstr_get_path(ctx,
4640 : pdata,
4641 127 : req->flags2,
4642 : &newname,
4643 : &pdata[12],
4644 : len,
4645 : 0,
4646 : &status);
4647 : }
4648 127 : if (!NT_STATUS_IS_OK(status)) {
4649 0 : return status;
4650 : }
4651 :
4652 127 : DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4653 : newname));
4654 :
4655 : /* Check the new name has no '/' characters. */
4656 127 : if (strchr_m(newname, '/')) {
4657 8 : return NT_STATUS_NOT_SUPPORTED;
4658 : }
4659 :
4660 119 : if (fsp && fsp->base_fsp) {
4661 : /* newname must be a stream name. */
4662 28 : if (newname[0] != ':') {
4663 0 : return NT_STATUS_NOT_SUPPORTED;
4664 : }
4665 :
4666 : /* Create an smb_fname to call rename_internals_fsp() with. */
4667 28 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4668 28 : fsp->base_fsp->fsp_name->base_name,
4669 : newname,
4670 : NULL,
4671 28 : fsp->base_fsp->fsp_name->twrp,
4672 28 : fsp->base_fsp->fsp_name->flags);
4673 28 : if (smb_fname_dst == NULL) {
4674 0 : status = NT_STATUS_NO_MEMORY;
4675 0 : goto out;
4676 : }
4677 :
4678 : /*
4679 : * Get the original last component, since
4680 : * rename_internals_fsp() requires it.
4681 : */
4682 28 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4683 : conn,
4684 : newname,
4685 : 0);
4686 28 : if (dst_original_lcomp == NULL) {
4687 0 : status = NT_STATUS_NO_MEMORY;
4688 0 : goto out;
4689 : }
4690 :
4691 : } else {
4692 : /*
4693 : * Build up an smb_fname_dst based on the filename passed in.
4694 : * We basically just strip off the last component, and put on
4695 : * the newname instead.
4696 : */
4697 91 : char *base_name = NULL;
4698 91 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4699 91 : NTTIME dst_twrp = 0;
4700 :
4701 : /* newname must *not* be a stream name. */
4702 91 : if (newname[0] == ':') {
4703 0 : return NT_STATUS_NOT_SUPPORTED;
4704 : }
4705 :
4706 : /*
4707 : * Strip off the last component (filename) of the path passed
4708 : * in.
4709 : */
4710 91 : base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4711 91 : if (!base_name) {
4712 0 : return NT_STATUS_NO_MEMORY;
4713 : }
4714 91 : p = strrchr_m(base_name, '/');
4715 91 : if (p) {
4716 80 : p[1] = '\0';
4717 : } else {
4718 11 : base_name = talloc_strdup(ctx, "");
4719 11 : if (!base_name) {
4720 0 : return NT_STATUS_NO_MEMORY;
4721 : }
4722 : }
4723 : /* Append the new name. */
4724 91 : base_name = talloc_asprintf_append(base_name,
4725 : "%s",
4726 : newname);
4727 91 : if (!base_name) {
4728 0 : return NT_STATUS_NO_MEMORY;
4729 : }
4730 :
4731 91 : if (ucf_flags & UCF_GMT_PATHNAME) {
4732 0 : extract_snapshot_token(base_name, &dst_twrp);
4733 : }
4734 :
4735 : /* The newname is *not* a DFS path. */
4736 91 : ucf_flags &= ~UCF_DFS_PATHNAME;
4737 :
4738 91 : status = filename_convert_dirfsp(ctx,
4739 : conn,
4740 : base_name,
4741 : ucf_flags,
4742 : dst_twrp,
4743 : &dst_dirfsp,
4744 : &smb_fname_dst);
4745 :
4746 91 : if (!NT_STATUS_IS_OK(status)) {
4747 0 : goto out;
4748 : }
4749 91 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4750 : conn,
4751 : newname,
4752 : ucf_flags);
4753 91 : if (dst_original_lcomp == NULL) {
4754 0 : status = NT_STATUS_NO_MEMORY;
4755 0 : goto out;
4756 : }
4757 : }
4758 :
4759 119 : if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4760 80 : DEBUG(10,("smb_file_rename_information: "
4761 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4762 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4763 : smb_fname_str_dbg(smb_fname_dst)));
4764 80 : status = rename_internals_fsp(conn,
4765 : fsp,
4766 : smb_fname_dst,
4767 : dst_original_lcomp,
4768 : 0,
4769 : overwrite);
4770 : } else {
4771 39 : DEBUG(10,("smb_file_rename_information: "
4772 : "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4773 : smb_fname_str_dbg(smb_fname_src),
4774 : smb_fname_str_dbg(smb_fname_dst)));
4775 39 : status = rename_internals(ctx,
4776 : conn,
4777 : req,
4778 : NULL, /* src_dirfsp */
4779 : smb_fname_src,
4780 : smb_fname_dst,
4781 : dst_original_lcomp,
4782 : 0,
4783 : overwrite,
4784 : FILE_WRITE_ATTRIBUTES);
4785 : }
4786 119 : out:
4787 119 : TALLOC_FREE(smb_fname_dst);
4788 119 : return status;
4789 : }
4790 :
4791 : /****************************************************************************
4792 : Deal with SMB_SET_FILE_BASIC_INFO.
4793 : ****************************************************************************/
4794 :
4795 2815 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4796 : const char *pdata,
4797 : int total_data,
4798 : files_struct *fsp,
4799 : struct smb_filename *smb_fname)
4800 : {
4801 : /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4802 31 : struct smb_file_time ft;
4803 2815 : uint32_t dosmode = 0;
4804 2815 : NTSTATUS status = NT_STATUS_OK;
4805 :
4806 2815 : init_smb_file_time(&ft);
4807 :
4808 2815 : if (total_data < 36) {
4809 0 : return NT_STATUS_INVALID_PARAMETER;
4810 : }
4811 :
4812 2815 : if (fsp == NULL) {
4813 0 : return NT_STATUS_INVALID_HANDLE;
4814 : }
4815 :
4816 2815 : status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4817 2815 : if (!NT_STATUS_IS_OK(status)) {
4818 5 : return status;
4819 : }
4820 :
4821 : /* Set the attributes */
4822 2810 : dosmode = IVAL(pdata,32);
4823 2810 : status = smb_set_file_dosmode(conn, fsp, dosmode);
4824 2810 : if (!NT_STATUS_IS_OK(status)) {
4825 5 : return status;
4826 : }
4827 :
4828 : /* create time */
4829 2805 : ft.create_time = pull_long_date_full_timespec(pdata);
4830 :
4831 : /* access time */
4832 2805 : ft.atime = pull_long_date_full_timespec(pdata+8);
4833 :
4834 : /* write time. */
4835 2805 : ft.mtime = pull_long_date_full_timespec(pdata+16);
4836 :
4837 : /* change time. */
4838 2805 : ft.ctime = pull_long_date_full_timespec(pdata+24);
4839 :
4840 2805 : DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4841 : smb_fname_str_dbg(smb_fname)));
4842 :
4843 2805 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4844 2805 : if (!NT_STATUS_IS_OK(status)) {
4845 0 : return status;
4846 : }
4847 :
4848 2805 : if (fsp->fsp_flags.modified) {
4849 1068 : trigger_write_time_update_immediate(fsp);
4850 : }
4851 2805 : return NT_STATUS_OK;
4852 : }
4853 :
4854 : /****************************************************************************
4855 : Deal with SMB_INFO_STANDARD.
4856 : ****************************************************************************/
4857 :
4858 8 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
4859 : const char *pdata,
4860 : int total_data,
4861 : files_struct *fsp,
4862 : struct smb_filename *smb_fname)
4863 : {
4864 0 : NTSTATUS status;
4865 0 : struct smb_file_time ft;
4866 :
4867 8 : init_smb_file_time(&ft);
4868 :
4869 8 : if (total_data < 12) {
4870 0 : return NT_STATUS_INVALID_PARAMETER;
4871 : }
4872 :
4873 8 : if (fsp == NULL) {
4874 0 : return NT_STATUS_INVALID_HANDLE;
4875 : }
4876 :
4877 : /* create time */
4878 8 : ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4879 : /* access time */
4880 8 : ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4881 : /* write time */
4882 8 : ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4883 :
4884 8 : DEBUG(10,("smb_set_info_standard: file %s\n",
4885 : smb_fname_str_dbg(smb_fname)));
4886 :
4887 8 : status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4888 8 : if (!NT_STATUS_IS_OK(status)) {
4889 4 : return status;
4890 : }
4891 :
4892 4 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4893 4 : if (!NT_STATUS_IS_OK(status)) {
4894 0 : return status;
4895 : }
4896 :
4897 4 : if (fsp->fsp_flags.modified) {
4898 0 : trigger_write_time_update_immediate(fsp);
4899 : }
4900 4 : return NT_STATUS_OK;
4901 : }
4902 :
4903 : /****************************************************************************
4904 : Deal with SMB_SET_FILE_ALLOCATION_INFO.
4905 : ****************************************************************************/
4906 :
4907 16 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4908 : struct smb_request *req,
4909 : const char *pdata,
4910 : int total_data,
4911 : files_struct *fsp,
4912 : struct smb_filename *smb_fname)
4913 : {
4914 16 : uint64_t allocation_size = 0;
4915 16 : NTSTATUS status = NT_STATUS_OK;
4916 16 : files_struct *new_fsp = NULL;
4917 :
4918 16 : if (!VALID_STAT(smb_fname->st)) {
4919 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4920 : }
4921 :
4922 16 : if (total_data < 8) {
4923 0 : return NT_STATUS_INVALID_PARAMETER;
4924 : }
4925 :
4926 16 : allocation_size = (uint64_t)IVAL(pdata,0);
4927 16 : allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4928 16 : DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4929 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4930 : (double)allocation_size));
4931 :
4932 16 : if (allocation_size) {
4933 6 : allocation_size = smb_roundup(conn, allocation_size);
4934 : }
4935 :
4936 16 : DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4937 : "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4938 : (double)allocation_size));
4939 :
4940 16 : if (fsp &&
4941 20 : !fsp->fsp_flags.is_pathref &&
4942 4 : fsp_get_io_fd(fsp) != -1)
4943 : {
4944 : /* Open file handle. */
4945 4 : status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4946 4 : if (!NT_STATUS_IS_OK(status)) {
4947 0 : return status;
4948 : }
4949 :
4950 : /* Only change if needed. */
4951 4 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4952 4 : if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4953 0 : return map_nt_error_from_unix(errno);
4954 : }
4955 : }
4956 : /* But always update the time. */
4957 : /*
4958 : * This is equivalent to a write. Ensure it's seen immediately
4959 : * if there are no pending writes.
4960 : */
4961 4 : trigger_write_time_update_immediate(fsp);
4962 4 : return NT_STATUS_OK;
4963 : }
4964 :
4965 : /* Pathname or stat or directory file. */
4966 12 : status = SMB_VFS_CREATE_FILE(
4967 : conn, /* conn */
4968 : req, /* req */
4969 : NULL, /* dirfsp */
4970 : smb_fname, /* fname */
4971 : FILE_WRITE_DATA, /* access_mask */
4972 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4973 : FILE_SHARE_DELETE),
4974 : FILE_OPEN, /* create_disposition*/
4975 : 0, /* create_options */
4976 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4977 : 0, /* oplock_request */
4978 : NULL, /* lease */
4979 : 0, /* allocation_size */
4980 : 0, /* private_flags */
4981 : NULL, /* sd */
4982 : NULL, /* ea_list */
4983 : &new_fsp, /* result */
4984 : NULL, /* pinfo */
4985 : NULL, NULL); /* create context */
4986 :
4987 12 : if (!NT_STATUS_IS_OK(status)) {
4988 : /* NB. We check for open_was_deferred in the caller. */
4989 10 : return status;
4990 : }
4991 :
4992 : /* Only change if needed. */
4993 2 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4994 2 : if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4995 0 : status = map_nt_error_from_unix(errno);
4996 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4997 0 : return status;
4998 : }
4999 : }
5000 :
5001 : /* Changing the allocation size should set the last mod time. */
5002 : /*
5003 : * This is equivalent to a write. Ensure it's seen immediately
5004 : * if there are no pending writes.
5005 : */
5006 2 : trigger_write_time_update_immediate(new_fsp);
5007 2 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
5008 2 : return NT_STATUS_OK;
5009 : }
5010 :
5011 : /****************************************************************************
5012 : Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5013 : ****************************************************************************/
5014 :
5015 332 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5016 : struct smb_request *req,
5017 : const char *pdata,
5018 : int total_data,
5019 : files_struct *fsp,
5020 : struct smb_filename *smb_fname,
5021 : bool fail_after_createfile)
5022 : {
5023 1 : off_t size;
5024 :
5025 332 : if (total_data < 8) {
5026 0 : return NT_STATUS_INVALID_PARAMETER;
5027 : }
5028 :
5029 332 : size = IVAL(pdata,0);
5030 332 : size |= (((off_t)IVAL(pdata,4)) << 32);
5031 332 : DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5032 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5033 : (double)size));
5034 :
5035 332 : return smb_set_file_size(conn, req,
5036 : fsp,
5037 : smb_fname,
5038 332 : &smb_fname->st,
5039 : size,
5040 : fail_after_createfile);
5041 : }
5042 :
5043 10829 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5044 : struct smb_request *req,
5045 : TALLOC_CTX *mem_ctx,
5046 : uint16_t info_level,
5047 : files_struct *fsp,
5048 : struct smb_filename *smb_fname,
5049 : char **ppdata, int total_data,
5050 : int *ret_data_size)
5051 : {
5052 10829 : char *pdata = *ppdata;
5053 10829 : NTSTATUS status = NT_STATUS_OK;
5054 10829 : int data_return_size = 0;
5055 :
5056 10829 : *ret_data_size = 0;
5057 :
5058 10829 : DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5059 : "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5060 : fsp_fnum_dbg(fsp),
5061 : info_level, total_data));
5062 :
5063 10829 : switch (info_level) {
5064 :
5065 8 : case SMB_INFO_STANDARD:
5066 : {
5067 8 : status = smb_set_info_standard(conn,
5068 : pdata,
5069 : total_data,
5070 : fsp,
5071 : smb_fname);
5072 8 : break;
5073 : }
5074 :
5075 2931 : case SMB_INFO_SET_EA:
5076 : {
5077 2931 : status = smb_info_set_ea(conn,
5078 : pdata,
5079 : total_data,
5080 : fsp,
5081 : smb_fname);
5082 2931 : break;
5083 : }
5084 :
5085 2815 : case SMB_SET_FILE_BASIC_INFO:
5086 : case SMB_FILE_BASIC_INFORMATION:
5087 : {
5088 2815 : status = smb_set_file_basic_info(conn,
5089 : pdata,
5090 : total_data,
5091 : fsp,
5092 : smb_fname);
5093 2815 : break;
5094 : }
5095 :
5096 16 : case SMB_FILE_ALLOCATION_INFORMATION:
5097 : case SMB_SET_FILE_ALLOCATION_INFO:
5098 : {
5099 16 : status = smb_set_file_allocation_info(conn, req,
5100 : pdata,
5101 : total_data,
5102 : fsp,
5103 : smb_fname);
5104 16 : break;
5105 : }
5106 :
5107 332 : case SMB_FILE_END_OF_FILE_INFORMATION:
5108 : case SMB_SET_FILE_END_OF_FILE_INFO:
5109 : {
5110 : /*
5111 : * XP/Win7 both fail after the createfile with
5112 : * SMB_SET_FILE_END_OF_FILE_INFO but not
5113 : * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5114 : * The level is known here, so pass it down
5115 : * appropriately.
5116 : */
5117 332 : bool should_fail =
5118 : (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5119 :
5120 332 : status = smb_set_file_end_of_file_info(conn, req,
5121 : pdata,
5122 : total_data,
5123 : fsp,
5124 : smb_fname,
5125 : should_fail);
5126 332 : break;
5127 : }
5128 :
5129 3639 : case SMB_FILE_DISPOSITION_INFORMATION:
5130 : case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5131 : {
5132 : #if 0
5133 : /* JRA - We used to just ignore this on a path ?
5134 : * Shouldn't this be invalid level on a pathname
5135 : * based call ?
5136 : */
5137 : if (tran_call != TRANSACT2_SETFILEINFO) {
5138 : return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5139 : }
5140 : #endif
5141 3639 : status = smb_set_file_disposition_info(conn,
5142 : pdata,
5143 : total_data,
5144 : fsp,
5145 : smb_fname);
5146 3639 : break;
5147 : }
5148 :
5149 94 : case SMB_FILE_POSITION_INFORMATION:
5150 : {
5151 94 : status = smb_file_position_information(conn,
5152 : pdata,
5153 : total_data,
5154 : fsp);
5155 94 : break;
5156 : }
5157 :
5158 12 : case SMB_FILE_FULL_EA_INFORMATION:
5159 : {
5160 12 : status = smb_set_file_full_ea_info(conn,
5161 : pdata,
5162 : total_data,
5163 : fsp);
5164 12 : break;
5165 : }
5166 :
5167 : /* From tridge Samba4 :
5168 : * MODE_INFORMATION in setfileinfo (I have no
5169 : * idea what "mode information" on a file is - it takes a value of 0,
5170 : * 2, 4 or 6. What could it be?).
5171 : */
5172 :
5173 8 : case SMB_FILE_MODE_INFORMATION:
5174 : {
5175 8 : status = smb_file_mode_information(conn,
5176 : pdata,
5177 : total_data);
5178 8 : break;
5179 : }
5180 :
5181 : /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5182 8 : case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5183 : case SMB_FILE_SHORT_NAME_INFORMATION:
5184 16 : return NT_STATUS_NOT_SUPPORTED;
5185 :
5186 139 : case SMB_FILE_RENAME_INFORMATION:
5187 : {
5188 139 : status = smb_file_rename_information(conn, req,
5189 : pdata, total_data,
5190 : fsp, smb_fname);
5191 139 : break;
5192 : }
5193 :
5194 792 : case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5195 : {
5196 : /* SMB2 rename information. */
5197 792 : status = smb2_file_rename_information(conn, req,
5198 : pdata, total_data,
5199 : fsp, smb_fname);
5200 792 : break;
5201 : }
5202 :
5203 27 : case SMB_FILE_LINK_INFORMATION:
5204 : {
5205 27 : if (conn->sconn->using_smb2) {
5206 19 : status = smb2_file_link_information(conn,
5207 : req,
5208 : pdata,
5209 : total_data,
5210 : fsp,
5211 : smb_fname);
5212 : } else {
5213 8 : status = smb_file_link_information(conn,
5214 : req,
5215 : pdata,
5216 : total_data,
5217 : fsp,
5218 : smb_fname);
5219 : }
5220 27 : break;
5221 : }
5222 :
5223 8 : default:
5224 8 : return NT_STATUS_INVALID_LEVEL;
5225 : }
5226 :
5227 10813 : if (!NT_STATUS_IS_OK(status)) {
5228 668 : return status;
5229 : }
5230 :
5231 10145 : *ret_data_size = data_return_size;
5232 10145 : return NT_STATUS_OK;
5233 : }
5234 :
5235 130 : static uint32_t generate_volume_serial_number(
5236 : const struct loadparm_substitution *lp_sub,
5237 : int snum)
5238 : {
5239 130 : int serial = lp_volume_serial_number(snum);
5240 258 : return serial != -1 ? serial:
5241 128 : str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5242 128 : (str_checksum(get_local_machine_name())<<16);
5243 : }
|