ctdb-server: Clean up connection tracking functions
[samba4-gss.git] / source3 / smbd / smb2_trans2.c
blob3f8dcb09c502d90d6bfa731f6f04816831b3c36f
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
10 Extensively modified by Andrew Tridgell, 1995
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.
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.
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/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
30 #include "version.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "../librpc/gen_ndr/ndr_smb3posix.h"
37 #include "libcli/security/security.h"
38 #include "trans2.h"
39 #include "auth.h"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
42 #include "printing.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.h"
45 #include "messages.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
50 #include "source3/smbd/dir.h"
51 #include "source3/modules/util_reparse.h"
53 #define DIR_ENTRY_SAFETY_MARGIN 4096
55 static uint32_t generate_volume_serial_number(
56 const struct loadparm_substitution *lp_sub,
57 int snum);
59 /****************************************************************************
60 Check if an open file handle is a symlink.
61 ****************************************************************************/
63 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
66 if (!VALID_STAT(fsp->fsp_name->st)) {
67 return NT_STATUS_ACCESS_DENIED;
69 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
70 return NT_STATUS_ACCESS_DENIED;
72 if (fsp_get_pathref_fd(fsp) == -1) {
73 return NT_STATUS_ACCESS_DENIED;
75 return NT_STATUS_OK;
78 /**
79 * Check that one or more of the rights in access mask are
80 * allowed. Iow, access_requested can contain more then one right and
81 * it is sufficient having only one of those granted to pass.
82 **/
83 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
84 uint32_t access_requested)
86 const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
87 uint32_t ro_access_granted = 0;
88 uint32_t access_granted = 0;
89 NTSTATUS status;
91 if (fsp->fsp_flags.is_fsa) {
92 access_granted = fsp->access_mask;
93 } else {
94 uint32_t mask = 1;
96 while (mask != 0) {
97 if (!(mask & access_requested)) {
98 mask <<= 1;
99 continue;
102 status = smbd_check_access_rights_fsp(
103 fsp->conn->cwd_fsp,
104 fsp,
105 false,
106 mask);
107 if (NT_STATUS_IS_OK(status)) {
108 access_granted |= mask;
109 if (fsp->fsp_name->twrp == 0) {
111 * We can only optimize
112 * the non-snapshot case
114 break;
117 mask <<= 1;
120 if ((access_granted & access_requested) == 0) {
121 return NT_STATUS_ACCESS_DENIED;
124 if (fsp->fsp_name->twrp == 0) {
125 return NT_STATUS_OK;
128 ro_access_granted = access_granted & ro_access;
129 if ((ro_access_granted & access_requested) == 0) {
130 return NT_STATUS_MEDIA_WRITE_PROTECTED;
133 return NT_STATUS_OK;
136 /********************************************************************
137 Roundup a value to the nearest allocation roundup size boundary.
138 Only do this for Windows clients.
139 ********************************************************************/
141 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
143 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
145 /* Only roundup for Windows clients. */
146 enum remote_arch_types ra_type = get_remote_arch();
147 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
148 val = SMB_ROUNDUP(val,rval);
150 return val;
153 /****************************************************************************
154 Utility functions for dealing with extended attributes.
155 ****************************************************************************/
157 /****************************************************************************
158 Refuse to allow clients to overwrite our private xattrs.
159 ****************************************************************************/
161 bool samba_private_attr_name(const char *unix_ea_name)
163 bool prohibited = false;
165 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
166 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
167 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
168 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_REPARSE_ATTRIB);
169 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
170 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
172 if (prohibited) {
173 return true;
176 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
177 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
178 return true;
180 return false;
183 /****************************************************************************
184 Get one EA value. Fill in a struct ea_struct.
185 ****************************************************************************/
187 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
188 files_struct *fsp,
189 const char *ea_name,
190 struct ea_struct *pea)
192 /* Get the value of this xattr. Max size is 64k. */
193 size_t attr_size = 256;
194 char *val = NULL;
195 ssize_t sizeret;
196 size_t max_xattr_size = 0;
197 NTSTATUS status;
199 if (fsp == NULL) {
200 return NT_STATUS_INVALID_HANDLE;
202 status = refuse_symlink_fsp(fsp);
203 if (!NT_STATUS_IS_OK(status)) {
204 return status;
207 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
209 again:
211 val = talloc_realloc(mem_ctx, val, char, attr_size);
212 if (!val) {
213 return NT_STATUS_NO_MEMORY;
216 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
217 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
218 attr_size = max_xattr_size;
219 goto again;
222 if (sizeret == -1) {
223 return map_nt_error_from_unix(errno);
226 DBG_DEBUG("EA %s is of length %zd\n", ea_name, sizeret);
227 dump_data(10, (uint8_t *)val, sizeret);
229 pea->flags = 0;
230 if (strnequal(ea_name, "user.", 5)) {
231 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
232 } else {
233 pea->name = talloc_strdup(mem_ctx, ea_name);
235 if (pea->name == NULL) {
236 TALLOC_FREE(val);
237 return NT_STATUS_NO_MEMORY;
239 pea->value.data = (unsigned char *)val;
240 pea->value.length = (size_t)sizeret;
241 return NT_STATUS_OK;
244 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
245 files_struct *fsp,
246 char ***pnames,
247 size_t *pnum_names)
249 char smallbuf[1024];
250 /* Get a list of all xattrs. Max namesize is 64k. */
251 size_t ea_namelist_size = 1024;
252 char *ea_namelist = smallbuf;
253 char *to_free = NULL;
255 char *p;
256 char **names;
257 size_t num_names;
258 ssize_t sizeret = -1;
259 NTSTATUS status;
261 if (pnames) {
262 *pnames = NULL;
264 *pnum_names = 0;
266 if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
268 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
269 * symlink. This is ok, handle it here, by just return no EA's
270 * on a symlink.
272 return NT_STATUS_OK;
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
276 ea_namelist_size);
278 if ((sizeret == -1) && (errno == ERANGE)) {
279 ea_namelist_size = 65536;
280 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
281 if (ea_namelist == NULL) {
282 return NT_STATUS_NO_MEMORY;
284 to_free = ea_namelist;
286 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
287 ea_namelist_size);
290 if (sizeret == -1) {
291 status = map_nt_error_from_unix(errno);
292 TALLOC_FREE(to_free);
293 return status;
296 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
298 if (sizeret == 0) {
299 TALLOC_FREE(to_free);
300 return NT_STATUS_OK;
304 * Ensure the result is 0-terminated
307 if (ea_namelist[sizeret-1] != '\0') {
308 TALLOC_FREE(to_free);
309 return NT_STATUS_INTERNAL_ERROR;
313 * count the names
315 num_names = 0;
317 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
318 num_names += 1;
321 *pnum_names = num_names;
323 if (pnames == NULL) {
324 TALLOC_FREE(to_free);
325 return NT_STATUS_OK;
328 names = talloc_array(mem_ctx, char *, num_names);
329 if (names == NULL) {
330 DEBUG(0, ("talloc failed\n"));
331 TALLOC_FREE(to_free);
332 return NT_STATUS_NO_MEMORY;
335 if (ea_namelist == smallbuf) {
336 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
337 if (ea_namelist == NULL) {
338 TALLOC_FREE(names);
339 return NT_STATUS_NO_MEMORY;
341 } else {
342 talloc_steal(names, ea_namelist);
344 ea_namelist = talloc_realloc(names, ea_namelist, char,
345 sizeret);
346 if (ea_namelist == NULL) {
347 TALLOC_FREE(names);
348 return NT_STATUS_NO_MEMORY;
352 num_names = 0;
354 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
355 names[num_names++] = p;
358 *pnames = names;
360 return NT_STATUS_OK;
363 /****************************************************************************
364 Return a linked list of the total EA's. Plus the total size
365 ****************************************************************************/
367 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
368 files_struct *fsp,
369 size_t *pea_total_len,
370 struct ea_list **ea_list)
372 /* Get a list of all xattrs. Max namesize is 64k. */
373 size_t i, num_names;
374 char **names;
375 struct ea_list *ea_list_head = NULL;
376 bool posix_pathnames = false;
377 NTSTATUS status;
379 *pea_total_len = 0;
380 *ea_list = NULL;
382 /* symlink */
383 if (fsp == NULL) {
384 return NT_STATUS_OK;
387 if (!lp_ea_support(SNUM(fsp->conn))) {
388 return NT_STATUS_OK;
391 if (fsp_is_alternate_stream(fsp)) {
392 return NT_STATUS_INVALID_PARAMETER;
395 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
397 status = get_ea_names_from_fsp(talloc_tos(),
398 fsp,
399 &names,
400 &num_names);
402 if (!NT_STATUS_IS_OK(status)) {
403 return status;
406 if (num_names == 0) {
407 return NT_STATUS_OK;
410 for (i=0; i<num_names; i++) {
411 struct ea_list *listp;
412 fstring dos_ea_name;
415 * POSIX EA names are divided into several namespaces by
416 * means of string prefixes. Usually, the system controls
417 * semantics for each namespace, but the 'user' namespace is
418 * available for arbitrary use, which comes closest to
419 * Windows EA semantics. Hence, we map POSIX EAs from the
420 * 'user' namespace to Windows EAs, and just ignore all the
421 * other namespaces. Also, a few specific names in the 'user'
422 * namespace are used by Samba internally. Filter them out as
423 * well, and only present the EAs that are available for
424 * arbitrary use.
426 if (!strnequal(names[i], "user.", 5)
427 || samba_private_attr_name(names[i]))
428 continue;
431 * Filter out any underlying POSIX EA names
432 * that a Windows client can't handle.
434 if (!posix_pathnames &&
435 is_invalid_windows_ea_name(names[i])) {
436 continue;
439 listp = talloc(mem_ctx, struct ea_list);
440 if (listp == NULL) {
441 return NT_STATUS_NO_MEMORY;
444 status = get_ea_value_fsp(listp,
445 fsp,
446 names[i],
447 &listp->ea);
449 if (!NT_STATUS_IS_OK(status)) {
450 TALLOC_FREE(listp);
451 return status;
454 if (listp->ea.value.length == 0) {
456 * We can never return a zero length EA.
457 * Windows reports the EA's as corrupted.
459 TALLOC_FREE(listp);
460 continue;
462 if (listp->ea.value.length > 65536) {
464 * SMB clients may report error with file
465 * if large EA is presented to them.
467 DBG_ERR("EA [%s] on file [%s] exceeds "
468 "maximum permitted EA size of 64KiB: %zu\n.",
469 listp->ea.name, fsp_str_dbg(fsp),
470 listp->ea.value.length);
471 TALLOC_FREE(listp);
472 continue;
475 push_ascii_fstring(dos_ea_name, listp->ea.name);
477 *pea_total_len +=
478 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
480 DBG_DEBUG("total_len = %zu, %s, val len = %zu\n",
481 *pea_total_len,
482 dos_ea_name,
483 listp->ea.value.length);
485 DLIST_ADD_END(ea_list_head, listp);
489 /* Add on 4 for total length. */
490 if (*pea_total_len) {
491 *pea_total_len += 4;
494 DBG_DEBUG("total_len = %zu\n", *pea_total_len);
496 *ea_list = ea_list_head;
497 return NT_STATUS_OK;
500 /****************************************************************************
501 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
502 that was filled.
503 ****************************************************************************/
505 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
506 connection_struct *conn, struct ea_list *ea_list)
508 unsigned int ret_data_size = 4;
509 char *p = pdata;
511 SMB_ASSERT(total_data_size >= 4);
513 if (!lp_ea_support(SNUM(conn))) {
514 SIVAL(pdata,4,0);
515 return 4;
518 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
519 size_t dos_namelen;
520 fstring dos_ea_name;
521 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
522 dos_namelen = strlen(dos_ea_name);
523 if (dos_namelen > 255 || dos_namelen == 0) {
524 break;
526 if (ea_list->ea.value.length > 65535) {
527 break;
529 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
530 break;
533 /* We know we have room. */
534 SCVAL(p,0,ea_list->ea.flags);
535 SCVAL(p,1,dos_namelen);
536 SSVAL(p,2,ea_list->ea.value.length);
537 strlcpy(p+4, dos_ea_name, dos_namelen+1);
538 if (ea_list->ea.value.length > 0) {
539 memcpy(p + 4 + dos_namelen + 1,
540 ea_list->ea.value.data,
541 ea_list->ea.value.length);
544 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
545 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
548 ret_data_size = PTR_DIFF(p, pdata);
549 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
550 SIVAL(pdata,0,ret_data_size);
551 return ret_data_size;
554 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
555 char *pdata,
556 unsigned int total_data_size,
557 unsigned int *ret_data_size,
558 connection_struct *conn,
559 struct ea_list *ea_list)
561 uint8_t *p = (uint8_t *)pdata;
562 uint8_t *last_start = NULL;
563 bool do_store_data = (pdata != NULL);
565 *ret_data_size = 0;
567 if (!lp_ea_support(SNUM(conn))) {
568 return NT_STATUS_NO_EAS_ON_FILE;
571 for (; ea_list; ea_list = ea_list->next) {
572 size_t dos_namelen;
573 fstring dos_ea_name;
574 size_t this_size;
575 size_t pad = 0;
577 if (last_start != NULL && do_store_data) {
578 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
580 last_start = p;
582 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
583 dos_namelen = strlen(dos_ea_name);
584 if (dos_namelen > 255 || dos_namelen == 0) {
585 return NT_STATUS_INTERNAL_ERROR;
587 if (ea_list->ea.value.length > 65535) {
588 return NT_STATUS_INTERNAL_ERROR;
591 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
593 if (ea_list->next) {
594 pad = (4 - (this_size % 4)) % 4;
595 this_size += pad;
598 if (do_store_data) {
599 if (this_size > total_data_size) {
600 return NT_STATUS_INFO_LENGTH_MISMATCH;
603 /* We know we have room. */
604 SIVAL(p, 0x00, 0); /* next offset */
605 SCVAL(p, 0x04, ea_list->ea.flags);
606 SCVAL(p, 0x05, dos_namelen);
607 SSVAL(p, 0x06, ea_list->ea.value.length);
608 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
609 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
610 if (pad) {
611 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
612 '\0',
613 pad);
615 total_data_size -= this_size;
618 p += this_size;
621 *ret_data_size = PTR_DIFF(p, pdata);
622 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
623 return NT_STATUS_OK;
626 unsigned int estimate_ea_size(files_struct *fsp)
628 size_t total_ea_len = 0;
629 TALLOC_CTX *mem_ctx;
630 struct ea_list *ea_list = NULL;
631 NTSTATUS status;
633 /* symlink */
634 if (fsp == NULL) {
635 return 0;
638 if (!lp_ea_support(SNUM(fsp->conn))) {
639 return 0;
642 mem_ctx = talloc_stackframe();
644 /* If this is a stream fsp, then we need to instead find the
645 * estimated ea len from the main file, not the stream
646 * (streams cannot have EAs), but the estimate isn't just 0 in
647 * this case! */
648 fsp = metadata_fsp(fsp);
649 (void)get_ea_list_from_fsp(mem_ctx,
650 fsp,
651 &total_ea_len,
652 &ea_list);
654 if(conn_using_smb2(fsp->conn->sconn)) {
655 unsigned int ret_data_size;
657 * We're going to be using fill_ea_chained_buffer() to
658 * marshall EA's - this size is significantly larger
659 * than the SMB1 buffer. Re-calculate the size without
660 * marshalling.
662 status = fill_ea_chained_buffer(mem_ctx,
663 NULL,
665 &ret_data_size,
666 fsp->conn,
667 ea_list);
668 if (!NT_STATUS_IS_OK(status)) {
669 ret_data_size = 0;
671 total_ea_len = ret_data_size;
673 TALLOC_FREE(mem_ctx);
674 return total_ea_len;
677 /****************************************************************************
678 Ensure the EA name is case insensitive by matching any existing EA name.
679 ****************************************************************************/
681 static void canonicalize_ea_name(files_struct *fsp,
682 fstring unix_ea_name)
684 size_t total_ea_len;
685 TALLOC_CTX *mem_ctx = talloc_tos();
686 struct ea_list *ea_list;
687 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
688 fsp,
689 &total_ea_len,
690 &ea_list);
691 if (!NT_STATUS_IS_OK(status)) {
692 return;
695 for (; ea_list; ea_list = ea_list->next) {
696 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
697 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
698 &unix_ea_name[5], ea_list->ea.name));
699 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
700 break;
705 /****************************************************************************
706 Set or delete an extended attribute.
707 ****************************************************************************/
709 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
710 struct ea_list *ea_list)
712 NTSTATUS status;
713 bool posix_pathnames = false;
715 if (!lp_ea_support(SNUM(conn))) {
716 return NT_STATUS_EAS_NOT_SUPPORTED;
719 if (fsp == NULL) {
720 return NT_STATUS_INVALID_HANDLE;
723 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
725 status = refuse_symlink_fsp(fsp);
726 if (!NT_STATUS_IS_OK(status)) {
727 return status;
730 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
731 if (!NT_STATUS_IS_OK(status)) {
732 return status;
735 /* Setting EAs on streams isn't supported. */
736 if (fsp_is_alternate_stream(fsp)) {
737 return NT_STATUS_INVALID_PARAMETER;
741 * Filter out invalid Windows EA names - before
742 * we set *any* of them.
745 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
746 return STATUS_INVALID_EA_NAME;
749 for (;ea_list; ea_list = ea_list->next) {
750 int ret;
751 fstring unix_ea_name;
754 * Complementing the forward mapping from POSIX EAs to
755 * Windows EAs in get_ea_list_from_fsp(), here we map in the
756 * opposite direction from Windows EAs to the 'user' namespace
757 * of POSIX EAs. Hence, all POSIX EA names the we set here must
758 * start with a 'user.' prefix.
760 fstrcpy(unix_ea_name, "user.");
761 fstrcat(unix_ea_name, ea_list->ea.name);
763 canonicalize_ea_name(fsp, unix_ea_name);
765 DBG_DEBUG("ea_name %s ealen = %zu\n",
766 unix_ea_name,
767 ea_list->ea.value.length);
769 if (samba_private_attr_name(unix_ea_name)) {
770 DBG_DEBUG("ea name %s is a private Samba name.\n",
771 unix_ea_name);
772 return NT_STATUS_ACCESS_DENIED;
775 if (ea_list->ea.value.length == 0) {
776 /* Remove the attribute. */
777 DBG_DEBUG("deleting ea name %s on "
778 "file %s by file descriptor.\n",
779 unix_ea_name, fsp_str_dbg(fsp));
780 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
781 #ifdef ENOATTR
782 /* Removing a non existent attribute always succeeds. */
783 if (ret == -1 && errno == ENOATTR) {
784 DBG_DEBUG("deleting ea name %s didn't exist - "
785 "succeeding by default.\n",
786 unix_ea_name);
787 ret = 0;
789 #endif
790 } else {
791 DBG_DEBUG("setting ea name %s on file "
792 "%s by file descriptor.\n",
793 unix_ea_name,
794 fsp_str_dbg(fsp));
795 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
796 ea_list->ea.value.data, ea_list->ea.value.length, 0);
799 if (ret == -1) {
800 #ifdef ENOTSUP
801 if (errno == ENOTSUP) {
802 return NT_STATUS_EAS_NOT_SUPPORTED;
804 #endif
805 return map_nt_error_from_unix(errno);
809 return NT_STATUS_OK;
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
818 struct ea_list *ea_list_head = NULL;
819 size_t offset = 0;
820 size_t bytes_used = 0;
822 while (offset < data_size) {
823 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
825 if (!eal) {
826 return NULL;
829 DLIST_ADD_END(ea_list_head, eal);
830 offset += bytes_used;
833 return ea_list_head;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list *ealist)
842 fstring dos_ea_name;
843 struct ea_list *listp;
844 size_t ret = 0;
846 for (listp = ealist; listp; listp = listp->next) {
847 push_ascii_fstring(dos_ea_name, listp->ea.name);
848 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
850 /* Add on 4 for total length. */
851 if (ret) {
852 ret += 4;
855 return ret;
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
866 struct ea_list *nlistp, *flistp;
868 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
869 for (flistp = file_list; flistp; flistp = flistp->next) {
870 if (strequal(nlistp->ea.name, flistp->ea.name)) {
871 break;
875 if (flistp) {
876 /* Copy the data from this entry. */
877 nlistp->ea.flags = flistp->ea.flags;
878 nlistp->ea.value = flistp->ea.value;
879 } else {
880 /* Null entry. */
881 nlistp->ea.flags = 0;
882 ZERO_STRUCT(nlistp->ea.value);
886 *total_ea_len = ea_list_size(name_list);
887 return name_list;
890 /****************************************************************************
891 Map wire perms onto standard UNIX permissions. Obey share restrictions.
892 ****************************************************************************/
894 NTSTATUS unix_perms_from_wire(connection_struct *conn,
895 const SMB_STRUCT_STAT *psbuf,
896 uint32_t perms,
897 mode_t *ret_perms)
899 mode_t ret = 0;
901 if (perms == SMB_MODE_NO_CHANGE) {
902 if (!VALID_STAT(*psbuf)) {
903 return NT_STATUS_INVALID_PARAMETER;
905 *ret_perms = psbuf->st_ex_mode;
906 return NT_STATUS_OK;
909 ret = wire_perms_to_unix(perms);
911 *ret_perms = ret;
912 return NT_STATUS_OK;
915 /****************************************************************************
916 Get a level dependent lanman2 dir entry.
917 ****************************************************************************/
919 struct smbd_dirptr_lanman2_state {
920 connection_struct *conn;
921 uint32_t info_level;
922 bool check_mangled_names;
923 bool case_sensitive;
926 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
927 void *private_data,
928 const char *dname,
929 const char *mask,
930 char **_fname)
932 struct smbd_dirptr_lanman2_state *state =
933 (struct smbd_dirptr_lanman2_state *)private_data;
934 bool ok;
935 char mangled_name[13]; /* mangled 8.3 name. */
936 bool got_match;
937 const char *fname;
939 /* Mangle fname if it's an illegal name. */
940 if (mangle_must_mangle(dname, state->conn->params)) {
942 * Slow path - ensure we can push the original name as UCS2. If
943 * not, then just don't return this name.
945 NTSTATUS status;
946 size_t ret_len = 0;
947 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
948 uint8_t *tmp = talloc_array(talloc_tos(),
949 uint8_t,
950 len);
952 status = srvstr_push(NULL,
953 FLAGS2_UNICODE_STRINGS,
954 tmp,
955 dname,
956 len,
957 STR_TERMINATE,
958 &ret_len);
960 TALLOC_FREE(tmp);
962 if (!NT_STATUS_IS_OK(status)) {
963 return false;
966 ok = name_to_8_3(dname, mangled_name,
967 true, state->conn->params);
968 if (!ok) {
969 return false;
971 fname = mangled_name;
972 } else {
973 fname = dname;
976 got_match = mask_match(fname, mask,
977 state->case_sensitive);
979 if(!got_match && state->check_mangled_names &&
980 !mangle_is_8_3(fname, false, state->conn->params)) {
982 * It turns out that NT matches wildcards against
983 * both long *and* short names. This may explain some
984 * of the wildcard weirdness from old DOS clients
985 * that some people have been seeing.... JRA.
987 /* Force the mangling into 8.3. */
988 ok = name_to_8_3(fname, mangled_name,
989 false, state->conn->params);
990 if (!ok) {
991 return false;
994 got_match = mask_match(mangled_name, mask,
995 state->case_sensitive);
998 if (!got_match) {
999 return false;
1002 *_fname = talloc_strdup(ctx, fname);
1003 if (*_fname == NULL) {
1004 return false;
1007 return true;
1010 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1012 uint32_t ea_size = IO_REPARSE_TAG_DFS;
1014 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1015 (void)fsctl_get_reparse_tag(fsp, &ea_size);
1016 } else {
1017 ea_size = estimate_ea_size(fsp);
1020 return ea_size;
1023 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1024 connection_struct *conn,
1025 uint16_t flags2,
1026 uint32_t info_level,
1027 struct ea_list *name_list,
1028 bool check_mangled_names,
1029 bool requires_resume_key,
1030 uint32_t mode,
1031 const char *fname,
1032 const struct smb_filename *smb_fname,
1033 int space_remaining,
1034 uint8_t align,
1035 bool do_pad,
1036 char *base_data,
1037 char **ppdata,
1038 char *end_data,
1039 uint64_t *last_entry_off)
1041 char *p, *q, *pdata = *ppdata;
1042 uint32_t reskey=0;
1043 uint64_t file_size = 0;
1044 uint64_t allocation_size = 0;
1045 uint64_t file_id = 0;
1046 size_t len = 0;
1047 struct timespec mdate_ts = {0};
1048 struct timespec adate_ts = {0};
1049 struct timespec cdate_ts = {0};
1050 struct timespec create_date_ts = {0};
1051 char *nameptr;
1052 char *last_entry_ptr;
1053 bool was_8_3;
1054 int off;
1055 int pad = 0;
1056 NTSTATUS status;
1057 struct readdir_attr_data *readdir_attr_data = NULL;
1058 uint32_t ea_size;
1060 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1061 file_size = get_file_size_stat(&smb_fname->st);
1063 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1066 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1067 * a DFS symlink.
1069 if (smb_fname->fsp != NULL &&
1070 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1071 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1072 ctx,
1073 &readdir_attr_data);
1074 if (!NT_STATUS_IS_OK(status)) {
1075 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1076 status)) {
1077 return status;
1082 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1084 mdate_ts = smb_fname->st.st_ex_mtime;
1085 adate_ts = smb_fname->st.st_ex_atime;
1086 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1087 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1089 if (lp_dos_filetime_resolution(SNUM(conn))) {
1090 dos_filetime_timespec(&create_date_ts);
1091 dos_filetime_timespec(&mdate_ts);
1092 dos_filetime_timespec(&adate_ts);
1093 dos_filetime_timespec(&cdate_ts);
1096 /* align the record */
1097 SMB_ASSERT(align >= 1);
1099 off = (int)PTR_DIFF(pdata, base_data);
1100 pad = (off + (align-1)) & ~(align-1);
1101 pad -= off;
1103 if (pad && pad > space_remaining) {
1104 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1105 "for padding (wanted %u, had %d)\n",
1106 (unsigned int)pad,
1107 space_remaining ));
1108 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1111 off += pad;
1112 /* initialize padding to 0 */
1113 if (pad) {
1114 memset(pdata, 0, pad);
1116 space_remaining -= pad;
1118 DBG_DEBUG("space_remaining = %d\n", space_remaining);
1120 pdata += pad;
1121 p = pdata;
1122 last_entry_ptr = p;
1124 pad = 0;
1125 off = 0;
1127 switch (info_level) {
1128 case SMB_FIND_INFO_STANDARD:
1129 DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1130 if(requires_resume_key) {
1131 SIVAL(p,0,reskey);
1132 p += 4;
1134 srv_put_dos_date2_ts(p, 0, create_date_ts);
1135 srv_put_dos_date2_ts(p, 4, adate_ts);
1136 srv_put_dos_date2_ts(p, 8, mdate_ts);
1137 SIVAL(p,12,(uint32_t)file_size);
1138 SIVAL(p,16,(uint32_t)allocation_size);
1139 SSVAL(p,20,mode);
1140 p += 23;
1141 nameptr = p;
1142 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1143 p += ucs2_align(base_data, p, 0);
1145 status = srvstr_push(base_data, flags2, p,
1146 fname, PTR_DIFF(end_data, p),
1147 STR_TERMINATE, &len);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 return status;
1151 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1152 if (len > 2) {
1153 SCVAL(nameptr, -1, len - 2);
1154 } else {
1155 SCVAL(nameptr, -1, 0);
1157 } else {
1158 if (len > 1) {
1159 SCVAL(nameptr, -1, len - 1);
1160 } else {
1161 SCVAL(nameptr, -1, 0);
1164 p += len;
1165 break;
1167 case SMB_FIND_EA_SIZE:
1168 DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1169 if (requires_resume_key) {
1170 SIVAL(p,0,reskey);
1171 p += 4;
1173 srv_put_dos_date2_ts(p, 0, create_date_ts);
1174 srv_put_dos_date2_ts(p, 4, adate_ts);
1175 srv_put_dos_date2_ts(p, 8, mdate_ts);
1176 SIVAL(p,12,(uint32_t)file_size);
1177 SIVAL(p,16,(uint32_t)allocation_size);
1178 SSVAL(p,20,mode);
1180 ea_size = estimate_ea_size(smb_fname->fsp);
1181 SIVAL(p,22,ea_size); /* Extended attributes */
1183 p += 27;
1184 nameptr = p - 1;
1185 status = srvstr_push(base_data, flags2,
1186 p, fname, PTR_DIFF(end_data, p),
1187 STR_TERMINATE | STR_NOALIGN, &len);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 return status;
1191 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1192 if (len > 2) {
1193 len -= 2;
1194 } else {
1195 len = 0;
1197 } else {
1198 if (len > 1) {
1199 len -= 1;
1200 } else {
1201 len = 0;
1204 SCVAL(nameptr,0,len);
1205 p += len;
1206 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1207 break;
1209 case SMB_FIND_EA_LIST:
1211 struct ea_list *file_list = NULL;
1212 size_t ea_len = 0;
1214 DBG_DEBUG("SMB_FIND_EA_LIST\n");
1215 if (!name_list) {
1216 return NT_STATUS_INVALID_PARAMETER;
1218 if (requires_resume_key) {
1219 SIVAL(p,0,reskey);
1220 p += 4;
1222 srv_put_dos_date2_ts(p, 0, create_date_ts);
1223 srv_put_dos_date2_ts(p, 4, adate_ts);
1224 srv_put_dos_date2_ts(p, 8, mdate_ts);
1225 SIVAL(p,12,(uint32_t)file_size);
1226 SIVAL(p,16,(uint32_t)allocation_size);
1227 SSVAL(p,20,mode);
1228 p += 22; /* p now points to the EA area. */
1230 status = get_ea_list_from_fsp(ctx,
1231 smb_fname->fsp,
1232 &ea_len, &file_list);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 file_list = NULL;
1236 name_list = ea_list_union(name_list, file_list, &ea_len);
1238 /* We need to determine if this entry will fit in the space available. */
1239 /* Max string size is 255 bytes. */
1240 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1241 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1242 "(wanted %u, had %d)\n",
1243 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1244 space_remaining ));
1245 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1248 /* Push the ea_data followed by the name. */
1249 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1250 nameptr = p;
1251 status = srvstr_push(base_data, flags2,
1252 p + 1, fname, PTR_DIFF(end_data, p+1),
1253 STR_TERMINATE | STR_NOALIGN, &len);
1254 if (!NT_STATUS_IS_OK(status)) {
1255 return status;
1257 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1258 if (len > 2) {
1259 len -= 2;
1260 } else {
1261 len = 0;
1263 } else {
1264 if (len > 1) {
1265 len -= 1;
1266 } else {
1267 len = 0;
1270 SCVAL(nameptr,0,len);
1271 p += len + 1;
1272 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1273 break;
1276 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1277 DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1278 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1279 p += 4;
1280 SIVAL(p,0,reskey); p += 4;
1281 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1282 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1283 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1284 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1285 SOFF_T(p,0,file_size); p += 8;
1286 SOFF_T(p,0,allocation_size); p += 8;
1287 SIVAL(p,0,mode); p += 4;
1288 q = p; p += 4; /* q is placeholder for name length. */
1289 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1290 SIVAL(p, 0, ea_size);
1291 p += 4;
1292 /* Clear the short name buffer. This is
1293 * IMPORTANT as not doing so will trigger
1294 * a Win2k client bug. JRA.
1296 if (!was_8_3 && check_mangled_names) {
1297 char mangled_name[13]; /* mangled 8.3 name. */
1298 if (!name_to_8_3(fname,mangled_name,True,
1299 conn->params)) {
1300 /* Error - mangle failed ! */
1301 memset(mangled_name,'\0',12);
1303 mangled_name[12] = 0;
1304 status = srvstr_push(base_data, flags2,
1305 p+2, mangled_name, 24,
1306 STR_UPPER|STR_UNICODE, &len);
1307 if (!NT_STATUS_IS_OK(status)) {
1308 return status;
1310 if (len < 24) {
1311 memset(p + 2 + len,'\0',24 - len);
1313 SSVAL(p, 0, len);
1314 } else {
1315 memset(p,'\0',26);
1317 p += 2 + 24;
1318 status = srvstr_push(base_data, flags2, p,
1319 fname, PTR_DIFF(end_data, p),
1320 STR_TERMINATE_ASCII, &len);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 return status;
1324 SIVAL(q,0,len);
1325 p += len;
1327 len = PTR_DIFF(p, pdata);
1328 pad = (len + (align-1)) & ~(align-1);
1330 * offset to the next entry, the caller
1331 * will overwrite it for the last entry
1332 * that's why we always include the padding
1334 SIVAL(pdata,0,pad);
1336 * set padding to zero
1338 if (do_pad) {
1339 memset(p, 0, pad - len);
1340 p = pdata + pad;
1341 } else {
1342 p = pdata + len;
1344 break;
1346 case SMB_FIND_FILE_DIRECTORY_INFO:
1347 DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1348 p += 4;
1349 SIVAL(p,0,reskey); p += 4;
1350 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1351 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1352 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1353 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1354 SOFF_T(p,0,file_size); p += 8;
1355 SOFF_T(p,0,allocation_size); p += 8;
1356 SIVAL(p,0,mode); p += 4;
1357 status = srvstr_push(base_data, flags2,
1358 p + 4, fname, PTR_DIFF(end_data, p+4),
1359 STR_TERMINATE_ASCII, &len);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 return status;
1363 SIVAL(p,0,len);
1364 p += 4 + len;
1366 len = PTR_DIFF(p, pdata);
1367 pad = (len + (align-1)) & ~(align-1);
1369 * offset to the next entry, the caller
1370 * will overwrite it for the last entry
1371 * that's why we always include the padding
1373 SIVAL(pdata,0,pad);
1375 * set padding to zero
1377 if (do_pad) {
1378 memset(p, 0, pad - len);
1379 p = pdata + pad;
1380 } else {
1381 p = pdata + len;
1383 break;
1385 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1386 DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1387 p += 4;
1388 SIVAL(p,0,reskey); p += 4;
1389 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1390 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1391 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1392 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1393 SOFF_T(p,0,file_size); p += 8;
1394 SOFF_T(p,0,allocation_size); p += 8;
1395 SIVAL(p,0,mode); p += 4;
1396 q = p; p += 4; /* q is placeholder for name length. */
1397 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1398 SIVAL(p, 0, ea_size);
1399 p +=4;
1400 status = srvstr_push(base_data, flags2, p,
1401 fname, PTR_DIFF(end_data, p),
1402 STR_TERMINATE_ASCII, &len);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 return status;
1406 SIVAL(q, 0, len);
1407 p += len;
1409 len = PTR_DIFF(p, pdata);
1410 pad = (len + (align-1)) & ~(align-1);
1412 * offset to the next entry, the caller
1413 * will overwrite it for the last entry
1414 * that's why we always include the padding
1416 SIVAL(pdata,0,pad);
1418 * set padding to zero
1420 if (do_pad) {
1421 memset(p, 0, pad - len);
1422 p = pdata + pad;
1423 } else {
1424 p = pdata + len;
1426 break;
1428 case SMB_FIND_FILE_NAMES_INFO:
1429 DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1430 p += 4;
1431 SIVAL(p,0,reskey); p += 4;
1432 p += 4;
1433 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1434 acl on a dir (tridge) */
1435 status = srvstr_push(base_data, flags2, p,
1436 fname, PTR_DIFF(end_data, p),
1437 STR_TERMINATE_ASCII, &len);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 return status;
1441 SIVAL(p, -4, len);
1442 p += len;
1444 len = PTR_DIFF(p, pdata);
1445 pad = (len + (align-1)) & ~(align-1);
1447 * offset to the next entry, the caller
1448 * will overwrite it for the last entry
1449 * that's why we always include the padding
1451 SIVAL(pdata,0,pad);
1453 * set padding to zero
1455 if (do_pad) {
1456 memset(p, 0, pad - len);
1457 p = pdata + pad;
1458 } else {
1459 p = pdata + len;
1461 break;
1463 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1464 DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1465 p += 4;
1466 SIVAL(p,0,reskey); p += 4;
1467 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1468 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1469 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1470 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1471 SOFF_T(p,0,file_size); p += 8;
1472 SOFF_T(p,0,allocation_size); p += 8;
1473 SIVAL(p,0,mode); p += 4;
1474 q = p; p += 4; /* q is placeholder for name length. */
1475 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1476 SIVAL(p, 0, ea_size);
1477 p += 4;
1478 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1479 SBVAL(p,0,file_id); p += 8;
1480 status = srvstr_push(base_data, flags2, p,
1481 fname, PTR_DIFF(end_data, p),
1482 STR_TERMINATE_ASCII, &len);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 return status;
1486 SIVAL(q, 0, len);
1487 p += len;
1489 len = PTR_DIFF(p, pdata);
1490 pad = (len + (align-1)) & ~(align-1);
1492 * offset to the next entry, the caller
1493 * will overwrite it for the last entry
1494 * that's why we always include the padding
1496 SIVAL(pdata,0,pad);
1498 * set padding to zero
1500 if (do_pad) {
1501 memset(p, 0, pad - len);
1502 p = pdata + pad;
1503 } else {
1504 p = pdata + len;
1506 break;
1508 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1509 DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1510 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1511 p += 4;
1512 SIVAL(p,0,reskey); p += 4;
1513 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1514 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1515 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1516 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1517 SOFF_T(p,0,file_size); p += 8;
1518 SOFF_T(p,0,allocation_size); p += 8;
1519 SIVAL(p,0,mode); p += 4;
1520 q = p; p += 4; /* q is placeholder for name length */
1521 if (readdir_attr_data &&
1522 readdir_attr_data->type == RDATTR_AAPL) {
1524 * OS X specific SMB2 extension negotiated via
1525 * AAPL create context: return max_access in
1526 * ea_size field.
1528 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1529 } else {
1530 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1532 SIVAL(p,0,ea_size); /* Extended attributes */
1533 p += 4;
1535 if (readdir_attr_data &&
1536 readdir_attr_data->type == RDATTR_AAPL) {
1538 * OS X specific SMB2 extension negotiated via
1539 * AAPL create context: return resource fork
1540 * length and compressed FinderInfo in
1541 * shortname field.
1543 * According to documentation short_name_len
1544 * should be 0, but on the wire behaviour
1545 * shows its set to 24 by clients.
1547 SSVAL(p, 0, 24);
1549 /* Resourefork length */
1550 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1552 /* Compressed FinderInfo */
1553 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1554 } else if (!was_8_3 && check_mangled_names) {
1555 char mangled_name[13]; /* mangled 8.3 name. */
1556 if (!name_to_8_3(fname,mangled_name,True,
1557 conn->params)) {
1558 /* Error - mangle failed ! */
1559 memset(mangled_name,'\0',12);
1561 mangled_name[12] = 0;
1562 status = srvstr_push(base_data, flags2,
1563 p+2, mangled_name, 24,
1564 STR_UPPER|STR_UNICODE, &len);
1565 if (!NT_STATUS_IS_OK(status)) {
1566 return status;
1568 SSVAL(p, 0, len);
1569 if (len < 24) {
1570 memset(p + 2 + len,'\0',24 - len);
1572 SSVAL(p, 0, len);
1573 } else {
1574 /* Clear the short name buffer. This is
1575 * IMPORTANT as not doing so will trigger
1576 * a Win2k client bug. JRA.
1578 memset(p,'\0',26);
1580 p += 26;
1582 /* Reserved ? */
1583 if (readdir_attr_data &&
1584 readdir_attr_data->type == RDATTR_AAPL) {
1586 * OS X specific SMB2 extension negotiated via
1587 * AAPL create context: return UNIX mode in
1588 * reserved field.
1590 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1591 SSVAL(p, 0, aapl_mode);
1592 } else {
1593 SSVAL(p, 0, 0);
1595 p += 2;
1597 SBVAL(p,0,file_id); p += 8;
1598 status = srvstr_push(base_data, flags2, p,
1599 fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE_ASCII, &len);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 return status;
1604 SIVAL(q,0,len);
1605 p += len;
1607 len = PTR_DIFF(p, pdata);
1608 pad = (len + (align-1)) & ~(align-1);
1610 * offset to the next entry, the caller
1611 * will overwrite it for the last entry
1612 * that's why we always include the padding
1614 SIVAL(pdata,0,pad);
1616 * set padding to zero
1618 if (do_pad) {
1619 memset(p, 0, pad - len);
1620 p = pdata + pad;
1621 } else {
1622 p = pdata + len;
1624 break;
1626 /* CIFS UNIX Extension. */
1628 case SMB_FIND_FILE_UNIX:
1629 case SMB_FIND_FILE_UNIX_INFO2:
1630 p+= 4;
1631 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1633 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1635 if (info_level == SMB_FIND_FILE_UNIX) {
1636 DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1637 p = store_file_unix_basic(conn, p,
1638 NULL, &smb_fname->st);
1639 status = srvstr_push(base_data, flags2, p,
1640 fname, PTR_DIFF(end_data, p),
1641 STR_TERMINATE, &len);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 return status;
1645 } else {
1646 DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1647 p = store_file_unix_basic_info2(conn, p,
1648 NULL, &smb_fname->st);
1649 nameptr = p;
1650 p += 4;
1651 status = srvstr_push(base_data, flags2, p, fname,
1652 PTR_DIFF(end_data, p), 0, &len);
1653 if (!NT_STATUS_IS_OK(status)) {
1654 return status;
1656 SIVAL(nameptr, 0, len);
1659 p += len;
1661 len = PTR_DIFF(p, pdata);
1662 pad = (len + (align-1)) & ~(align-1);
1664 * offset to the next entry, the caller
1665 * will overwrite it for the last entry
1666 * that's why we always include the padding
1668 SIVAL(pdata,0,pad);
1670 * set padding to zero
1672 if (do_pad) {
1673 memset(p, 0, pad - len);
1674 p = pdata + pad;
1675 } else {
1676 p = pdata + len;
1678 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1680 break;
1682 /* SMB2 UNIX Extension. */
1684 case SMB2_FILE_POSIX_INFORMATION:
1686 struct smb3_file_posix_information info = {};
1687 uint8_t buf[sizeof(info)];
1688 struct ndr_push ndr = {
1689 .data = buf,
1690 .alloc_size = sizeof(buf),
1691 .fixed_buf_size = true,
1693 enum ndr_err_code ndr_err;
1694 uint32_t tag = 0;
1696 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1698 p+= 4;
1699 SIVAL(p,0,reskey); p+= 4;
1701 if (!conn_using_smb2(conn->sconn)) {
1702 return NT_STATUS_INVALID_LEVEL;
1705 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1706 status = fsctl_get_reparse_tag(smb_fname->fsp,
1707 &tag);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 DBG_DEBUG("Could not get reparse "
1710 "tag for %s: %s\n",
1711 smb_fname_str_dbg(smb_fname),
1712 nt_errstr(status));
1713 return status;
1717 smb3_file_posix_information_init(
1718 conn, &smb_fname->st, tag, mode, &info);
1720 ndr_err = ndr_push_smb3_file_posix_information(
1721 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1722 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1723 return NT_STATUS_INSUFFICIENT_RESOURCES;
1726 memcpy(p, buf, ndr.offset);
1727 p += ndr.offset;
1729 nameptr = p;
1730 p += 4;
1731 status = srvstr_push(base_data, flags2, p, fname,
1732 PTR_DIFF(end_data, p), 0, &len);
1733 if (!NT_STATUS_IS_OK(status)) {
1734 return status;
1736 SIVAL(nameptr, 0, len);
1738 p += len;
1740 len = PTR_DIFF(p, pdata);
1741 pad = (len + (align-1)) & ~(align-1);
1743 * offset to the next entry, the caller
1744 * will overwrite it for the last entry
1745 * that's why we always include the padding
1747 SIVAL(pdata,0,pad);
1748 break;
1751 default:
1752 return NT_STATUS_INVALID_LEVEL;
1755 if (PTR_DIFF(p,pdata) > space_remaining) {
1756 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1757 "(wanted %u, had %d)\n",
1758 (unsigned int)PTR_DIFF(p,pdata),
1759 space_remaining ));
1760 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1763 /* Setup the last entry pointer, as an offset from base_data */
1764 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1765 /* Advance the data pointer to the next slot */
1766 *ppdata = p;
1768 return NT_STATUS_OK;
1771 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1772 connection_struct *conn,
1773 struct dptr_struct *dirptr,
1774 uint16_t flags2,
1775 const char *path_mask,
1776 uint32_t dirtype,
1777 int info_level,
1778 int requires_resume_key,
1779 bool dont_descend,
1780 bool ask_sharemode,
1781 bool get_dosmode,
1782 uint8_t align,
1783 bool do_pad,
1784 char **ppdata,
1785 char *base_data,
1786 char *end_data,
1787 int space_remaining,
1788 struct smb_filename **_smb_fname,
1789 int *_last_entry_off,
1790 struct ea_list *name_list,
1791 struct file_id *file_id)
1793 const char *p;
1794 const char *mask = NULL;
1795 uint32_t mode = 0;
1796 char *fname = NULL;
1797 struct smb_filename *smb_fname = NULL;
1798 struct smbd_dirptr_lanman2_state state;
1799 bool ok;
1800 uint64_t last_entry_off = 0;
1801 NTSTATUS status;
1802 enum mangled_names_options mangled_names;
1803 bool marshall_with_83_names;
1805 mangled_names = lp_mangled_names(conn->params);
1807 ZERO_STRUCT(state);
1808 state.conn = conn;
1809 state.info_level = info_level;
1810 if (mangled_names != MANGLED_NAMES_NO) {
1811 state.check_mangled_names = true;
1813 state.case_sensitive = dptr_case_sensitive(dirptr);
1815 p = strrchr_m(path_mask,'/');
1816 if(p != NULL) {
1817 if(p[1] == '\0') {
1818 mask = "*.*";
1819 } else {
1820 mask = p+1;
1822 } else {
1823 mask = path_mask;
1826 ok = smbd_dirptr_get_entry(ctx,
1827 dirptr,
1828 mask,
1829 dirtype,
1830 dont_descend,
1831 ask_sharemode,
1832 get_dosmode,
1833 smbd_dirptr_lanman2_match_fn,
1834 &state,
1835 &fname,
1836 &smb_fname,
1837 &mode);
1838 if (!ok) {
1839 return NT_STATUS_END_OF_FILE;
1842 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1844 status = smbd_marshall_dir_entry(ctx,
1845 conn,
1846 flags2,
1847 info_level,
1848 name_list,
1849 marshall_with_83_names,
1850 requires_resume_key,
1851 mode,
1852 fname,
1853 smb_fname,
1854 space_remaining,
1855 align,
1856 do_pad,
1857 base_data,
1858 ppdata,
1859 end_data,
1860 &last_entry_off);
1861 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1862 DEBUG(1,("Conversion error: illegal character: %s\n",
1863 smb_fname_str_dbg(smb_fname)));
1866 if (file_id != NULL) {
1867 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1870 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1871 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1874 if (!NT_STATUS_IS_OK(status)) {
1875 TALLOC_FREE(smb_fname);
1876 TALLOC_FREE(fname);
1877 return status;
1880 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1882 if (_smb_fname != NULL) {
1884 * smb_fname is already talloc'ed off ctx.
1885 * We just need to make sure we don't return
1886 * any stream_name, and replace base_name
1887 * with fname in case base_name got mangled.
1888 * This allows us to preserve any smb_fname->fsp
1889 * for asynchronous handle lookups.
1891 TALLOC_FREE(smb_fname->stream_name);
1894 * smbd_dirptr_set_last_name_sent() above consumed
1895 * base_name
1897 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1899 if (smb_fname->base_name == NULL) {
1900 TALLOC_FREE(smb_fname);
1901 TALLOC_FREE(fname);
1902 return NT_STATUS_NO_MEMORY;
1904 *_smb_fname = smb_fname;
1905 } else {
1906 TALLOC_FREE(smb_fname);
1908 TALLOC_FREE(fname);
1910 *_last_entry_off = last_entry_off;
1911 return NT_STATUS_OK;
1914 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1916 const struct loadparm_substitution *lp_sub =
1917 loadparm_s3_global_substitution();
1919 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1920 return objid;
1923 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1925 SMB_ASSERT(extended_info != NULL);
1927 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1928 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1929 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1930 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1931 #ifdef SAMBA_VERSION_REVISION
1932 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1933 #endif
1934 extended_info->samba_subversion = 0;
1935 #ifdef SAMBA_VERSION_RC_RELEASE
1936 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1937 #else
1938 #ifdef SAMBA_VERSION_PRE_RELEASE
1939 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1940 #endif
1941 #endif
1942 #ifdef SAMBA_VERSION_VENDOR_PATCH
1943 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1944 #endif
1945 extended_info->samba_gitcommitdate = 0;
1946 #ifdef SAMBA_VERSION_COMMIT_TIME
1947 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1948 #endif
1950 memset(extended_info->samba_version_string, 0,
1951 sizeof(extended_info->samba_version_string));
1953 snprintf (extended_info->samba_version_string,
1954 sizeof(extended_info->samba_version_string),
1955 "%s", samba_version_string());
1958 static bool fsinfo_unix_valid_level(connection_struct *conn,
1959 struct files_struct *fsp,
1960 uint16_t info_level)
1962 if (conn_using_smb2(conn->sconn) &&
1963 fsp->fsp_flags.posix_open &&
1964 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
1966 return true;
1968 #if defined(SMB1SERVER)
1969 if (lp_smb1_unix_extensions() &&
1970 info_level == SMB_QUERY_POSIX_FS_INFO) {
1971 return true;
1973 #endif
1974 return false;
1978 * fsp is only valid for SMB2.
1980 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1981 connection_struct *conn,
1982 TALLOC_CTX *mem_ctx,
1983 uint16_t info_level,
1984 uint16_t flags2,
1985 unsigned int max_data_bytes,
1986 size_t *fixed_portion,
1987 struct files_struct *fsp,
1988 struct smb_filename *fname,
1989 char **ppdata,
1990 int *ret_data_len)
1992 const struct loadparm_substitution *lp_sub =
1993 loadparm_s3_global_substitution();
1994 char *pdata, *end_data;
1995 int data_len = 0;
1996 size_t len = 0;
1997 const char *vname = volume_label(talloc_tos(), SNUM(conn));
1998 int snum = SNUM(conn);
1999 const char *fstype = lp_fstype(SNUM(conn));
2000 const char *filename = NULL;
2001 uint64_t bytes_per_sector = 512;
2002 struct smb_filename smb_fname;
2003 SMB_STRUCT_STAT st;
2004 NTSTATUS status = NT_STATUS_OK;
2005 uint64_t df_ret;
2006 uint32_t serial;
2008 if (fname == NULL || fname->base_name == NULL) {
2009 filename = ".";
2010 } else {
2011 filename = fname->base_name;
2014 if (IS_IPC(conn)) {
2015 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2016 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2017 "info level (0x%x) on IPC$.\n",
2018 (unsigned int)info_level));
2019 return NT_STATUS_ACCESS_DENIED;
2023 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2025 smb_fname = (struct smb_filename) {
2026 .base_name = discard_const_p(char, filename),
2027 .flags = fname ? fname->flags : 0,
2028 .twrp = fname ? fname->twrp : 0,
2031 if(info_level != SMB_FS_QUOTA_INFORMATION
2032 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2033 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2034 return map_nt_error_from_unix(errno);
2037 st = smb_fname.st;
2039 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2040 return NT_STATUS_INVALID_PARAMETER;
2043 *ppdata = (char *)SMB_REALLOC(
2044 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2045 if (*ppdata == NULL) {
2046 return NT_STATUS_NO_MEMORY;
2049 pdata = *ppdata;
2050 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2051 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2053 *fixed_portion = 0;
2055 switch (info_level) {
2056 case SMB_INFO_ALLOCATION:
2058 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2059 data_len = 18;
2060 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2061 &dfree, &dsize);
2062 if (df_ret == (uint64_t)-1) {
2063 return map_nt_error_from_unix(errno);
2066 block_size = lp_block_size(snum);
2067 if (bsize < block_size) {
2068 uint64_t factor = block_size/bsize;
2069 bsize = block_size;
2070 dsize /= factor;
2071 dfree /= factor;
2073 if (bsize > block_size) {
2074 uint64_t factor = bsize/block_size;
2075 bsize = block_size;
2076 dsize *= factor;
2077 dfree *= factor;
2079 sectors_per_unit = bsize/bytes_per_sector;
2081 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2082 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2083 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2086 * For large drives, return max values and not modulo.
2088 dsize = MIN(dsize, UINT32_MAX);
2089 dfree = MIN(dfree, UINT32_MAX);
2091 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2092 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2093 SIVAL(pdata,l1_cUnit,dsize);
2094 SIVAL(pdata,l1_cUnitAvail,dfree);
2095 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2096 break;
2099 case SMB_INFO_VOLUME:
2100 /* Return volume name */
2102 * Add volume serial number - hash of a combination of
2103 * the called hostname and the service name.
2105 serial = generate_volume_serial_number(lp_sub, snum);
2106 SIVAL(pdata,0,serial);
2108 * Win2k3 and previous mess this up by sending a name length
2109 * one byte short. I believe only older clients (OS/2 Win9x) use
2110 * this call so try fixing this by adding a terminating null to
2111 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2113 status = srvstr_push(
2114 pdata, flags2,
2115 pdata+l2_vol_szVolLabel, vname,
2116 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2117 STR_NOALIGN|STR_TERMINATE, &len);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 return status;
2121 SCVAL(pdata,l2_vol_cch,len);
2122 data_len = l2_vol_szVolLabel + len;
2123 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2124 "name = %s serial = 0x%04"PRIx32"\n",
2125 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2126 (unsigned)len, vname, serial));
2127 break;
2129 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2130 case SMB_FS_ATTRIBUTE_INFORMATION:
2132 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2133 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2134 conn->fs_capabilities); /* FS ATTRIBUTES */
2136 SIVAL(pdata,4,255); /* Max filename component length */
2137 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2138 and will think we can't do long filenames */
2139 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2140 PTR_DIFF(end_data, pdata+12),
2141 STR_UNICODE, &len);
2142 if (!NT_STATUS_IS_OK(status)) {
2143 return status;
2145 SIVAL(pdata,8,len);
2146 data_len = 12 + len;
2147 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2148 /* the client only requested a portion of the
2149 file system name */
2150 data_len = max_data_bytes;
2151 status = STATUS_BUFFER_OVERFLOW;
2153 *fixed_portion = 16;
2154 break;
2156 case SMB_QUERY_FS_LABEL_INFO:
2157 case SMB_FS_LABEL_INFORMATION:
2158 status = srvstr_push(pdata, flags2, pdata+4, vname,
2159 PTR_DIFF(end_data, pdata+4), 0, &len);
2160 if (!NT_STATUS_IS_OK(status)) {
2161 return status;
2163 data_len = 4 + len;
2164 SIVAL(pdata,0,len);
2165 break;
2167 case SMB_QUERY_FS_VOLUME_INFO:
2168 case SMB_FS_VOLUME_INFORMATION:
2169 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2170 pdata, &st.st_ex_btime);
2172 * Add volume serial number - hash of a combination of
2173 * the called hostname and the service name.
2175 serial = generate_volume_serial_number(lp_sub, snum);
2176 SIVAL(pdata,8,serial);
2178 /* Max label len is 32 characters. */
2179 status = srvstr_push(pdata, flags2, pdata+18, vname,
2180 PTR_DIFF(end_data, pdata+18),
2181 STR_UNICODE, &len);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 return status;
2185 SIVAL(pdata,12,len);
2186 data_len = 18+len;
2188 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2189 "namelen = %d, vol=%s serv=%s "
2190 "serial=0x%04"PRIx32"\n",
2191 (int)strlen(vname),vname,
2192 lp_servicename(talloc_tos(), lp_sub, snum),
2193 serial));
2194 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2195 /* the client only requested a portion of the
2196 volume label */
2197 data_len = max_data_bytes;
2198 status = STATUS_BUFFER_OVERFLOW;
2200 *fixed_portion = 24;
2201 break;
2203 case SMB_QUERY_FS_SIZE_INFO:
2204 case SMB_FS_SIZE_INFORMATION:
2206 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2207 data_len = 24;
2208 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2209 &dfree, &dsize);
2210 if (df_ret == (uint64_t)-1) {
2211 return map_nt_error_from_unix(errno);
2213 block_size = lp_block_size(snum);
2214 if (bsize < block_size) {
2215 uint64_t factor = block_size/bsize;
2216 bsize = block_size;
2217 dsize /= factor;
2218 dfree /= factor;
2220 if (bsize > block_size) {
2221 uint64_t factor = bsize/block_size;
2222 bsize = block_size;
2223 dsize *= factor;
2224 dfree *= factor;
2226 sectors_per_unit = bsize/bytes_per_sector;
2227 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2228 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2229 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2230 SBIG_UINT(pdata,0,dsize);
2231 SBIG_UINT(pdata,8,dfree);
2232 SIVAL(pdata,16,sectors_per_unit);
2233 SIVAL(pdata,20,bytes_per_sector);
2234 *fixed_portion = 24;
2235 break;
2238 case SMB_FS_FULL_SIZE_INFORMATION:
2240 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2241 data_len = 32;
2242 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2243 &dfree, &dsize);
2244 if (df_ret == (uint64_t)-1) {
2245 return map_nt_error_from_unix(errno);
2247 block_size = lp_block_size(snum);
2248 if (bsize < block_size) {
2249 uint64_t factor = block_size/bsize;
2250 bsize = block_size;
2251 dsize /= factor;
2252 dfree /= factor;
2254 if (bsize > block_size) {
2255 uint64_t factor = bsize/block_size;
2256 bsize = block_size;
2257 dsize *= factor;
2258 dfree *= factor;
2260 sectors_per_unit = bsize/bytes_per_sector;
2261 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2262 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2263 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2264 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2265 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2266 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2267 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2268 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2269 *fixed_portion = 32;
2270 break;
2273 case SMB_QUERY_FS_DEVICE_INFO:
2274 case SMB_FS_DEVICE_INFORMATION:
2276 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2278 if (!CAN_WRITE(conn)) {
2279 characteristics |= FILE_READ_ONLY_DEVICE;
2281 data_len = 8;
2282 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2283 SIVAL(pdata,4,characteristics);
2284 *fixed_portion = 8;
2285 break;
2288 #ifdef HAVE_SYS_QUOTAS
2289 case SMB_FS_QUOTA_INFORMATION:
2291 * what we have to send --metze:
2293 * Unknown1: 24 NULL bytes
2294 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2295 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2296 * Quota Flags: 2 byte :
2297 * Unknown3: 6 NULL bytes
2299 * 48 bytes total
2301 * details for Quota Flags:
2303 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2304 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2305 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2306 * 0x0001 Enable Quotas: enable quota for this fs
2310 /* we need to fake up a fsp here,
2311 * because its not send in this call
2313 files_struct tmpfsp = {
2314 .conn = conn,
2315 .fnum = FNUM_FIELD_INVALID,
2317 SMB_NTQUOTA_STRUCT quotas = {};
2319 /* access check */
2320 if (get_current_uid(conn) != 0) {
2321 DEBUG(0,("get_user_quota: access_denied "
2322 "service [%s] user [%s]\n",
2323 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2324 conn->session_info->unix_info->unix_name));
2325 return NT_STATUS_ACCESS_DENIED;
2328 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2329 NULL, &quotas);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2332 return status;
2335 data_len = 48;
2337 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2338 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2340 /* Unknown1 24 NULL bytes*/
2341 SBIG_UINT(pdata,0,(uint64_t)0);
2342 SBIG_UINT(pdata,8,(uint64_t)0);
2343 SBIG_UINT(pdata,16,(uint64_t)0);
2345 /* Default Soft Quota 8 bytes */
2346 SBIG_UINT(pdata,24,quotas.softlim);
2348 /* Default Hard Quota 8 bytes */
2349 SBIG_UINT(pdata,32,quotas.hardlim);
2351 /* Quota flag 2 bytes */
2352 SSVAL(pdata,40,quotas.qflags);
2354 /* Unknown3 6 NULL bytes */
2355 SSVAL(pdata,42,0);
2356 SIVAL(pdata,44,0);
2358 break;
2360 #endif /* HAVE_SYS_QUOTAS */
2361 case SMB_FS_OBJECTID_INFORMATION:
2363 unsigned char objid[16];
2364 struct smb_extended_info extended_info;
2365 memcpy(pdata,create_volume_objectid(conn, objid),16);
2366 samba_extended_info_version (&extended_info);
2367 SIVAL(pdata,16,extended_info.samba_magic);
2368 SIVAL(pdata,20,extended_info.samba_version);
2369 SIVAL(pdata,24,extended_info.samba_subversion);
2370 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2371 memcpy(pdata+36,extended_info.samba_version_string,28);
2372 data_len = 64;
2373 break;
2376 case SMB_FS_SECTOR_SIZE_INFORMATION:
2378 uint32_t bps_logical = lp_parm_ulong(
2379 SNUM(conn),
2380 "fs", "logical bytes per sector",
2381 bytes_per_sector);
2382 uint32_t bps_aligned = lp_parm_ulong(
2383 SNUM(conn),
2384 "fs", "aligned bytes per sector",
2385 bytes_per_sector);
2386 uint32_t bps_performance = lp_parm_ulong(
2387 SNUM(conn),
2388 "fs", "performance bytes per sector",
2389 bytes_per_sector);
2390 uint32_t bps_effective = lp_parm_ulong(
2391 SNUM(conn),
2392 "fs", "effective aligned bytes per sector",
2393 bytes_per_sector);
2395 data_len = 28;
2397 * These values match a physical Windows Server 2012
2398 * share backed by NTFS atop spinning rust.
2400 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2401 /* logical_bytes_per_sector */
2402 SIVAL(pdata, 0, bps_logical);
2403 /* phys_bytes_per_sector_atomic */
2404 SIVAL(pdata, 4, bps_aligned);
2405 /* phys_bytes_per_sector_perf */
2406 SIVAL(pdata, 8, bps_performance);
2407 /* fs_effective_phys_bytes_per_sector_atomic */
2408 SIVAL(pdata, 12, bps_effective);
2409 /* flags */
2410 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2411 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2412 /* byte_off_sector_align */
2413 SIVAL(pdata, 20, 0);
2414 /* byte_off_partition_align */
2415 SIVAL(pdata, 24, 0);
2416 *fixed_portion = 28;
2417 break;
2421 #if defined(WITH_SMB1SERVER)
2423 * Query the version and capabilities of the CIFS UNIX extensions
2424 * in use.
2427 case SMB_QUERY_CIFS_UNIX_INFO:
2429 bool large_write = lp_min_receive_file_size() &&
2430 !smb1_srv_is_signing_active(xconn);
2431 bool large_read = !smb1_srv_is_signing_active(xconn);
2432 int encrypt_caps = 0;
2434 if (!lp_smb1_unix_extensions()) {
2435 return NT_STATUS_INVALID_LEVEL;
2438 switch (conn->encrypt_level) {
2439 case SMB_SIGNING_OFF:
2440 encrypt_caps = 0;
2441 break;
2442 case SMB_SIGNING_DESIRED:
2443 case SMB_SIGNING_IF_REQUIRED:
2444 case SMB_SIGNING_DEFAULT:
2445 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2446 break;
2447 case SMB_SIGNING_REQUIRED:
2448 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2449 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2450 large_write = false;
2451 large_read = false;
2452 break;
2455 data_len = 12;
2456 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2457 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2459 /* We have POSIX ACLs, pathname, encryption,
2460 * large read/write, and locking capability. */
2462 SBIG_UINT(pdata,4,((uint64_t)(
2463 CIFS_UNIX_POSIX_ACLS_CAP|
2464 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2465 CIFS_UNIX_FCNTL_LOCKS_CAP|
2466 CIFS_UNIX_EXTATTR_CAP|
2467 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2468 encrypt_caps|
2469 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2470 (large_write ?
2471 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2472 break;
2474 #endif
2476 case SMB_QUERY_POSIX_FS_INFO:
2477 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2479 int rc;
2480 struct vfs_statvfs_struct svfs;
2482 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2483 return NT_STATUS_INVALID_LEVEL;
2486 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2488 if (!rc) {
2489 data_len = 56;
2490 SIVAL(pdata,0,svfs.OptimalTransferSize);
2491 SIVAL(pdata,4,svfs.BlockSize);
2492 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2493 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2494 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2495 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2496 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2497 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2499 #ifdef EOPNOTSUPP
2500 } else if (rc == EOPNOTSUPP) {
2501 return NT_STATUS_INVALID_LEVEL;
2502 #endif /* EOPNOTSUPP */
2503 } else {
2504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2505 return NT_STATUS_DOS(ERRSRV, ERRerror);
2507 break;
2510 case SMB_QUERY_POSIX_WHOAMI:
2512 uint32_t flags = 0;
2513 uint32_t sid_bytes;
2514 uint32_t i;
2516 if (!lp_smb1_unix_extensions()) {
2517 return NT_STATUS_INVALID_LEVEL;
2520 if (max_data_bytes < 40) {
2521 return NT_STATUS_BUFFER_TOO_SMALL;
2524 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2525 flags |= SMB_WHOAMI_GUEST;
2528 /* NOTE: 8 bytes for UID/GID, irrespective of native
2529 * platform size. This matches
2530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2532 data_len = 4 /* flags */
2533 + 4 /* flag mask */
2534 + 8 /* uid */
2535 + 8 /* gid */
2536 + 4 /* ngroups */
2537 + 4 /* num_sids */
2538 + 4 /* SID bytes */
2539 + 4 /* pad/reserved */
2540 + (conn->session_info->unix_token->ngroups * 8)
2541 /* groups list */
2542 + (conn->session_info->security_token->num_sids *
2543 SID_MAX_SIZE)
2544 /* SID list */;
2546 SIVAL(pdata, 0, flags);
2547 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2548 SBIG_UINT(pdata, 8,
2549 (uint64_t)conn->session_info->unix_token->uid);
2550 SBIG_UINT(pdata, 16,
2551 (uint64_t)conn->session_info->unix_token->gid);
2554 if (data_len >= max_data_bytes) {
2555 /* Potential overflow, skip the GIDs and SIDs. */
2557 SIVAL(pdata, 24, 0); /* num_groups */
2558 SIVAL(pdata, 28, 0); /* num_sids */
2559 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2560 SIVAL(pdata, 36, 0); /* reserved */
2562 data_len = 40;
2563 break;
2566 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2567 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2569 /* We walk the SID list twice, but this call is fairly
2570 * infrequent, and I don't expect that it's performance
2571 * sensitive -- jpeach
2573 for (i = 0, sid_bytes = 0;
2574 i < conn->session_info->security_token->num_sids; ++i) {
2575 sid_bytes += ndr_size_dom_sid(
2576 &conn->session_info->security_token->sids[i],
2580 /* SID list byte count */
2581 SIVAL(pdata, 32, sid_bytes);
2583 /* 4 bytes pad/reserved - must be zero */
2584 SIVAL(pdata, 36, 0);
2585 data_len = 40;
2587 /* GID list */
2588 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2589 SBIG_UINT(pdata, data_len,
2590 (uint64_t)conn->session_info->unix_token->groups[i]);
2591 data_len += 8;
2594 /* SID list */
2595 for (i = 0;
2596 i < conn->session_info->security_token->num_sids; ++i) {
2597 int sid_len = ndr_size_dom_sid(
2598 &conn->session_info->security_token->sids[i],
2601 sid_linearize((uint8_t *)(pdata + data_len),
2602 sid_len,
2603 &conn->session_info->security_token->sids[i]);
2604 data_len += sid_len;
2607 break;
2610 case SMB_MAC_QUERY_FS_INFO:
2612 * Thursby MAC extension... ONLY on NTFS filesystems
2613 * once we do streams then we don't need this
2615 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2616 data_len = 88;
2617 SIVAL(pdata,84,0x100); /* Don't support mac... */
2618 break;
2621 FALL_THROUGH;
2622 default:
2623 return NT_STATUS_INVALID_LEVEL;
2626 *ret_data_len = data_len;
2627 return status;
2630 NTSTATUS smb_set_fsquota(connection_struct *conn,
2631 struct smb_request *req,
2632 files_struct *fsp,
2633 const DATA_BLOB *qdata)
2635 const struct loadparm_substitution *lp_sub =
2636 loadparm_s3_global_substitution();
2637 NTSTATUS status;
2638 SMB_NTQUOTA_STRUCT quotas;
2640 ZERO_STRUCT(quotas);
2642 /* access check */
2643 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2644 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2645 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2646 conn->session_info->unix_info->unix_name);
2647 return NT_STATUS_ACCESS_DENIED;
2650 if (!check_fsp_ntquota_handle(conn, req,
2651 fsp)) {
2652 DBG_WARNING("no valid QUOTA HANDLE\n");
2653 return NT_STATUS_INVALID_HANDLE;
2656 /* note: normally there're 48 bytes,
2657 * but we didn't use the last 6 bytes for now
2658 * --metze
2660 if (qdata->length < 42) {
2661 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2662 qdata->length);
2663 return NT_STATUS_INVALID_PARAMETER;
2666 /* unknown_1 24 NULL bytes in pdata*/
2668 /* the soft quotas 8 bytes (uint64_t)*/
2669 quotas.softlim = BVAL(qdata->data,24);
2671 /* the hard quotas 8 bytes (uint64_t)*/
2672 quotas.hardlim = BVAL(qdata->data,32);
2674 /* quota_flags 2 bytes **/
2675 quotas.qflags = SVAL(qdata->data,40);
2677 /* unknown_2 6 NULL bytes follow*/
2679 /* now set the quotas */
2680 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2681 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2682 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2683 status = map_nt_error_from_unix(errno);
2684 } else {
2685 status = NT_STATUS_OK;
2687 return status;
2690 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2691 struct smb_request *req,
2692 TALLOC_CTX *mem_ctx,
2693 uint16_t info_level,
2694 files_struct *fsp,
2695 const DATA_BLOB *pdata)
2697 switch (info_level) {
2698 case SMB_FS_QUOTA_INFORMATION:
2700 return smb_set_fsquota(conn,
2701 req,
2702 fsp,
2703 pdata);
2706 default:
2707 break;
2709 return NT_STATUS_INVALID_LEVEL;
2712 /****************************************************************************
2713 Store the FILE_UNIX_BASIC info.
2714 ****************************************************************************/
2716 char *store_file_unix_basic(connection_struct *conn,
2717 char *pdata,
2718 files_struct *fsp,
2719 const SMB_STRUCT_STAT *psbuf)
2721 dev_t devno;
2723 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2724 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2726 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2727 pdata += 8;
2729 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2730 pdata += 8;
2732 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2733 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2734 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2735 pdata += 24;
2737 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2738 SIVAL(pdata,4,0);
2739 pdata += 8;
2741 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2742 SIVAL(pdata,4,0);
2743 pdata += 8;
2745 SIVAL(pdata, 0, unix_filetype_to_wire(psbuf->st_ex_mode));
2746 pdata += 4;
2748 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2749 devno = psbuf->st_ex_rdev;
2750 } else {
2751 devno = psbuf->st_ex_dev;
2754 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2755 SIVAL(pdata,4,0);
2756 pdata += 8;
2758 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2759 SIVAL(pdata,4,0);
2760 pdata += 8;
2762 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2763 pdata += 8;
2765 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2766 SIVAL(pdata,4,0);
2767 pdata += 8;
2769 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2770 SIVAL(pdata,4,0);
2771 pdata += 8;
2773 return pdata;
2776 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2777 * the chflags(2) (or equivalent) flags.
2779 * XXX: this really should be behind the VFS interface. To do this, we would
2780 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2781 * Each VFS module could then implement its own mapping as appropriate for the
2782 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2784 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2785 info2_flags_map[] =
2787 #ifdef UF_NODUMP
2788 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2789 #endif
2791 #ifdef UF_IMMUTABLE
2792 { UF_IMMUTABLE, EXT_IMMUTABLE },
2793 #endif
2795 #ifdef UF_APPEND
2796 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2797 #endif
2799 #ifdef UF_HIDDEN
2800 { UF_HIDDEN, EXT_HIDDEN },
2801 #endif
2803 /* Do not remove. We need to guarantee that this array has at least one
2804 * entry to build on HP-UX.
2806 { 0, 0 }
2810 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2811 uint32_t *smb_fflags, uint32_t *smb_fmask)
2813 size_t i;
2815 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2816 *smb_fmask |= info2_flags_map[i].smb_fflag;
2817 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2818 *smb_fflags |= info2_flags_map[i].smb_fflag;
2823 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2824 const uint32_t smb_fflags,
2825 const uint32_t smb_fmask,
2826 int *stat_fflags)
2828 uint32_t max_fmask = 0;
2829 size_t i;
2831 *stat_fflags = psbuf->st_ex_flags;
2833 /* For each flags requested in smb_fmask, check the state of the
2834 * corresponding flag in smb_fflags and set or clear the matching
2835 * stat flag.
2838 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2839 max_fmask |= info2_flags_map[i].smb_fflag;
2840 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2841 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2842 *stat_fflags |= info2_flags_map[i].stat_fflag;
2843 } else {
2844 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2849 /* If smb_fmask is asking to set any bits that are not supported by
2850 * our flag mappings, we should fail.
2852 if ((smb_fmask & max_fmask) != smb_fmask) {
2853 return False;
2856 return True;
2860 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2861 * of file flags and birth (create) time.
2863 char *store_file_unix_basic_info2(connection_struct *conn,
2864 char *pdata,
2865 files_struct *fsp,
2866 const SMB_STRUCT_STAT *psbuf)
2868 uint32_t file_flags = 0;
2869 uint32_t flags_mask = 0;
2871 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2873 /* Create (birth) time 64 bit */
2874 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2875 pdata += 8;
2877 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2878 SIVAL(pdata, 0, file_flags); /* flags */
2879 SIVAL(pdata, 4, flags_mask); /* mask */
2880 pdata += 8;
2882 return pdata;
2885 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2886 const struct stream_struct *streams,
2887 char *data,
2888 unsigned int max_data_bytes,
2889 unsigned int *data_size)
2891 unsigned int i;
2892 unsigned int ofs = 0;
2894 if (max_data_bytes < 32) {
2895 return NT_STATUS_INFO_LENGTH_MISMATCH;
2898 for (i = 0; i < num_streams; i++) {
2899 unsigned int next_offset;
2900 size_t namelen;
2901 smb_ucs2_t *namebuf;
2903 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2904 streams[i].name, &namelen) ||
2905 namelen <= 2)
2907 return NT_STATUS_INVALID_PARAMETER;
2911 * name_buf is now null-terminated, we need to marshall as not
2912 * terminated
2915 namelen -= 2;
2918 * We cannot overflow ...
2920 if ((ofs + 24 + namelen) > max_data_bytes) {
2921 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2922 i));
2923 TALLOC_FREE(namebuf);
2924 return STATUS_BUFFER_OVERFLOW;
2927 SIVAL(data, ofs+4, namelen);
2928 SOFF_T(data, ofs+8, streams[i].size);
2929 SOFF_T(data, ofs+16, streams[i].alloc_size);
2930 memcpy(data+ofs+24, namebuf, namelen);
2931 TALLOC_FREE(namebuf);
2933 next_offset = ofs + 24 + namelen;
2935 if (i == num_streams-1) {
2936 SIVAL(data, ofs, 0);
2938 else {
2939 unsigned int align = ndr_align_size(next_offset, 8);
2941 if ((next_offset + align) > max_data_bytes) {
2942 DEBUG(10, ("refusing to overflow align "
2943 "reply at stream %u\n",
2944 i));
2945 TALLOC_FREE(namebuf);
2946 return STATUS_BUFFER_OVERFLOW;
2949 memset(data+next_offset, 0, align);
2950 next_offset += align;
2952 SIVAL(data, ofs, next_offset - ofs);
2953 ofs = next_offset;
2956 ofs = next_offset;
2959 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2961 *data_size = ofs;
2963 return NT_STATUS_OK;
2966 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2967 TALLOC_CTX *mem_ctx,
2968 struct smb_request *req,
2969 uint16_t info_level,
2970 files_struct *fsp,
2971 struct smb_filename *smb_fname,
2972 bool delete_pending,
2973 struct timespec write_time_ts,
2974 struct ea_list *ea_list,
2975 uint16_t flags2,
2976 unsigned int max_data_bytes,
2977 size_t *fixed_portion,
2978 char **ppdata,
2979 unsigned int *pdata_size)
2981 char *pdata = *ppdata;
2982 char *dstart, *dend;
2983 unsigned int data_size;
2984 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2985 SMB_STRUCT_STAT *psbuf = NULL;
2986 SMB_STRUCT_STAT *base_sp = NULL;
2987 char *p;
2988 char *base_name;
2989 char *dos_fname;
2990 int mode;
2991 int nlink;
2992 NTSTATUS status;
2993 uint64_t file_size = 0;
2994 uint64_t pos = 0;
2995 uint64_t allocation_size = 0;
2996 uint64_t file_id = 0;
2997 uint32_t access_mask = 0;
2998 size_t len = 0;
3000 if (INFO_LEVEL_IS_UNIX(info_level)) {
3001 bool ok = false;
3003 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3004 DBG_DEBUG("SMB1 unix extensions activated\n");
3005 ok = true;
3008 if (conn_using_smb2(conn->sconn) &&
3009 fsp->fsp_flags.posix_open)
3011 DBG_DEBUG("SMB2 posix open\n");
3012 ok = true;
3015 if (!ok) {
3016 return NT_STATUS_INVALID_LEVEL;
3020 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3021 smb_fname_str_dbg(smb_fname),
3022 fsp_fnum_dbg(fsp),
3023 info_level, max_data_bytes);
3026 * In case of querying a symlink in POSIX context,
3027 * fsp will be NULL. fdos_mode() deals with it.
3029 if (fsp != NULL) {
3030 smb_fname = fsp->fsp_name;
3032 mode = fdos_mode(fsp);
3033 psbuf = &smb_fname->st;
3035 if (fsp != NULL) {
3036 base_sp = fsp->base_fsp ?
3037 &fsp->base_fsp->fsp_name->st :
3038 &fsp->fsp_name->st;
3039 } else {
3040 base_sp = &smb_fname->st;
3043 nlink = psbuf->st_ex_nlink;
3045 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3046 nlink = 1;
3049 if ((nlink > 0) && delete_pending) {
3050 nlink -= 1;
3053 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3054 return NT_STATUS_INVALID_PARAMETER;
3057 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3058 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3059 if (*ppdata == NULL) {
3060 return NT_STATUS_NO_MEMORY;
3062 pdata = *ppdata;
3063 dstart = pdata;
3064 dend = dstart + data_size - 1;
3066 if (!is_omit_timespec(&write_time_ts) &&
3067 !INFO_LEVEL_IS_UNIX(info_level))
3069 update_stat_ex_mtime(psbuf, write_time_ts);
3072 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3073 mtime_ts = psbuf->st_ex_mtime;
3074 atime_ts = psbuf->st_ex_atime;
3075 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3077 if (lp_dos_filetime_resolution(SNUM(conn))) {
3078 dos_filetime_timespec(&create_time_ts);
3079 dos_filetime_timespec(&mtime_ts);
3080 dos_filetime_timespec(&atime_ts);
3081 dos_filetime_timespec(&ctime_ts);
3084 p = strrchr_m(smb_fname->base_name,'/');
3085 if (p == NULL) {
3086 base_name = smb_fname->base_name;
3087 } else {
3088 base_name = p+1;
3091 /* NT expects the name to be in an exact form of the *full*
3092 filename. See the trans2 torture test */
3093 if (ISDOT(base_name)) {
3094 dos_fname = talloc_strdup(mem_ctx, "\\");
3095 if (!dos_fname) {
3096 return NT_STATUS_NO_MEMORY;
3098 } else {
3099 dos_fname = talloc_asprintf(mem_ctx,
3100 "\\%s",
3101 smb_fname->base_name);
3102 if (!dos_fname) {
3103 return NT_STATUS_NO_MEMORY;
3105 if (is_named_stream(smb_fname)) {
3106 dos_fname = talloc_asprintf(dos_fname, "%s",
3107 smb_fname->stream_name);
3108 if (!dos_fname) {
3109 return NT_STATUS_NO_MEMORY;
3113 string_replace(dos_fname, '/', '\\');
3116 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3118 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3119 /* Do we have this path open ? */
3120 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3121 files_struct *fsp1 = file_find_di_first(
3122 conn->sconn, fileid, true);
3123 if (fsp1 && fsp1->initial_allocation_size) {
3124 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3128 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3129 file_size = get_file_size_stat(psbuf);
3132 if (fsp) {
3133 pos = fh_get_position_information(fsp->fh);
3136 if (fsp) {
3137 access_mask = fsp->access_mask;
3138 } else {
3139 /* GENERIC_EXECUTE mapping from Windows */
3140 access_mask = 0x12019F;
3143 /* This should be an index number - looks like
3144 dev/ino to me :-)
3146 I think this causes us to fail the IFSKIT
3147 BasicFileInformationTest. -tpot */
3148 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3150 *fixed_portion = 0;
3152 switch (info_level) {
3153 case SMB_INFO_STANDARD:
3154 DBG_DEBUG("SMB_INFO_STANDARD\n");
3155 data_size = 22;
3156 srv_put_dos_date2_ts(pdata,
3157 l1_fdateCreation,
3158 create_time_ts);
3159 srv_put_dos_date2_ts(pdata,
3160 l1_fdateLastAccess,
3161 atime_ts);
3162 srv_put_dos_date2_ts(pdata,
3163 l1_fdateLastWrite,
3164 mtime_ts); /* write time */
3165 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3166 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3167 SSVAL(pdata,l1_attrFile,mode);
3168 break;
3170 case SMB_INFO_QUERY_EA_SIZE:
3172 unsigned int ea_size =
3173 estimate_ea_size(smb_fname->fsp);
3174 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3175 data_size = 26;
3176 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3177 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3178 srv_put_dos_date2_ts(pdata,
3180 mtime_ts); /* write time */
3181 SIVAL(pdata,12,(uint32_t)file_size);
3182 SIVAL(pdata,16,(uint32_t)allocation_size);
3183 SSVAL(pdata,20,mode);
3184 SIVAL(pdata,22,ea_size);
3185 break;
3188 case SMB_INFO_IS_NAME_VALID:
3189 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3190 if (fsp) {
3191 /* os/2 needs this ? really ?*/
3192 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3194 /* This is only reached for qpathinfo */
3195 data_size = 0;
3196 break;
3198 case SMB_INFO_QUERY_EAS_FROM_LIST:
3200 size_t total_ea_len = 0;
3201 struct ea_list *ea_file_list = NULL;
3202 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3204 status =
3205 get_ea_list_from_fsp(mem_ctx,
3206 smb_fname->fsp,
3207 &total_ea_len, &ea_file_list);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 return status;
3212 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3214 if (!ea_list || (total_ea_len > data_size)) {
3215 data_size = 4;
3216 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3217 break;
3220 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3221 break;
3224 case SMB_INFO_QUERY_ALL_EAS:
3226 /* We have data_size bytes to put EA's into. */
3227 size_t total_ea_len = 0;
3228 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3230 status = get_ea_list_from_fsp(mem_ctx,
3231 smb_fname->fsp,
3232 &total_ea_len, &ea_list);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 return status;
3237 if (!ea_list || (total_ea_len > data_size)) {
3238 data_size = 4;
3239 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3240 break;
3243 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3244 break;
3247 case SMB2_FILE_FULL_EA_INFORMATION:
3249 /* We have data_size bytes to put EA's into. */
3250 size_t total_ea_len = 0;
3251 struct ea_list *ea_file_list = NULL;
3253 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3255 /*TODO: add filtering and index handling */
3257 status =
3258 get_ea_list_from_fsp(mem_ctx,
3259 smb_fname->fsp,
3260 &total_ea_len, &ea_file_list);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 return status;
3264 if (!ea_file_list) {
3265 return NT_STATUS_NO_EAS_ON_FILE;
3268 status = fill_ea_chained_buffer(mem_ctx,
3269 pdata,
3270 data_size,
3271 &data_size,
3272 conn, ea_file_list);
3273 if (!NT_STATUS_IS_OK(status)) {
3274 return status;
3276 break;
3279 case SMB_FILE_BASIC_INFORMATION:
3280 case SMB_QUERY_FILE_BASIC_INFO:
3282 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3283 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3284 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3285 } else {
3286 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3287 data_size = 40;
3288 SIVAL(pdata,36,0);
3290 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3291 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3292 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3293 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3294 SIVAL(pdata,32,mode);
3296 DBG_INFO("SMB_QFBI - create: %s access: %s "
3297 "write: %s change: %s mode: %x\n",
3298 ctime(&create_time_ts.tv_sec),
3299 ctime(&atime_ts.tv_sec),
3300 ctime(&mtime_ts.tv_sec),
3301 ctime(&ctime_ts.tv_sec),
3302 mode);
3303 *fixed_portion = data_size;
3304 break;
3306 case SMB_FILE_STANDARD_INFORMATION:
3307 case SMB_QUERY_FILE_STANDARD_INFO:
3309 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3310 data_size = 24;
3311 SOFF_T(pdata,0,allocation_size);
3312 SOFF_T(pdata,8,file_size);
3313 SIVAL(pdata,16,nlink);
3314 SCVAL(pdata,20,delete_pending?1:0);
3315 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3316 SSVAL(pdata,22,0); /* Padding. */
3317 *fixed_portion = 24;
3318 break;
3320 case SMB_FILE_EA_INFORMATION:
3321 case SMB_QUERY_FILE_EA_INFO:
3323 unsigned int ea_size =
3324 estimate_ea_size(smb_fname->fsp);
3325 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3326 data_size = 4;
3327 *fixed_portion = 4;
3328 SIVAL(pdata,0,ea_size);
3329 break;
3332 /* Get the 8.3 name - used if NT SMB was negotiated. */
3333 case SMB_QUERY_FILE_ALT_NAME_INFO:
3334 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3336 char mangled_name[13];
3337 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3338 if (!name_to_8_3(base_name,mangled_name,
3339 True,conn->params)) {
3340 return NT_STATUS_NO_MEMORY;
3342 status = srvstr_push(dstart, flags2,
3343 pdata+4, mangled_name,
3344 PTR_DIFF(dend, pdata+4),
3345 STR_UNICODE, &len);
3346 if (!NT_STATUS_IS_OK(status)) {
3347 return status;
3349 data_size = 4 + len;
3350 SIVAL(pdata,0,len);
3351 *fixed_portion = 8;
3352 break;
3355 case SMB_QUERY_FILE_NAME_INFO:
3358 this must be *exactly* right for ACLs on mapped drives to work
3360 status = srvstr_push(dstart, flags2,
3361 pdata+4, dos_fname,
3362 PTR_DIFF(dend, pdata+4),
3363 STR_UNICODE, &len);
3364 if (!NT_STATUS_IS_OK(status)) {
3365 return status;
3367 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3368 data_size = 4 + len;
3369 SIVAL(pdata,0,len);
3370 break;
3373 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3375 char *nfname = NULL;
3377 if (fsp == NULL ||
3378 !conn_using_smb2(fsp->conn->sconn)) {
3379 return NT_STATUS_INVALID_LEVEL;
3382 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3383 if (nfname == NULL) {
3384 return NT_STATUS_NO_MEMORY;
3387 if (ISDOT(nfname)) {
3388 nfname[0] = '\0';
3390 string_replace(nfname, '/', '\\');
3392 if (fsp_is_alternate_stream(fsp)) {
3393 const char *s = smb_fname->stream_name;
3394 const char *e = NULL;
3395 size_t n;
3397 SMB_ASSERT(s[0] != '\0');
3400 * smb_fname->stream_name is in form
3401 * of ':StrEam:$DATA', but we should only
3402 * append ':StrEam' here.
3405 e = strchr(&s[1], ':');
3406 if (e == NULL) {
3407 n = strlen(s);
3408 } else {
3409 n = PTR_DIFF(e, s);
3411 nfname = talloc_strndup_append(nfname, s, n);
3412 if (nfname == NULL) {
3413 return NT_STATUS_NO_MEMORY;
3417 status = srvstr_push(dstart, flags2,
3418 pdata+4, nfname,
3419 PTR_DIFF(dend, pdata+4),
3420 STR_UNICODE, &len);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 return status;
3424 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3425 data_size = 4 + len;
3426 SIVAL(pdata,0,len);
3427 *fixed_portion = 8;
3428 break;
3431 case SMB_FILE_ALLOCATION_INFORMATION:
3432 case SMB_QUERY_FILE_ALLOCATION_INFO:
3433 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3434 data_size = 8;
3435 SOFF_T(pdata,0,allocation_size);
3436 break;
3438 case SMB_FILE_END_OF_FILE_INFORMATION:
3439 case SMB_QUERY_FILE_END_OF_FILEINFO:
3440 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3441 data_size = 8;
3442 SOFF_T(pdata,0,file_size);
3443 break;
3445 case SMB_QUERY_FILE_ALL_INFO:
3446 case SMB_FILE_ALL_INFORMATION:
3448 unsigned int ea_size =
3449 estimate_ea_size(smb_fname->fsp);
3450 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3451 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3452 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3453 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3454 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3455 SIVAL(pdata,32,mode);
3456 SIVAL(pdata,36,0); /* padding. */
3457 pdata += 40;
3458 SOFF_T(pdata,0,allocation_size);
3459 SOFF_T(pdata,8,file_size);
3460 SIVAL(pdata,16,nlink);
3461 SCVAL(pdata,20,delete_pending);
3462 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3463 SSVAL(pdata,22,0);
3464 pdata += 24;
3465 SIVAL(pdata,0,ea_size);
3466 pdata += 4; /* EA info */
3467 status = srvstr_push(dstart, flags2,
3468 pdata+4, dos_fname,
3469 PTR_DIFF(dend, pdata+4),
3470 STR_UNICODE, &len);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 return status;
3474 SIVAL(pdata,0,len);
3475 pdata += 4 + len;
3476 data_size = PTR_DIFF(pdata,(*ppdata));
3477 *fixed_portion = 10;
3478 break;
3481 case SMB2_FILE_ALL_INFORMATION:
3483 unsigned int ea_size =
3484 estimate_ea_size(smb_fname->fsp);
3485 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3486 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3487 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3488 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3489 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3490 SIVAL(pdata, 0x20, mode);
3491 SIVAL(pdata, 0x24, 0); /* padding. */
3492 SBVAL(pdata, 0x28, allocation_size);
3493 SBVAL(pdata, 0x30, file_size);
3494 SIVAL(pdata, 0x38, nlink);
3495 SCVAL(pdata, 0x3C, delete_pending);
3496 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3497 SSVAL(pdata, 0x3E, 0); /* padding */
3498 SBVAL(pdata, 0x40, file_id);
3499 SIVAL(pdata, 0x48, ea_size);
3500 SIVAL(pdata, 0x4C, access_mask);
3501 SBVAL(pdata, 0x50, pos);
3502 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3503 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3505 pdata += 0x60;
3507 status = srvstr_push(dstart, flags2,
3508 pdata+4, dos_fname,
3509 PTR_DIFF(dend, pdata+4),
3510 STR_UNICODE, &len);
3511 if (!NT_STATUS_IS_OK(status)) {
3512 return status;
3514 SIVAL(pdata,0,len);
3515 pdata += 4 + len;
3516 data_size = PTR_DIFF(pdata,(*ppdata));
3517 *fixed_portion = 104;
3518 break;
3520 case SMB_FILE_INTERNAL_INFORMATION:
3522 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3523 SBVAL(pdata, 0, file_id);
3524 data_size = 8;
3525 *fixed_portion = 8;
3526 break;
3528 case SMB_FILE_ACCESS_INFORMATION:
3529 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3530 SIVAL(pdata, 0, access_mask);
3531 data_size = 4;
3532 *fixed_portion = 4;
3533 break;
3535 case SMB_FILE_NAME_INFORMATION:
3536 /* Pathname with leading '\'. */
3538 size_t byte_len;
3539 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3540 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3541 SIVAL(pdata,0,byte_len);
3542 data_size = 4 + byte_len;
3543 break;
3546 case SMB_FILE_DISPOSITION_INFORMATION:
3547 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3548 data_size = 1;
3549 SCVAL(pdata,0,delete_pending);
3550 *fixed_portion = 1;
3551 break;
3553 case SMB_FILE_POSITION_INFORMATION:
3554 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3555 data_size = 8;
3556 SOFF_T(pdata,0,pos);
3557 *fixed_portion = 8;
3558 break;
3560 case SMB_FILE_MODE_INFORMATION:
3561 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3562 SIVAL(pdata,0,mode);
3563 data_size = 4;
3564 *fixed_portion = 4;
3565 break;
3567 case SMB_FILE_ALIGNMENT_INFORMATION:
3568 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3569 SIVAL(pdata,0,0); /* No alignment needed. */
3570 data_size = 4;
3571 *fixed_portion = 4;
3572 break;
3575 * NT4 server just returns "invalid query" to this - if we try
3576 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3577 * want this. JRA.
3579 /* The first statement above is false - verified using Thursby
3580 * client against NT4 -- gcolley.
3582 case SMB_QUERY_FILE_STREAM_INFO:
3583 case SMB_FILE_STREAM_INFORMATION: {
3584 unsigned int num_streams = 0;
3585 struct stream_struct *streams = NULL;
3587 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3589 if (is_ntfs_stream_smb_fname(smb_fname)) {
3590 return NT_STATUS_INVALID_PARAMETER;
3593 status = vfs_fstreaminfo(fsp,
3594 mem_ctx,
3595 &num_streams,
3596 &streams);
3598 if (!NT_STATUS_IS_OK(status)) {
3599 DBG_DEBUG("could not get stream info: %s\n",
3600 nt_errstr(status));
3601 return status;
3604 status = marshall_stream_info(num_streams, streams,
3605 pdata, max_data_bytes,
3606 &data_size);
3608 if (!NT_STATUS_IS_OK(status)) {
3609 DBG_DEBUG("marshall_stream_info failed: %s\n",
3610 nt_errstr(status));
3611 TALLOC_FREE(streams);
3612 return status;
3615 TALLOC_FREE(streams);
3617 *fixed_portion = 32;
3619 break;
3621 case SMB_QUERY_COMPRESSION_INFO:
3622 case SMB_FILE_COMPRESSION_INFORMATION:
3623 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3624 SOFF_T(pdata,0,file_size);
3625 SIVAL(pdata,8,0); /* ??? */
3626 SIVAL(pdata,12,0); /* ??? */
3627 data_size = 16;
3628 *fixed_portion = 16;
3629 break;
3631 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3632 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3633 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3634 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3635 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3636 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3637 SOFF_T(pdata,32,allocation_size);
3638 SOFF_T(pdata,40,file_size);
3639 SIVAL(pdata,48,mode);
3640 SIVAL(pdata,52,0); /* ??? */
3641 data_size = 56;
3642 *fixed_portion = 56;
3643 break;
3645 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: {
3646 uint32_t tag = 0;
3648 DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3650 (void)fsctl_get_reparse_tag(fsp, &tag);
3652 DBG_DEBUG("tag=%"PRIu32"\n", tag);
3654 SIVAL(pdata, 0, mode);
3655 SIVAL(pdata, 4, tag);
3656 data_size = 8;
3657 *fixed_portion = 8;
3658 break;
3661 * SMB2 UNIX Extensions.
3663 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3665 struct smb3_file_posix_information info = {};
3666 uint8_t buf[sizeof(info)];
3667 struct ndr_push ndr = {
3668 .data = buf,
3669 .alloc_size = sizeof(buf),
3670 .fixed_buf_size = true,
3672 enum ndr_err_code ndr_err;
3674 if (!conn_using_smb2(conn->sconn)) {
3675 return NT_STATUS_INVALID_LEVEL;
3677 if (fsp == NULL) {
3678 return NT_STATUS_INVALID_HANDLE;
3680 if (!fsp->fsp_flags.posix_open) {
3681 return NT_STATUS_INVALID_LEVEL;
3684 smb3_file_posix_information_init(
3685 conn, &smb_fname->st, 0, mode, &info);
3687 ndr_err = ndr_push_smb3_file_posix_information(
3688 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3689 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3690 return NT_STATUS_INSUFFICIENT_RESOURCES;
3693 memcpy(pdata, buf, ndr.offset);
3694 data_size = ndr.offset;
3695 break;
3698 default:
3699 return NT_STATUS_INVALID_LEVEL;
3702 *pdata_size = data_size;
3703 return NT_STATUS_OK;
3706 /****************************************************************************
3707 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3708 code.
3709 ****************************************************************************/
3711 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3712 connection_struct *conn,
3713 struct smb_request *req,
3714 bool overwrite_if_exists,
3715 const struct smb_filename *smb_fname_old,
3716 struct smb_filename *smb_fname_new)
3718 NTSTATUS status = NT_STATUS_OK;
3719 int ret;
3720 bool ok;
3721 struct smb_filename *parent_fname_old = NULL;
3722 struct smb_filename *base_name_old = NULL;
3723 struct smb_filename *parent_fname_new = NULL;
3724 struct smb_filename *base_name_new = NULL;
3726 /* source must already exist. */
3727 if (!VALID_STAT(smb_fname_old->st)) {
3728 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3729 goto out;
3732 /* No links from a directory. */
3733 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3734 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3735 goto out;
3738 /* Setting a hardlink to/from a stream isn't currently supported. */
3739 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3740 if (ok) {
3741 DBG_DEBUG("Old name has streams\n");
3742 status = NT_STATUS_INVALID_PARAMETER;
3743 goto out;
3745 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3746 if (ok) {
3747 DBG_DEBUG("New name has streams\n");
3748 status = NT_STATUS_INVALID_PARAMETER;
3749 goto out;
3752 if (smb_fname_old->twrp != 0) {
3753 status = NT_STATUS_NOT_SAME_DEVICE;
3754 goto out;
3757 status = parent_pathref(talloc_tos(),
3758 conn->cwd_fsp,
3759 smb_fname_old,
3760 &parent_fname_old,
3761 &base_name_old);
3762 if (!NT_STATUS_IS_OK(status)) {
3763 goto out;
3766 status = parent_pathref(talloc_tos(),
3767 conn->cwd_fsp,
3768 smb_fname_new,
3769 &parent_fname_new,
3770 &base_name_new);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 goto out;
3775 if (VALID_STAT(smb_fname_new->st)) {
3776 if (overwrite_if_exists) {
3777 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3778 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3779 goto out;
3781 status = unlink_internals(conn,
3782 req,
3783 FILE_ATTRIBUTE_NORMAL,
3784 NULL, /* new_dirfsp */
3785 smb_fname_new);
3786 if (!NT_STATUS_IS_OK(status)) {
3787 goto out;
3789 } else {
3790 /* Disallow if newname already exists. */
3791 status = NT_STATUS_OBJECT_NAME_COLLISION;
3792 goto out;
3796 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3797 smb_fname_old->base_name, smb_fname_new->base_name));
3799 ret = SMB_VFS_LINKAT(conn,
3800 parent_fname_old->fsp,
3801 base_name_old,
3802 parent_fname_new->fsp,
3803 base_name_new,
3806 if (ret != 0) {
3807 status = map_nt_error_from_unix(errno);
3808 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3809 nt_errstr(status), smb_fname_old->base_name,
3810 smb_fname_new->base_name));
3811 goto out;
3814 notify_fname(conn,
3815 NOTIFY_ACTION_ADDED |
3816 NOTIFY_ACTION_DIRLEASE_BREAK,
3817 FILE_NOTIFY_CHANGE_FILE_NAME,
3818 smb_fname_new,
3819 fsp_get_smb2_lease(smb_fname_old->fsp));
3821 out:
3823 TALLOC_FREE(parent_fname_old);
3824 TALLOC_FREE(parent_fname_new);
3825 return status;
3828 /****************************************************************************
3829 Deal with setting the time from any of the setfilepathinfo functions.
3830 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3831 calling this function.
3832 ****************************************************************************/
3834 NTSTATUS smb_set_file_time(connection_struct *conn,
3835 files_struct *fsp,
3836 struct smb_filename *smb_fname,
3837 struct smb_file_time *ft,
3838 bool setting_write_time)
3840 const struct smb2_lease *lease = NULL;
3841 struct files_struct *set_fsp = NULL;
3842 struct timeval_buf tbuf[4];
3843 uint32_t action = NOTIFY_ACTION_MODIFIED;
3844 uint32_t filter =
3845 FILE_NOTIFY_CHANGE_LAST_ACCESS
3846 |FILE_NOTIFY_CHANGE_LAST_WRITE
3847 |FILE_NOTIFY_CHANGE_CREATION;
3848 int ret;
3850 if (!VALID_STAT(smb_fname->st)) {
3851 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3854 if (fsp == NULL) {
3855 /* A symlink */
3856 return NT_STATUS_OK;
3859 set_fsp = metadata_fsp(fsp);
3861 /* get some defaults (no modifications) if any info is zero or -1. */
3862 if (is_omit_timespec(&ft->create_time)) {
3863 filter &= ~FILE_NOTIFY_CHANGE_CREATION;
3866 if (is_omit_timespec(&ft->atime)) {
3867 filter &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3870 if (is_omit_timespec(&ft->mtime)) {
3871 filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3874 if (!setting_write_time) {
3875 /* ft->mtime comes from change time, not write time. */
3876 filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3879 /* Ensure the resolution is the correct for
3880 * what we can store on this filesystem. */
3882 round_timespec(conn->ts_res, &ft->create_time);
3883 round_timespec(conn->ts_res, &ft->ctime);
3884 round_timespec(conn->ts_res, &ft->atime);
3885 round_timespec(conn->ts_res, &ft->mtime);
3887 DBG_DEBUG("actime: %s\n ",
3888 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3889 DBG_DEBUG("modtime: %s\n ",
3890 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3891 DBG_DEBUG("ctime: %s\n ",
3892 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3893 DBG_DEBUG("createtime: %s\n ",
3894 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3896 if (setting_write_time) {
3898 * This was a Windows setfileinfo on an open file.
3899 * NT does this a lot. We also need to
3900 * set the time here, as it can be read by
3901 * FindFirst/FindNext and with the patch for bug #2045
3902 * in smbd/fileio.c it ensures that this timestamp is
3903 * kept sticky even after a write. We save the request
3904 * away and will set it on file close and after a write. JRA.
3907 DBG_DEBUG("setting pending modtime to %s\n",
3908 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3910 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3911 action |= NOTIFY_ACTION_DIRLEASE_BREAK;
3912 lease = fsp_get_smb2_lease(fsp);
3915 DBG_DEBUG("setting utimes to modified values.\n");
3917 ret = file_ntimes(conn, set_fsp, ft);
3918 if (ret != 0) {
3919 return map_nt_error_from_unix(errno);
3922 notify_fname(conn,
3923 action,
3924 filter,
3925 smb_fname,
3926 lease);
3927 return NT_STATUS_OK;
3930 /****************************************************************************
3931 Deal with setting the dosmode from any of the setfilepathinfo functions.
3932 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3933 done before calling this function.
3934 ****************************************************************************/
3936 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3937 struct files_struct *fsp,
3938 uint32_t dosmode)
3940 struct files_struct *dos_fsp = NULL;
3941 uint32_t current_dosmode;
3942 int ret;
3944 if (!VALID_STAT(fsp->fsp_name->st)) {
3945 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3948 dos_fsp = metadata_fsp(fsp);
3950 if (dosmode != 0) {
3951 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3952 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3953 } else {
3954 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3958 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3960 /* check the mode isn't different, before changing it */
3961 if (dosmode == 0) {
3962 return NT_STATUS_OK;
3964 current_dosmode = fdos_mode(dos_fsp);
3965 if (dosmode == current_dosmode) {
3966 return NT_STATUS_OK;
3969 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3970 fsp_str_dbg(dos_fsp), dosmode);
3972 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3973 if (ret != 0) {
3974 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3975 fsp_str_dbg(dos_fsp), strerror(errno));
3976 return map_nt_error_from_unix(errno);
3979 return NT_STATUS_OK;
3982 /****************************************************************************
3983 Deal with setting the size from any of the setfilepathinfo functions.
3984 ****************************************************************************/
3986 NTSTATUS smb_set_file_size(connection_struct *conn,
3987 struct smb_request *req,
3988 files_struct *fsp,
3989 struct smb_filename *smb_fname,
3990 const SMB_STRUCT_STAT *psbuf,
3991 off_t size,
3992 bool fail_after_createfile)
3994 NTSTATUS status = NT_STATUS_OK;
3995 files_struct *new_fsp = NULL;
3997 if (!VALID_STAT(*psbuf)) {
3998 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4001 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4002 (uint64_t)size,
4003 get_file_size_stat(psbuf));
4005 if (size == get_file_size_stat(psbuf)) {
4006 if (fsp == NULL) {
4007 return NT_STATUS_OK;
4009 if (!fsp->fsp_flags.modified) {
4010 return NT_STATUS_OK;
4012 trigger_write_time_update_immediate(fsp);
4013 return NT_STATUS_OK;
4016 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4017 smb_fname_str_dbg(smb_fname), (double)size));
4019 if (fsp &&
4020 !fsp->fsp_flags.is_pathref &&
4021 fsp_get_io_fd(fsp) != -1)
4023 /* Handle based call. */
4024 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 return status;
4029 if (vfs_set_filelen(fsp, size) == -1) {
4030 return map_nt_error_from_unix(errno);
4032 trigger_write_time_update_immediate(fsp);
4033 return NT_STATUS_OK;
4036 status = SMB_VFS_CREATE_FILE(
4037 conn, /* conn */
4038 req, /* req */
4039 NULL, /* dirfsp */
4040 smb_fname, /* fname */
4041 FILE_WRITE_DATA, /* access_mask */
4042 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4043 FILE_SHARE_DELETE),
4044 FILE_OPEN, /* create_disposition*/
4045 0, /* create_options */
4046 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4047 0, /* oplock_request */
4048 NULL, /* lease */
4049 0, /* allocation_size */
4050 0, /* private_flags */
4051 NULL, /* sd */
4052 NULL, /* ea_list */
4053 &new_fsp, /* result */
4054 NULL, /* pinfo */
4055 NULL, NULL); /* create context */
4057 if (!NT_STATUS_IS_OK(status)) {
4058 /* NB. We check for open_was_deferred in the caller. */
4059 return status;
4062 /* See RAW-SFILEINFO-END-OF-FILE */
4063 if (fail_after_createfile) {
4064 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4065 return NT_STATUS_INVALID_LEVEL;
4068 if (vfs_set_filelen(new_fsp, size) == -1) {
4069 status = map_nt_error_from_unix(errno);
4070 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4071 return status;
4074 trigger_write_time_update_immediate(new_fsp);
4075 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4076 return NT_STATUS_OK;
4079 /****************************************************************************
4080 Deal with SMB_INFO_SET_EA.
4081 ****************************************************************************/
4083 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4084 const char *pdata,
4085 int total_data,
4086 files_struct *fsp,
4087 struct smb_filename *smb_fname)
4089 struct ea_list *ea_list = NULL;
4090 TALLOC_CTX *ctx = NULL;
4091 NTSTATUS status = NT_STATUS_OK;
4093 if (total_data < 10) {
4095 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4096 length. They seem to have no effect. Bug #3212. JRA */
4098 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4099 /* We're done. We only get EA info in this call. */
4100 return NT_STATUS_OK;
4103 return NT_STATUS_INVALID_PARAMETER;
4106 if (IVAL(pdata,0) > total_data) {
4107 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4108 IVAL(pdata,0), (unsigned int)total_data));
4109 return NT_STATUS_INVALID_PARAMETER;
4112 ctx = talloc_tos();
4113 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4114 if (!ea_list) {
4115 return NT_STATUS_INVALID_PARAMETER;
4118 if (fsp == NULL) {
4120 * The only way fsp can be NULL here is if
4121 * smb_fname points at a symlink and
4122 * and we're in POSIX context.
4123 * Ensure this is the case.
4125 * In this case we cannot set the EA.
4127 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4128 return NT_STATUS_ACCESS_DENIED;
4131 status = set_ea(conn, fsp, ea_list);
4133 return status;
4136 /****************************************************************************
4137 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4138 ****************************************************************************/
4140 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4141 const char *pdata,
4142 int total_data,
4143 files_struct *fsp)
4145 struct ea_list *ea_list = NULL;
4146 NTSTATUS status;
4148 if (fsp == NULL) {
4149 return NT_STATUS_INVALID_HANDLE;
4152 if (!lp_ea_support(SNUM(conn))) {
4153 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4154 "EA's not supported.\n",
4155 (unsigned int)total_data));
4156 return NT_STATUS_EAS_NOT_SUPPORTED;
4159 if (total_data < 10) {
4160 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4161 "too small.\n",
4162 (unsigned int)total_data));
4163 return NT_STATUS_INVALID_PARAMETER;
4166 ea_list = read_nttrans_ea_list(talloc_tos(),
4167 pdata,
4168 total_data);
4170 if (!ea_list) {
4171 return NT_STATUS_INVALID_PARAMETER;
4174 status = set_ea(conn, fsp, ea_list);
4176 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4177 smb_fname_str_dbg(fsp->fsp_name),
4178 nt_errstr(status) ));
4180 return status;
4184 /****************************************************************************
4185 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4186 ****************************************************************************/
4188 NTSTATUS smb_check_file_disposition_info(struct files_struct *fsp,
4189 const char *data,
4190 int total_data,
4191 bool *_delete_on_close)
4193 bool delete_on_close;
4194 uint32_t dosmode = 0;
4195 NTSTATUS status;
4197 if (total_data < 1) {
4198 return NT_STATUS_INVALID_PARAMETER;
4201 if (fsp == NULL) {
4202 return NT_STATUS_INVALID_HANDLE;
4205 delete_on_close = (PULL_LE_U8(data, 0) ? true : false);
4206 *_delete_on_close = delete_on_close;
4208 dosmode = fdos_mode(fsp);
4210 DBG_DEBUG("file [%s] dosmode = %u, delete_on_close = %s\n",
4211 fsp_str_dbg(fsp),
4212 (unsigned int)dosmode,
4213 delete_on_close ? "yes" : "no");
4215 if (!delete_on_close) {
4216 return NT_STATUS_OK;
4219 status = can_set_delete_on_close(fsp, dosmode);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 return status;
4224 return NT_STATUS_OK;
4227 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4228 const char *pdata,
4229 int total_data,
4230 files_struct *fsp,
4231 struct smb_filename *smb_fname)
4233 NTSTATUS status;
4234 bool delete_on_close;
4236 status = smb_check_file_disposition_info(fsp,
4237 pdata,
4238 total_data,
4239 &delete_on_close);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 return status;
4244 /* The set is across all open files on this dev/inode pair. */
4245 if (!set_delete_on_close(fsp, delete_on_close,
4246 conn->session_info->security_token,
4247 conn->session_info->unix_token)) {
4248 return NT_STATUS_ACCESS_DENIED;
4250 return NT_STATUS_OK;
4253 /****************************************************************************
4254 Deal with SMB_FILE_POSITION_INFORMATION.
4255 ****************************************************************************/
4257 static NTSTATUS smb_file_position_information(connection_struct *conn,
4258 const char *pdata,
4259 int total_data,
4260 files_struct *fsp)
4262 uint64_t position_information;
4264 if (total_data < 8) {
4265 return NT_STATUS_INVALID_PARAMETER;
4268 if (fsp == NULL) {
4269 /* Ignore on pathname based set. */
4270 return NT_STATUS_OK;
4273 position_information = (uint64_t)IVAL(pdata,0);
4274 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4276 DEBUG(10,("smb_file_position_information: Set file position "
4277 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4278 (double)position_information));
4279 fh_set_position_information(fsp->fh, position_information);
4280 return NT_STATUS_OK;
4283 /****************************************************************************
4284 Deal with SMB_FILE_MODE_INFORMATION.
4285 ****************************************************************************/
4287 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4288 const char *pdata,
4289 int total_data)
4291 uint32_t mode;
4293 if (total_data < 4) {
4294 return NT_STATUS_INVALID_PARAMETER;
4296 mode = IVAL(pdata,0);
4297 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4298 return NT_STATUS_INVALID_PARAMETER;
4300 return NT_STATUS_OK;
4303 /****************************************************************************
4304 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4305 ****************************************************************************/
4307 NTSTATUS smb2_parse_file_rename_information(TALLOC_CTX *ctx,
4308 struct connection_struct *conn,
4309 struct smb_request *req,
4310 const char *pdata,
4311 int total_data,
4312 files_struct *fsp,
4313 struct smb_filename *smb_fname_src,
4314 bool *_overwrite,
4315 struct files_struct **_dst_dirfsp,
4316 struct smb_filename **_smb_fname_dst,
4317 char **_dst_original_lcomp)
4319 char *newname = NULL;
4320 struct files_struct *dst_dirfsp = NULL;
4321 struct smb_filename *smb_fname_dst = NULL;
4322 char *dst_original_lcomp = NULL;
4323 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4324 bool overwrite = false;
4325 uint32_t len;
4326 NTSTATUS status;
4328 if (!fsp) {
4329 return NT_STATUS_INVALID_HANDLE;
4332 if (total_data < 20) {
4333 return NT_STATUS_INVALID_PARAMETER;
4336 overwrite = (CVAL(pdata,0) ? True : False);
4337 len = IVAL(pdata,16);
4339 if (len > (total_data - 20) || (len == 0)) {
4340 return NT_STATUS_INVALID_PARAMETER;
4343 (void)srvstr_pull_talloc(ctx,
4344 pdata,
4345 req->flags2,
4346 &newname,
4347 &pdata[20],
4348 len,
4349 STR_TERMINATE);
4351 if (newname == NULL) {
4352 return NT_STATUS_INVALID_PARAMETER;
4355 /* SMB2 rename paths are never DFS. */
4356 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4357 ucf_flags &= ~UCF_DFS_PATHNAME;
4359 status = check_path_syntax(newname,
4360 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4361 if (!NT_STATUS_IS_OK(status)) {
4362 TALLOC_FREE(newname);
4363 return status;
4366 DBG_DEBUG("got name |%s|\n", newname);
4368 if (newname[0] == ':') {
4369 /* Create an smb_fname to call rename_internals_fsp() with. */
4370 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4371 fsp->base_fsp->fsp_name->base_name,
4372 newname,
4373 NULL,
4374 fsp->base_fsp->fsp_name->twrp,
4375 fsp->base_fsp->fsp_name->flags);
4376 if (smb_fname_dst == NULL) {
4377 TALLOC_FREE(newname);
4378 return NT_STATUS_NO_MEMORY;
4380 goto done;
4381 } else {
4382 status = filename_convert_dirfsp(ctx,
4383 conn,
4384 newname,
4385 ucf_flags,
4386 0, /* Never a TWRP. */
4387 &dst_dirfsp,
4388 &smb_fname_dst);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 return status;
4395 * Set the original last component, since
4396 * rename_internals_fsp() requires it.
4398 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4399 conn,
4400 newname,
4401 ucf_flags);
4402 if (dst_original_lcomp == NULL) {
4403 TALLOC_FREE(newname);
4404 TALLOC_FREE(smb_fname_dst);
4405 return NT_STATUS_NO_MEMORY;
4408 done:
4409 *_overwrite = overwrite;
4410 *_dst_dirfsp = dst_dirfsp;
4411 *_smb_fname_dst = smb_fname_dst;
4412 *_dst_original_lcomp = dst_original_lcomp;
4413 return NT_STATUS_OK;
4416 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4417 struct smb_request *req,
4418 const char *pdata,
4419 int total_data,
4420 files_struct *fsp,
4421 struct share_mode_lock **lck,
4422 struct smb_filename *smb_fname_src)
4424 bool overwrite;
4425 struct files_struct *dst_dirfsp = NULL;
4426 struct smb_filename *smb_fname_dst = NULL;
4427 char *dst_original_lcomp = NULL;
4428 NTSTATUS status = NT_STATUS_OK;
4429 TALLOC_CTX *ctx = talloc_tos();
4431 status = smb2_parse_file_rename_information(ctx,
4432 conn,
4433 req,
4434 pdata,
4435 total_data,
4436 fsp,
4437 smb_fname_src,
4438 &overwrite,
4439 &dst_dirfsp,
4440 &smb_fname_dst,
4441 &dst_original_lcomp);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 return status;
4446 DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4447 fsp_fnum_dbg(fsp),
4448 fsp_str_dbg(fsp),
4449 smb_fname_str_dbg(smb_fname_dst));
4451 status = rename_internals_fsp(conn,
4452 fsp,
4453 lck,
4454 smb_fname_dst,
4455 dst_original_lcomp,
4456 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4457 overwrite);
4459 TALLOC_FREE(smb_fname_dst);
4460 return status;
4463 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4464 struct smb_request *req,
4465 const char *pdata,
4466 int total_data,
4467 files_struct *fsp,
4468 struct smb_filename *smb_fname_src)
4470 bool overwrite;
4471 uint32_t len;
4472 char *newname = NULL;
4473 struct files_struct *dst_dirfsp = NULL;
4474 struct smb_filename *smb_fname_dst = NULL;
4475 NTSTATUS status = NT_STATUS_OK;
4476 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4477 size_t ret;
4478 TALLOC_CTX *ctx = talloc_tos();
4480 if (!fsp) {
4481 return NT_STATUS_INVALID_HANDLE;
4484 if (total_data < 20) {
4485 return NT_STATUS_INVALID_PARAMETER;
4488 overwrite = (CVAL(pdata,0) ? true : false);
4489 len = IVAL(pdata,16);
4491 if (len > (total_data - 20) || (len == 0)) {
4492 return NT_STATUS_INVALID_PARAMETER;
4495 ret = srvstr_pull_talloc(ctx,
4496 pdata,
4497 req->flags2,
4498 &newname,
4499 &pdata[20],
4500 len,
4501 STR_TERMINATE);
4503 if (ret == (size_t)-1 || newname == NULL) {
4504 return NT_STATUS_INVALID_PARAMETER;
4507 /* SMB2 hardlink paths are never DFS. */
4508 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4509 ucf_flags &= ~UCF_DFS_PATHNAME;
4511 status = check_path_syntax(newname,
4512 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 return status;
4517 DBG_DEBUG("got name |%s|\n", newname);
4519 status = filename_convert_dirfsp(ctx,
4520 conn,
4521 newname,
4522 ucf_flags,
4523 0, /* No TWRP. */
4524 &dst_dirfsp,
4525 &smb_fname_dst);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 return status;
4530 if (fsp->base_fsp) {
4531 /* No stream names. */
4532 return NT_STATUS_NOT_SUPPORTED;
4535 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4536 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4537 smb_fname_str_dbg(smb_fname_dst));
4538 status = hardlink_internals(ctx,
4539 conn,
4540 req,
4541 overwrite,
4542 fsp->fsp_name,
4543 smb_fname_dst);
4545 TALLOC_FREE(smb_fname_dst);
4546 return status;
4549 static NTSTATUS smb_file_link_information(connection_struct *conn,
4550 struct smb_request *req,
4551 const char *pdata,
4552 int total_data,
4553 files_struct *fsp,
4554 struct smb_filename *smb_fname_src)
4556 bool overwrite;
4557 uint32_t len;
4558 char *newname = NULL;
4559 struct files_struct *dst_dirfsp = NULL;
4560 struct smb_filename *smb_fname_dst = NULL;
4561 NTSTATUS status = NT_STATUS_OK;
4562 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4563 NTTIME dst_twrp = 0;
4564 TALLOC_CTX *ctx = talloc_tos();
4566 if (!fsp) {
4567 return NT_STATUS_INVALID_HANDLE;
4570 if (total_data < 20) {
4571 return NT_STATUS_INVALID_PARAMETER;
4574 overwrite = (CVAL(pdata,0) ? true : false);
4575 len = IVAL(pdata,16);
4577 if (len > (total_data - 20) || (len == 0)) {
4578 return NT_STATUS_INVALID_PARAMETER;
4581 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4582 srvstr_get_path_posix(ctx,
4583 pdata,
4584 req->flags2,
4585 &newname,
4586 &pdata[20],
4587 len,
4588 STR_TERMINATE,
4589 &status);
4590 ucf_flags |= UCF_POSIX_PATHNAMES;
4591 } else {
4592 srvstr_get_path(ctx,
4593 pdata,
4594 req->flags2,
4595 &newname,
4596 &pdata[20],
4597 len,
4598 STR_TERMINATE,
4599 &status);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 return status;
4605 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4606 newname));
4608 if (ucf_flags & UCF_GMT_PATHNAME) {
4609 extract_snapshot_token(newname, &dst_twrp);
4611 /* hardlink paths are never DFS. */
4612 ucf_flags &= ~UCF_DFS_PATHNAME;
4614 status = filename_convert_dirfsp(ctx,
4615 conn,
4616 newname,
4617 ucf_flags,
4618 dst_twrp,
4619 &dst_dirfsp,
4620 &smb_fname_dst);
4621 if (!NT_STATUS_IS_OK(status)) {
4622 return status;
4625 if (fsp->base_fsp) {
4626 /* No stream names. */
4627 return NT_STATUS_NOT_SUPPORTED;
4630 DEBUG(10,("smb_file_link_information: "
4631 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4632 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4633 smb_fname_str_dbg(smb_fname_dst)));
4634 status = hardlink_internals(ctx,
4635 conn,
4636 req,
4637 overwrite,
4638 fsp->fsp_name,
4639 smb_fname_dst);
4641 TALLOC_FREE(smb_fname_dst);
4642 return status;
4646 /****************************************************************************
4647 Deal with SMB_FILE_RENAME_INFORMATION.
4648 ****************************************************************************/
4650 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4651 struct smb_request *req,
4652 const char *pdata,
4653 int total_data,
4654 files_struct *fsp,
4655 struct smb_filename *smb_fname_src)
4657 bool overwrite;
4658 uint32_t root_fid;
4659 uint32_t len;
4660 char *newname = NULL;
4661 struct files_struct *dst_dirfsp = NULL;
4662 struct smb_filename *smb_fname_dst = NULL;
4663 const char *dst_original_lcomp = NULL;
4664 NTSTATUS status = NT_STATUS_OK;
4665 char *p;
4666 TALLOC_CTX *ctx = talloc_tos();
4668 if (total_data < 13) {
4669 return NT_STATUS_INVALID_PARAMETER;
4672 overwrite = (CVAL(pdata,0) != 0);
4673 root_fid = IVAL(pdata,4);
4674 len = IVAL(pdata,8);
4676 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4677 return NT_STATUS_INVALID_PARAMETER;
4680 if (req->posix_pathnames) {
4681 srvstr_get_path_posix(ctx,
4682 pdata,
4683 req->flags2,
4684 &newname,
4685 &pdata[12],
4686 len,
4688 &status);
4689 } else {
4690 srvstr_get_path(ctx,
4691 pdata,
4692 req->flags2,
4693 &newname,
4694 &pdata[12],
4695 len,
4697 &status);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 return status;
4703 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4704 newname));
4706 /* Check the new name has no '/' characters. */
4707 if (strchr_m(newname, '/')) {
4708 return NT_STATUS_NOT_SUPPORTED;
4711 if (fsp && fsp->base_fsp) {
4712 /* newname must be a stream name. */
4713 if (newname[0] != ':') {
4714 return NT_STATUS_NOT_SUPPORTED;
4717 /* Create an smb_fname to call rename_internals_fsp() with. */
4718 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4719 fsp->base_fsp->fsp_name->base_name,
4720 newname,
4721 NULL,
4722 fsp->base_fsp->fsp_name->twrp,
4723 fsp->base_fsp->fsp_name->flags);
4724 if (smb_fname_dst == NULL) {
4725 status = NT_STATUS_NO_MEMORY;
4726 goto out;
4730 * Get the original last component, since
4731 * rename_internals_fsp() requires it.
4733 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4734 conn,
4735 newname,
4737 if (dst_original_lcomp == NULL) {
4738 status = NT_STATUS_NO_MEMORY;
4739 goto out;
4742 } else {
4744 * Build up an smb_fname_dst based on the filename passed in.
4745 * We basically just strip off the last component, and put on
4746 * the newname instead.
4748 char *base_name = NULL;
4749 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4750 NTTIME dst_twrp = 0;
4752 /* newname must *not* be a stream name. */
4753 if (newname[0] == ':') {
4754 return NT_STATUS_NOT_SUPPORTED;
4758 * Strip off the last component (filename) of the path passed
4759 * in.
4761 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4762 if (!base_name) {
4763 return NT_STATUS_NO_MEMORY;
4765 p = strrchr_m(base_name, '/');
4766 if (p) {
4767 p[1] = '\0';
4768 } else {
4769 base_name = talloc_strdup(ctx, "");
4770 if (!base_name) {
4771 return NT_STATUS_NO_MEMORY;
4774 /* Append the new name. */
4775 base_name = talloc_asprintf_append(base_name,
4776 "%s",
4777 newname);
4778 if (!base_name) {
4779 return NT_STATUS_NO_MEMORY;
4782 if (ucf_flags & UCF_GMT_PATHNAME) {
4783 extract_snapshot_token(base_name, &dst_twrp);
4786 /* The newname is *not* a DFS path. */
4787 ucf_flags &= ~UCF_DFS_PATHNAME;
4789 status = filename_convert_dirfsp(ctx,
4790 conn,
4791 base_name,
4792 ucf_flags,
4793 dst_twrp,
4794 &dst_dirfsp,
4795 &smb_fname_dst);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 goto out;
4800 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4801 conn,
4802 newname,
4803 ucf_flags);
4804 if (dst_original_lcomp == NULL) {
4805 status = NT_STATUS_NO_MEMORY;
4806 goto out;
4810 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4811 DEBUG(10,("smb_file_rename_information: "
4812 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4813 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4814 smb_fname_str_dbg(smb_fname_dst)));
4817 * If no pathnames are open below this directory,
4818 * allow the rename.
4820 if (have_file_open_below(fsp)) {
4821 status = NT_STATUS_ACCESS_DENIED;
4822 goto out;
4825 status = rename_internals_fsp(conn,
4826 fsp,
4827 NULL,
4828 smb_fname_dst,
4829 dst_original_lcomp,
4831 overwrite);
4832 } else {
4833 DEBUG(10,("smb_file_rename_information: "
4834 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4835 smb_fname_str_dbg(smb_fname_src),
4836 smb_fname_str_dbg(smb_fname_dst)));
4837 status = rename_internals(ctx,
4838 conn,
4839 req,
4840 NULL, /* src_dirfsp */
4841 smb_fname_src,
4842 smb_fname_dst,
4843 dst_original_lcomp,
4845 overwrite,
4846 FILE_WRITE_ATTRIBUTES);
4848 out:
4849 TALLOC_FREE(smb_fname_dst);
4850 return status;
4853 /****************************************************************************
4854 Deal with SMB_SET_FILE_BASIC_INFO.
4855 ****************************************************************************/
4857 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4858 const char *pdata,
4859 int total_data,
4860 files_struct *fsp,
4861 struct smb_filename *smb_fname)
4863 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4864 struct smb_file_time ft;
4865 uint32_t dosmode = 0;
4866 NTSTATUS status = NT_STATUS_OK;
4868 init_smb_file_time(&ft);
4870 if (total_data < 36) {
4871 return NT_STATUS_INVALID_PARAMETER;
4874 if (fsp == NULL) {
4875 return NT_STATUS_INVALID_HANDLE;
4878 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 return status;
4883 /* Set the attributes */
4884 dosmode = IVAL(pdata,32);
4885 status = smb_set_file_dosmode(conn, fsp, dosmode);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 return status;
4890 /* create time */
4891 ft.create_time = pull_long_date_full_timespec(pdata);
4893 /* access time */
4894 ft.atime = pull_long_date_full_timespec(pdata+8);
4896 /* write time. */
4897 ft.mtime = pull_long_date_full_timespec(pdata+16);
4899 /* change time. */
4900 ft.ctime = pull_long_date_full_timespec(pdata+24);
4902 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4903 smb_fname_str_dbg(smb_fname)));
4905 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4906 if (!NT_STATUS_IS_OK(status)) {
4907 return status;
4910 if (fsp->fsp_flags.modified) {
4911 trigger_write_time_update_immediate(fsp);
4913 return NT_STATUS_OK;
4916 /****************************************************************************
4917 Deal with SMB_INFO_STANDARD.
4918 ****************************************************************************/
4920 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4921 const char *pdata,
4922 int total_data,
4923 files_struct *fsp,
4924 struct smb_filename *smb_fname)
4926 NTSTATUS status;
4927 struct smb_file_time ft;
4929 init_smb_file_time(&ft);
4931 if (total_data < 12) {
4932 return NT_STATUS_INVALID_PARAMETER;
4935 if (fsp == NULL) {
4936 return NT_STATUS_INVALID_HANDLE;
4939 /* create time */
4940 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4941 /* access time */
4942 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4943 /* write time */
4944 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4946 DEBUG(10,("smb_set_info_standard: file %s\n",
4947 smb_fname_str_dbg(smb_fname)));
4949 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4950 if (!NT_STATUS_IS_OK(status)) {
4951 return status;
4954 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4955 if (!NT_STATUS_IS_OK(status)) {
4956 return status;
4959 if (fsp->fsp_flags.modified) {
4960 trigger_write_time_update_immediate(fsp);
4962 return NT_STATUS_OK;
4965 /****************************************************************************
4966 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4967 ****************************************************************************/
4969 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4970 struct smb_request *req,
4971 const char *pdata,
4972 int total_data,
4973 files_struct *fsp,
4974 struct smb_filename *smb_fname)
4976 uint64_t allocation_size = 0;
4977 NTSTATUS status = NT_STATUS_OK;
4978 files_struct *new_fsp = NULL;
4980 if (!VALID_STAT(smb_fname->st)) {
4981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4984 if (total_data < 8) {
4985 return NT_STATUS_INVALID_PARAMETER;
4988 allocation_size = (uint64_t)IVAL(pdata,0);
4989 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4990 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4991 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4992 (double)allocation_size));
4994 if (allocation_size) {
4995 allocation_size = smb_roundup(conn, allocation_size);
4998 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4999 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5000 (double)allocation_size));
5002 if (fsp &&
5003 !fsp->fsp_flags.is_pathref &&
5004 fsp_get_io_fd(fsp) != -1)
5006 /* Open file handle. */
5007 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
5008 if (!NT_STATUS_IS_OK(status)) {
5009 return status;
5012 /* Only change if needed. */
5013 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5014 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5015 return map_nt_error_from_unix(errno);
5018 /* But always update the time. */
5020 * This is equivalent to a write. Ensure it's seen immediately
5021 * if there are no pending writes.
5023 trigger_write_time_update_immediate(fsp);
5024 return NT_STATUS_OK;
5027 /* Pathname or stat or directory file. */
5028 status = SMB_VFS_CREATE_FILE(
5029 conn, /* conn */
5030 req, /* req */
5031 NULL, /* dirfsp */
5032 smb_fname, /* fname */
5033 FILE_WRITE_DATA, /* access_mask */
5034 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5035 FILE_SHARE_DELETE),
5036 FILE_OPEN, /* create_disposition*/
5037 0, /* create_options */
5038 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5039 0, /* oplock_request */
5040 NULL, /* lease */
5041 0, /* allocation_size */
5042 0, /* private_flags */
5043 NULL, /* sd */
5044 NULL, /* ea_list */
5045 &new_fsp, /* result */
5046 NULL, /* pinfo */
5047 NULL, NULL); /* create context */
5049 if (!NT_STATUS_IS_OK(status)) {
5050 /* NB. We check for open_was_deferred in the caller. */
5051 return status;
5054 /* Only change if needed. */
5055 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5056 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5057 status = map_nt_error_from_unix(errno);
5058 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5059 return status;
5063 /* Changing the allocation size should set the last mod time. */
5065 * This is equivalent to a write. Ensure it's seen immediately
5066 * if there are no pending writes.
5068 trigger_write_time_update_immediate(new_fsp);
5069 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5070 return NT_STATUS_OK;
5073 /****************************************************************************
5074 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5075 ****************************************************************************/
5077 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5078 struct smb_request *req,
5079 const char *pdata,
5080 int total_data,
5081 files_struct *fsp,
5082 struct smb_filename *smb_fname,
5083 bool fail_after_createfile)
5085 off_t size;
5087 if (total_data < 8) {
5088 return NT_STATUS_INVALID_PARAMETER;
5091 size = IVAL(pdata,0);
5092 size |= (((off_t)IVAL(pdata,4)) << 32);
5093 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5094 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5095 (double)size));
5097 return smb_set_file_size(conn, req,
5098 fsp,
5099 smb_fname,
5100 &smb_fname->st,
5101 size,
5102 fail_after_createfile);
5106 * Set an info_level
5108 * Called from the SMB1 and SMB2 code. For the path-based SMB1 code, there may
5109 * not be a full fsp from the FSA layer.
5111 * lck may be NULL, currently only passed for SMB2 rename requests.
5113 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5114 struct smb_request *req,
5115 TALLOC_CTX *mem_ctx,
5116 uint16_t info_level,
5117 files_struct *fsp,
5118 struct share_mode_lock **lck,
5119 struct smb_filename *smb_fname,
5120 char *pdata,
5121 int total_data,
5122 int *ret_data_size)
5124 NTSTATUS status = NT_STATUS_OK;
5125 int data_return_size = 0;
5127 *ret_data_size = 0;
5129 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5130 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5131 fsp_fnum_dbg(fsp),
5132 info_level, total_data));
5134 SMB_ASSERT(fsp != NULL);
5136 switch (info_level) {
5138 case SMB_INFO_STANDARD:
5140 status = smb_set_info_standard(conn,
5141 pdata,
5142 total_data,
5143 fsp,
5144 smb_fname);
5145 break;
5148 case SMB_INFO_SET_EA:
5150 status = smb_info_set_ea(conn,
5151 pdata,
5152 total_data,
5153 fsp,
5154 smb_fname);
5155 break;
5158 case SMB_SET_FILE_BASIC_INFO:
5159 case SMB_FILE_BASIC_INFORMATION:
5161 status = smb_set_file_basic_info(conn,
5162 pdata,
5163 total_data,
5164 fsp,
5165 smb_fname);
5166 break;
5169 case SMB_FILE_ALLOCATION_INFORMATION:
5170 case SMB_SET_FILE_ALLOCATION_INFO:
5172 status = smb_set_file_allocation_info(conn, req,
5173 pdata,
5174 total_data,
5175 fsp,
5176 smb_fname);
5177 break;
5180 case SMB_FILE_END_OF_FILE_INFORMATION:
5181 case SMB_SET_FILE_END_OF_FILE_INFO:
5184 * XP/Win7 both fail after the createfile with
5185 * SMB_SET_FILE_END_OF_FILE_INFO but not
5186 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5187 * The level is known here, so pass it down
5188 * appropriately.
5190 bool should_fail =
5191 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5193 status = smb_set_file_end_of_file_info(conn, req,
5194 pdata,
5195 total_data,
5196 fsp,
5197 smb_fname,
5198 should_fail);
5199 break;
5202 case SMB_FILE_DISPOSITION_INFORMATION:
5203 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5205 status = smb_set_file_disposition_info(conn,
5206 pdata,
5207 total_data,
5208 fsp,
5209 smb_fname);
5210 break;
5213 case SMB_FILE_POSITION_INFORMATION:
5215 status = smb_file_position_information(conn,
5216 pdata,
5217 total_data,
5218 fsp);
5219 break;
5222 case SMB_FILE_FULL_EA_INFORMATION:
5224 status = smb_set_file_full_ea_info(conn,
5225 pdata,
5226 total_data,
5227 fsp);
5228 break;
5231 /* From tridge Samba4 :
5232 * MODE_INFORMATION in setfileinfo (I have no
5233 * idea what "mode information" on a file is - it takes a value of 0,
5234 * 2, 4 or 6. What could it be?).
5237 case SMB_FILE_MODE_INFORMATION:
5239 status = smb_file_mode_information(conn,
5240 pdata,
5241 total_data);
5242 break;
5245 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5246 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5247 case SMB_FILE_SHORT_NAME_INFORMATION:
5248 return NT_STATUS_NOT_SUPPORTED;
5250 case SMB_FILE_RENAME_INFORMATION:
5252 status = smb_file_rename_information(conn, req,
5253 pdata, total_data,
5254 fsp, smb_fname);
5255 break;
5258 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5260 /* SMB2 rename information. */
5261 status = smb2_file_rename_information(conn,
5262 req,
5263 pdata,
5264 total_data,
5265 fsp,
5266 lck,
5267 smb_fname);
5268 break;
5271 case SMB_FILE_LINK_INFORMATION:
5273 if (conn_using_smb2(conn->sconn)) {
5274 status = smb2_file_link_information(conn,
5275 req,
5276 pdata,
5277 total_data,
5278 fsp,
5279 smb_fname);
5280 } else {
5281 status = smb_file_link_information(conn,
5282 req,
5283 pdata,
5284 total_data,
5285 fsp,
5286 smb_fname);
5288 break;
5291 default:
5292 return NT_STATUS_INVALID_LEVEL;
5295 if (!NT_STATUS_IS_OK(status)) {
5296 return status;
5299 *ret_data_size = data_return_size;
5300 return NT_STATUS_OK;
5303 static uint32_t generate_volume_serial_number(
5304 const struct loadparm_substitution *lp_sub,
5305 int snum)
5307 int serial = lp_volume_serial_number(snum);
5308 return serial != -1 ? serial:
5309 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5310 (str_checksum(get_local_machine_name())<<16);