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/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.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"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.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,
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;
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.
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;
91 if (fsp->fsp_flags.is_fsa) {
92 access_granted = fsp->access_mask;
97 if (!(mask & access_requested)) {
102 status = smbd_check_access_rights_fsp(
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
120 if ((access_granted & access_requested) == 0) {
121 return NT_STATUS_ACCESS_DENIED;
124 if (fsp->fsp_name->twrp == 0) {
128 ro_access_granted = access_granted & ro_access;
129 if ((ro_access_granted & access_requested) == 0) {
130 return NT_STATUS_MEDIA_WRITE_PROTECTED;
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);
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);
176 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
177 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
183 /****************************************************************************
184 Get one EA value. Fill in a struct ea_struct.
185 ****************************************************************************/
187 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
190 struct ea_struct *pea)
192 /* Get the value of this xattr. Max size is 64k. */
193 size_t attr_size = 256;
196 size_t max_xattr_size = 0;
200 return NT_STATUS_INVALID_HANDLE;
202 status = refuse_symlink_fsp(fsp);
203 if (!NT_STATUS_IS_OK(status)) {
207 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
211 val = talloc_realloc(mem_ctx, val, char, attr_size);
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;
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);
230 if (strnequal(ea_name, "user.", 5)) {
231 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
233 pea->name = talloc_strdup(mem_ctx, ea_name);
235 if (pea->name == NULL) {
237 return NT_STATUS_NO_MEMORY;
239 pea->value.data = (unsigned char *)val;
240 pea->value.length = (size_t)sizeret;
244 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
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;
258 ssize_t sizeret = -1;
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
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
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,
291 status = map_nt_error_from_unix(errno);
292 TALLOC_FREE(to_free);
296 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
299 TALLOC_FREE(to_free);
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;
317 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
321 *pnum_names = num_names;
323 if (pnames == NULL) {
324 TALLOC_FREE(to_free);
328 names = talloc_array(mem_ctx, char *, num_names);
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) {
339 return NT_STATUS_NO_MEMORY;
342 talloc_steal(names, ea_namelist);
344 ea_namelist = talloc_realloc(names, ea_namelist, char,
346 if (ea_namelist == NULL) {
348 return NT_STATUS_NO_MEMORY;
354 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
355 names[num_names++] = p;
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,
369 size_t *pea_total_len,
370 struct ea_list **ea_list)
372 /* Get a list of all xattrs. Max namesize is 64k. */
375 struct ea_list *ea_list_head = NULL;
376 bool posix_pathnames = false;
387 if (!lp_ea_support(SNUM(fsp->conn))) {
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(),
402 if (!NT_STATUS_IS_OK(status)) {
406 if (num_names == 0) {
410 for (i=0; i<num_names; i++) {
411 struct ea_list *listp;
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
426 if (!strnequal(names[i], "user.", 5)
427 || samba_private_attr_name(names[i]))
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])) {
439 listp = talloc(mem_ctx, struct ea_list);
441 return NT_STATUS_NO_MEMORY;
444 status = get_ea_value_fsp(listp,
449 if (!NT_STATUS_IS_OK(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.
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);
475 push_ascii_fstring(dos_ea_name, listp->ea.name);
478 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
480 DBG_DEBUG("total_len = %zu, %s, val len = %zu\n",
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) {
494 DBG_DEBUG("total_len = %zu\n", *pea_total_len);
496 *ea_list = ea_list_head;
500 /****************************************************************************
501 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
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;
511 SMB_ASSERT(total_data_size >= 4);
513 if (!lp_ea_support(SNUM(conn))) {
518 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
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) {
526 if (ea_list->ea.value.length > 65535) {
529 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
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,
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);
567 if (!lp_ea_support(SNUM(conn))) {
568 return NT_STATUS_NO_EAS_ON_FILE;
571 for (; ea_list; ea_list = ea_list->next) {
577 if (last_start != NULL && do_store_data) {
578 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
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;
594 pad = (4 - (this_size % 4)) % 4;
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);
611 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
615 total_data_size -= this_size;
621 *ret_data_size = PTR_DIFF(p, pdata);
622 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
626 unsigned int estimate_ea_size(files_struct *fsp)
628 size_t total_ea_len = 0;
630 struct ea_list *ea_list = NULL;
638 if (!lp_ea_support(SNUM(fsp->conn))) {
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
648 fsp = metadata_fsp(fsp);
649 (void)get_ea_list_from_fsp(mem_ctx,
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
662 status = fill_ea_chained_buffer(mem_ctx,
668 if (!NT_STATUS_IS_OK(status)) {
671 total_ea_len = ret_data_size;
673 TALLOC_FREE(mem_ctx);
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)
685 TALLOC_CTX *mem_ctx = talloc_tos();
686 struct ea_list *ea_list;
687 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
691 if (!NT_STATUS_IS_OK(status)) {
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);
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)
713 bool posix_pathnames = false;
715 if (!lp_ea_support(SNUM(conn))) {
716 return NT_STATUS_EAS_NOT_SUPPORTED;
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)) {
730 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
731 if (!NT_STATUS_IS_OK(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) {
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",
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",
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);
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",
791 DBG_DEBUG("setting ea name %s on file "
792 "%s by file descriptor.\n",
795 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
796 ea_list->ea.value.data, ea_list->ea.value.length, 0);
801 if (errno == ENOTSUP) {
802 return NT_STATUS_EAS_NOT_SUPPORTED;
805 return map_nt_error_from_unix(errno);
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;
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);
829 DLIST_ADD_END(ea_list_head, eal);
830 offset += bytes_used;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list *ealist)
843 struct ea_list *listp;
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. */
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)) {
876 /* Copy the data from this entry. */
877 nlistp->ea.flags = flistp->ea.flags;
878 nlistp->ea.value = flistp->ea.value;
881 nlistp->ea.flags = 0;
882 ZERO_STRUCT(nlistp->ea.value);
886 *total_ea_len = ea_list_size(name_list);
890 /****************************************************************************
891 Return the filetype for UNIX extensions.
892 ****************************************************************************/
894 static uint32_t unix_filetype(mode_t mode)
897 return UNIX_TYPE_FILE;
898 else if(S_ISDIR(mode))
899 return UNIX_TYPE_DIR;
901 else if(S_ISLNK(mode))
902 return UNIX_TYPE_SYMLINK;
905 else if(S_ISCHR(mode))
906 return UNIX_TYPE_CHARDEV;
909 else if(S_ISBLK(mode))
910 return UNIX_TYPE_BLKDEV;
913 else if(S_ISFIFO(mode))
914 return UNIX_TYPE_FIFO;
917 else if(S_ISSOCK(mode))
918 return UNIX_TYPE_SOCKET;
921 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
922 return UNIX_TYPE_UNKNOWN;
925 /****************************************************************************
926 Map wire perms onto standard UNIX permissions. Obey share restrictions.
927 ****************************************************************************/
929 NTSTATUS unix_perms_from_wire(connection_struct *conn,
930 const SMB_STRUCT_STAT *psbuf,
932 enum perm_type ptype,
937 if (perms == SMB_MODE_NO_CHANGE) {
938 if (!VALID_STAT(*psbuf)) {
939 return NT_STATUS_INVALID_PARAMETER;
941 *ret_perms = psbuf->st_ex_mode;
946 ret = wire_perms_to_unix(perms);
948 if (ptype == PERM_NEW_FILE) {
950 * "create mask"/"force create mode" are
951 * only applied to new files, not existing ones.
953 ret &= lp_create_mask(SNUM(conn));
954 /* Add in force bits */
955 ret |= lp_force_create_mode(SNUM(conn));
956 } else if (ptype == PERM_NEW_DIR) {
958 * "directory mask"/"force directory mode" are
959 * only applied to new directories, not existing ones.
961 ret &= lp_directory_mask(SNUM(conn));
962 /* Add in force bits */
963 ret |= lp_force_directory_mode(SNUM(conn));
970 /****************************************************************************
971 Get a level dependent lanman2 dir entry.
972 ****************************************************************************/
974 struct smbd_dirptr_lanman2_state {
975 connection_struct *conn;
977 bool check_mangled_names;
981 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
987 struct smbd_dirptr_lanman2_state *state =
988 (struct smbd_dirptr_lanman2_state *)private_data;
990 char mangled_name[13]; /* mangled 8.3 name. */
994 /* Mangle fname if it's an illegal name. */
995 if (mangle_must_mangle(dname, state->conn->params)) {
997 * Slow path - ensure we can push the original name as UCS2. If
998 * not, then just don't return this name.
1002 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1003 uint8_t *tmp = talloc_array(talloc_tos(),
1007 status = srvstr_push(NULL,
1008 FLAGS2_UNICODE_STRINGS,
1017 if (!NT_STATUS_IS_OK(status)) {
1021 ok = name_to_8_3(dname, mangled_name,
1022 true, state->conn->params);
1026 fname = mangled_name;
1031 got_match = mask_match(fname, mask,
1032 state->case_sensitive);
1034 if(!got_match && state->check_mangled_names &&
1035 !mangle_is_8_3(fname, false, state->conn->params)) {
1037 * It turns out that NT matches wildcards against
1038 * both long *and* short names. This may explain some
1039 * of the wildcard weirdness from old DOS clients
1040 * that some people have been seeing.... JRA.
1042 /* Force the mangling into 8.3. */
1043 ok = name_to_8_3(fname, mangled_name,
1044 false, state->conn->params);
1049 got_match = mask_match(mangled_name, mask,
1050 state->case_sensitive);
1057 *_fname = talloc_strdup(ctx, fname);
1058 if (*_fname == NULL) {
1065 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1067 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1068 unsigned ea_size = estimate_ea_size(fsp);
1071 return IO_REPARSE_TAG_DFS;
1074 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1075 connection_struct *conn,
1077 uint32_t info_level,
1078 struct ea_list *name_list,
1079 bool check_mangled_names,
1080 bool requires_resume_key,
1083 const struct smb_filename *smb_fname,
1084 int space_remaining,
1090 uint64_t *last_entry_off)
1092 char *p, *q, *pdata = *ppdata;
1094 uint64_t file_size = 0;
1095 uint64_t allocation_size = 0;
1096 uint64_t file_id = 0;
1098 struct timespec mdate_ts = {0};
1099 struct timespec adate_ts = {0};
1100 struct timespec cdate_ts = {0};
1101 struct timespec create_date_ts = {0};
1103 char *last_entry_ptr;
1108 struct readdir_attr_data *readdir_attr_data = NULL;
1111 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1112 file_size = get_file_size_stat(&smb_fname->st);
1114 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1117 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1120 if (smb_fname->fsp != NULL &&
1121 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1122 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1124 &readdir_attr_data);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1133 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1135 mdate_ts = smb_fname->st.st_ex_mtime;
1136 adate_ts = smb_fname->st.st_ex_atime;
1137 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1138 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1140 if (lp_dos_filetime_resolution(SNUM(conn))) {
1141 dos_filetime_timespec(&create_date_ts);
1142 dos_filetime_timespec(&mdate_ts);
1143 dos_filetime_timespec(&adate_ts);
1144 dos_filetime_timespec(&cdate_ts);
1147 /* align the record */
1148 SMB_ASSERT(align >= 1);
1150 off = (int)PTR_DIFF(pdata, base_data);
1151 pad = (off + (align-1)) & ~(align-1);
1154 if (pad && pad > space_remaining) {
1155 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1156 "for padding (wanted %u, had %d)\n",
1159 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1163 /* initialize padding to 0 */
1165 memset(pdata, 0, pad);
1167 space_remaining -= pad;
1169 DBG_DEBUG("space_remaining = %d\n", space_remaining);
1178 switch (info_level) {
1179 case SMB_FIND_INFO_STANDARD:
1180 DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1181 if(requires_resume_key) {
1185 srv_put_dos_date2_ts(p, 0, create_date_ts);
1186 srv_put_dos_date2_ts(p, 4, adate_ts);
1187 srv_put_dos_date2_ts(p, 8, mdate_ts);
1188 SIVAL(p,12,(uint32_t)file_size);
1189 SIVAL(p,16,(uint32_t)allocation_size);
1193 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1194 p += ucs2_align(base_data, p, 0);
1196 status = srvstr_push(base_data, flags2, p,
1197 fname, PTR_DIFF(end_data, p),
1198 STR_TERMINATE, &len);
1199 if (!NT_STATUS_IS_OK(status)) {
1202 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1204 SCVAL(nameptr, -1, len - 2);
1206 SCVAL(nameptr, -1, 0);
1210 SCVAL(nameptr, -1, len - 1);
1212 SCVAL(nameptr, -1, 0);
1218 case SMB_FIND_EA_SIZE:
1219 DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1220 if (requires_resume_key) {
1224 srv_put_dos_date2_ts(p, 0, create_date_ts);
1225 srv_put_dos_date2_ts(p, 4, adate_ts);
1226 srv_put_dos_date2_ts(p, 8, mdate_ts);
1227 SIVAL(p,12,(uint32_t)file_size);
1228 SIVAL(p,16,(uint32_t)allocation_size);
1231 ea_size = estimate_ea_size(smb_fname->fsp);
1232 SIVAL(p,22,ea_size); /* Extended attributes */
1236 status = srvstr_push(base_data, flags2,
1237 p, fname, PTR_DIFF(end_data, p),
1238 STR_TERMINATE | STR_NOALIGN, &len);
1239 if (!NT_STATUS_IS_OK(status)) {
1242 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1255 SCVAL(nameptr,0,len);
1257 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1260 case SMB_FIND_EA_LIST:
1262 struct ea_list *file_list = NULL;
1265 DBG_DEBUG("SMB_FIND_EA_LIST\n");
1267 return NT_STATUS_INVALID_PARAMETER;
1269 if (requires_resume_key) {
1273 srv_put_dos_date2_ts(p, 0, create_date_ts);
1274 srv_put_dos_date2_ts(p, 4, adate_ts);
1275 srv_put_dos_date2_ts(p, 8, mdate_ts);
1276 SIVAL(p,12,(uint32_t)file_size);
1277 SIVAL(p,16,(uint32_t)allocation_size);
1279 p += 22; /* p now points to the EA area. */
1281 status = get_ea_list_from_fsp(ctx,
1283 &ea_len, &file_list);
1284 if (!NT_STATUS_IS_OK(status)) {
1287 name_list = ea_list_union(name_list, file_list, &ea_len);
1289 /* We need to determine if this entry will fit in the space available. */
1290 /* Max string size is 255 bytes. */
1291 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1292 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1293 "(wanted %u, had %d)\n",
1294 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1296 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1299 /* Push the ea_data followed by the name. */
1300 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1302 status = srvstr_push(base_data, flags2,
1303 p + 1, fname, PTR_DIFF(end_data, p+1),
1304 STR_TERMINATE | STR_NOALIGN, &len);
1305 if (!NT_STATUS_IS_OK(status)) {
1308 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1321 SCVAL(nameptr,0,len);
1323 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1327 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1328 DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1329 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1331 SIVAL(p,0,reskey); p += 4;
1332 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1333 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1334 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1335 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1336 SOFF_T(p,0,file_size); p += 8;
1337 SOFF_T(p,0,allocation_size); p += 8;
1338 SIVAL(p,0,mode); p += 4;
1339 q = p; p += 4; /* q is placeholder for name length. */
1340 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1341 SIVAL(p, 0, ea_size);
1343 /* Clear the short name buffer. This is
1344 * IMPORTANT as not doing so will trigger
1345 * a Win2k client bug. JRA.
1347 if (!was_8_3 && check_mangled_names) {
1348 char mangled_name[13]; /* mangled 8.3 name. */
1349 if (!name_to_8_3(fname,mangled_name,True,
1351 /* Error - mangle failed ! */
1352 memset(mangled_name,'\0',12);
1354 mangled_name[12] = 0;
1355 status = srvstr_push(base_data, flags2,
1356 p+2, mangled_name, 24,
1357 STR_UPPER|STR_UNICODE, &len);
1358 if (!NT_STATUS_IS_OK(status)) {
1362 memset(p + 2 + len,'\0',24 - len);
1369 status = srvstr_push(base_data, flags2, p,
1370 fname, PTR_DIFF(end_data, p),
1371 STR_TERMINATE_ASCII, &len);
1372 if (!NT_STATUS_IS_OK(status)) {
1378 len = PTR_DIFF(p, pdata);
1379 pad = (len + (align-1)) & ~(align-1);
1381 * offset to the next entry, the caller
1382 * will overwrite it for the last entry
1383 * that's why we always include the padding
1387 * set padding to zero
1390 memset(p, 0, pad - len);
1397 case SMB_FIND_FILE_DIRECTORY_INFO:
1398 DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1400 SIVAL(p,0,reskey); p += 4;
1401 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1402 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1403 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1404 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1405 SOFF_T(p,0,file_size); p += 8;
1406 SOFF_T(p,0,allocation_size); p += 8;
1407 SIVAL(p,0,mode); p += 4;
1408 status = srvstr_push(base_data, flags2,
1409 p + 4, fname, PTR_DIFF(end_data, p+4),
1410 STR_TERMINATE_ASCII, &len);
1411 if (!NT_STATUS_IS_OK(status)) {
1417 len = PTR_DIFF(p, pdata);
1418 pad = (len + (align-1)) & ~(align-1);
1420 * offset to the next entry, the caller
1421 * will overwrite it for the last entry
1422 * that's why we always include the padding
1426 * set padding to zero
1429 memset(p, 0, pad - len);
1436 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1437 DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1439 SIVAL(p,0,reskey); p += 4;
1440 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1441 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1442 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1443 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1444 SOFF_T(p,0,file_size); p += 8;
1445 SOFF_T(p,0,allocation_size); p += 8;
1446 SIVAL(p,0,mode); p += 4;
1447 q = p; p += 4; /* q is placeholder for name length. */
1448 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1449 SIVAL(p, 0, ea_size);
1451 status = srvstr_push(base_data, flags2, p,
1452 fname, PTR_DIFF(end_data, p),
1453 STR_TERMINATE_ASCII, &len);
1454 if (!NT_STATUS_IS_OK(status)) {
1460 len = PTR_DIFF(p, pdata);
1461 pad = (len + (align-1)) & ~(align-1);
1463 * offset to the next entry, the caller
1464 * will overwrite it for the last entry
1465 * that's why we always include the padding
1469 * set padding to zero
1472 memset(p, 0, pad - len);
1479 case SMB_FIND_FILE_NAMES_INFO:
1480 DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1482 SIVAL(p,0,reskey); p += 4;
1484 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1485 acl on a dir (tridge) */
1486 status = srvstr_push(base_data, flags2, p,
1487 fname, PTR_DIFF(end_data, p),
1488 STR_TERMINATE_ASCII, &len);
1489 if (!NT_STATUS_IS_OK(status)) {
1495 len = PTR_DIFF(p, pdata);
1496 pad = (len + (align-1)) & ~(align-1);
1498 * offset to the next entry, the caller
1499 * will overwrite it for the last entry
1500 * that's why we always include the padding
1504 * set padding to zero
1507 memset(p, 0, pad - len);
1514 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1515 DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1517 SIVAL(p,0,reskey); p += 4;
1518 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1519 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1520 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1521 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1522 SOFF_T(p,0,file_size); p += 8;
1523 SOFF_T(p,0,allocation_size); p += 8;
1524 SIVAL(p,0,mode); p += 4;
1525 q = p; p += 4; /* q is placeholder for name length. */
1526 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1527 SIVAL(p, 0, ea_size);
1529 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1530 SBVAL(p,0,file_id); p += 8;
1531 status = srvstr_push(base_data, flags2, p,
1532 fname, PTR_DIFF(end_data, p),
1533 STR_TERMINATE_ASCII, &len);
1534 if (!NT_STATUS_IS_OK(status)) {
1540 len = PTR_DIFF(p, pdata);
1541 pad = (len + (align-1)) & ~(align-1);
1543 * offset to the next entry, the caller
1544 * will overwrite it for the last entry
1545 * that's why we always include the padding
1549 * set padding to zero
1552 memset(p, 0, pad - len);
1559 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1560 DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1561 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1563 SIVAL(p,0,reskey); p += 4;
1564 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1565 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1566 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1567 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1568 SOFF_T(p,0,file_size); p += 8;
1569 SOFF_T(p,0,allocation_size); p += 8;
1570 SIVAL(p,0,mode); p += 4;
1571 q = p; p += 4; /* q is placeholder for name length */
1572 if (readdir_attr_data &&
1573 readdir_attr_data->type == RDATTR_AAPL) {
1575 * OS X specific SMB2 extension negotiated via
1576 * AAPL create context: return max_access in
1579 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1581 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1583 SIVAL(p,0,ea_size); /* Extended attributes */
1586 if (readdir_attr_data &&
1587 readdir_attr_data->type == RDATTR_AAPL) {
1589 * OS X specific SMB2 extension negotiated via
1590 * AAPL create context: return resource fork
1591 * length and compressed FinderInfo in
1594 * According to documentation short_name_len
1595 * should be 0, but on the wire behaviour
1596 * shows its set to 24 by clients.
1600 /* Resourefork length */
1601 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1603 /* Compressed FinderInfo */
1604 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1605 } else if (!was_8_3 && check_mangled_names) {
1606 char mangled_name[13]; /* mangled 8.3 name. */
1607 if (!name_to_8_3(fname,mangled_name,True,
1609 /* Error - mangle failed ! */
1610 memset(mangled_name,'\0',12);
1612 mangled_name[12] = 0;
1613 status = srvstr_push(base_data, flags2,
1614 p+2, mangled_name, 24,
1615 STR_UPPER|STR_UNICODE, &len);
1616 if (!NT_STATUS_IS_OK(status)) {
1621 memset(p + 2 + len,'\0',24 - len);
1625 /* Clear the short name buffer. This is
1626 * IMPORTANT as not doing so will trigger
1627 * a Win2k client bug. JRA.
1634 if (readdir_attr_data &&
1635 readdir_attr_data->type == RDATTR_AAPL) {
1637 * OS X specific SMB2 extension negotiated via
1638 * AAPL create context: return UNIX mode in
1641 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1642 SSVAL(p, 0, aapl_mode);
1648 SBVAL(p,0,file_id); p += 8;
1649 status = srvstr_push(base_data, flags2, p,
1650 fname, PTR_DIFF(end_data, p),
1651 STR_TERMINATE_ASCII, &len);
1652 if (!NT_STATUS_IS_OK(status)) {
1658 len = PTR_DIFF(p, pdata);
1659 pad = (len + (align-1)) & ~(align-1);
1661 * offset to the next entry, the caller
1662 * will overwrite it for the last entry
1663 * that's why we always include the padding
1667 * set padding to zero
1670 memset(p, 0, pad - len);
1677 /* CIFS UNIX Extension. */
1679 case SMB_FIND_FILE_UNIX:
1680 case SMB_FIND_FILE_UNIX_INFO2:
1682 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1684 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1686 if (info_level == SMB_FIND_FILE_UNIX) {
1687 DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1688 p = store_file_unix_basic(conn, p,
1689 NULL, &smb_fname->st);
1690 status = srvstr_push(base_data, flags2, p,
1691 fname, PTR_DIFF(end_data, p),
1692 STR_TERMINATE, &len);
1693 if (!NT_STATUS_IS_OK(status)) {
1697 DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1698 p = store_file_unix_basic_info2(conn, p,
1699 NULL, &smb_fname->st);
1702 status = srvstr_push(base_data, flags2, p, fname,
1703 PTR_DIFF(end_data, p), 0, &len);
1704 if (!NT_STATUS_IS_OK(status)) {
1707 SIVAL(nameptr, 0, len);
1712 len = PTR_DIFF(p, pdata);
1713 pad = (len + (align-1)) & ~(align-1);
1715 * offset to the next entry, the caller
1716 * will overwrite it for the last entry
1717 * that's why we always include the padding
1721 * set padding to zero
1724 memset(p, 0, pad - len);
1729 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1733 /* SMB2 UNIX Extension. */
1735 case SMB2_FILE_POSIX_INFORMATION:
1737 struct smb3_file_posix_information info = {};
1738 uint8_t buf[sizeof(info)];
1739 struct ndr_push ndr = {
1741 .alloc_size = sizeof(buf),
1742 .fixed_buf_size = true,
1744 enum ndr_err_code ndr_err;
1746 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1749 SIVAL(p,0,reskey); p+= 4;
1751 if (!conn_using_smb2(conn->sconn)) {
1752 return NT_STATUS_INVALID_LEVEL;
1755 smb3_file_posix_information_init(
1756 conn, &smb_fname->st, 0, mode, &info);
1758 ndr_err = ndr_push_smb3_file_posix_information(
1759 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1760 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1761 return NT_STATUS_INSUFFICIENT_RESOURCES;
1764 memcpy(p, buf, ndr.offset);
1769 status = srvstr_push(base_data, flags2, p, fname,
1770 PTR_DIFF(end_data, p), 0, &len);
1771 if (!NT_STATUS_IS_OK(status)) {
1774 SIVAL(nameptr, 0, len);
1778 len = PTR_DIFF(p, pdata);
1779 pad = (len + (align-1)) & ~(align-1);
1781 * offset to the next entry, the caller
1782 * will overwrite it for the last entry
1783 * that's why we always include the padding
1790 return NT_STATUS_INVALID_LEVEL;
1793 if (PTR_DIFF(p,pdata) > space_remaining) {
1794 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1795 "(wanted %u, had %d)\n",
1796 (unsigned int)PTR_DIFF(p,pdata),
1798 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1801 /* Setup the last entry pointer, as an offset from base_data */
1802 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1803 /* Advance the data pointer to the next slot */
1806 return NT_STATUS_OK;
1809 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1810 connection_struct *conn,
1811 struct dptr_struct *dirptr,
1813 const char *path_mask,
1816 int requires_resume_key,
1825 int space_remaining,
1826 struct smb_filename **_smb_fname,
1827 int *_last_entry_off,
1828 struct ea_list *name_list,
1829 struct file_id *file_id)
1832 const char *mask = NULL;
1835 struct smb_filename *smb_fname = NULL;
1836 struct smbd_dirptr_lanman2_state state;
1838 uint64_t last_entry_off = 0;
1840 enum mangled_names_options mangled_names;
1841 bool marshall_with_83_names;
1843 mangled_names = lp_mangled_names(conn->params);
1847 state.info_level = info_level;
1848 if (mangled_names != MANGLED_NAMES_NO) {
1849 state.check_mangled_names = true;
1851 state.case_sensitive = dptr_case_sensitive(dirptr);
1853 p = strrchr_m(path_mask,'/');
1864 ok = smbd_dirptr_get_entry(ctx,
1871 smbd_dirptr_lanman2_match_fn,
1877 return NT_STATUS_END_OF_FILE;
1880 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1882 status = smbd_marshall_dir_entry(ctx,
1887 marshall_with_83_names,
1888 requires_resume_key,
1899 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1900 DEBUG(1,("Conversion error: illegal character: %s\n",
1901 smb_fname_str_dbg(smb_fname)));
1904 if (file_id != NULL) {
1905 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1908 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1909 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 TALLOC_FREE(smb_fname);
1918 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1920 if (_smb_fname != NULL) {
1922 * smb_fname is already talloc'ed off ctx.
1923 * We just need to make sure we don't return
1924 * any stream_name, and replace base_name
1925 * with fname in case base_name got mangled.
1926 * This allows us to preserve any smb_fname->fsp
1927 * for asynchronous handle lookups.
1929 TALLOC_FREE(smb_fname->stream_name);
1932 * smbd_dirptr_set_last_name_sent() above consumed
1935 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1937 if (smb_fname->base_name == NULL) {
1938 TALLOC_FREE(smb_fname);
1940 return NT_STATUS_NO_MEMORY;
1942 *_smb_fname = smb_fname;
1944 TALLOC_FREE(smb_fname);
1948 *_last_entry_off = last_entry_off;
1949 return NT_STATUS_OK;
1952 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1954 const struct loadparm_substitution *lp_sub =
1955 loadparm_s3_global_substitution();
1957 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1961 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1963 SMB_ASSERT(extended_info != NULL);
1965 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1966 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1967 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1968 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1969 #ifdef SAMBA_VERSION_REVISION
1970 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1972 extended_info->samba_subversion = 0;
1973 #ifdef SAMBA_VERSION_RC_RELEASE
1974 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1976 #ifdef SAMBA_VERSION_PRE_RELEASE
1977 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1980 #ifdef SAMBA_VERSION_VENDOR_PATCH
1981 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1983 extended_info->samba_gitcommitdate = 0;
1984 #ifdef SAMBA_VERSION_COMMIT_TIME
1985 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1988 memset(extended_info->samba_version_string, 0,
1989 sizeof(extended_info->samba_version_string));
1991 snprintf (extended_info->samba_version_string,
1992 sizeof(extended_info->samba_version_string),
1993 "%s", samba_version_string());
1996 static bool fsinfo_unix_valid_level(connection_struct *conn,
1997 struct files_struct *fsp,
1998 uint16_t info_level)
2000 if (conn_using_smb2(conn->sconn) &&
2001 fsp->posix_flags == FSP_POSIX_FLAGS_OPEN &&
2002 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
2006 #if defined(SMB1SERVER)
2007 if (lp_smb1_unix_extensions() &&
2008 info_level == SMB_QUERY_POSIX_FS_INFO) {
2016 * fsp is only valid for SMB2.
2018 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2019 connection_struct *conn,
2020 TALLOC_CTX *mem_ctx,
2021 uint16_t info_level,
2023 unsigned int max_data_bytes,
2024 size_t *fixed_portion,
2025 struct files_struct *fsp,
2026 struct smb_filename *fname,
2030 const struct loadparm_substitution *lp_sub =
2031 loadparm_s3_global_substitution();
2032 char *pdata, *end_data;
2035 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2036 int snum = SNUM(conn);
2037 const char *fstype = lp_fstype(SNUM(conn));
2038 const char *filename = NULL;
2039 const uint64_t bytes_per_sector = 512;
2040 uint32_t additional_flags = 0;
2041 struct smb_filename smb_fname;
2043 NTSTATUS status = NT_STATUS_OK;
2047 if (fname == NULL || fname->base_name == NULL) {
2050 filename = fname->base_name;
2054 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2055 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2056 "info level (0x%x) on IPC$.\n",
2057 (unsigned int)info_level));
2058 return NT_STATUS_ACCESS_DENIED;
2062 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2064 smb_fname = (struct smb_filename) {
2065 .base_name = discard_const_p(char, filename),
2066 .flags = fname ? fname->flags : 0,
2067 .twrp = fname ? fname->twrp : 0,
2070 if(info_level != SMB_FS_QUOTA_INFORMATION
2071 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2072 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2073 return map_nt_error_from_unix(errno);
2078 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2079 return NT_STATUS_INVALID_PARAMETER;
2082 *ppdata = (char *)SMB_REALLOC(
2083 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2084 if (*ppdata == NULL) {
2085 return NT_STATUS_NO_MEMORY;
2089 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2090 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2094 switch (info_level) {
2095 case SMB_INFO_ALLOCATION:
2097 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2099 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2101 if (df_ret == (uint64_t)-1) {
2102 return map_nt_error_from_unix(errno);
2105 block_size = lp_block_size(snum);
2106 if (bsize < block_size) {
2107 uint64_t factor = block_size/bsize;
2112 if (bsize > block_size) {
2113 uint64_t factor = bsize/block_size;
2118 sectors_per_unit = bsize/bytes_per_sector;
2120 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2121 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2122 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2125 * For large drives, return max values and not modulo.
2127 dsize = MIN(dsize, UINT32_MAX);
2128 dfree = MIN(dfree, UINT32_MAX);
2130 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2131 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2132 SIVAL(pdata,l1_cUnit,dsize);
2133 SIVAL(pdata,l1_cUnitAvail,dfree);
2134 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2138 case SMB_INFO_VOLUME:
2139 /* Return volume name */
2141 * Add volume serial number - hash of a combination of
2142 * the called hostname and the service name.
2144 serial = generate_volume_serial_number(lp_sub, snum);
2145 SIVAL(pdata,0,serial);
2147 * Win2k3 and previous mess this up by sending a name length
2148 * one byte short. I believe only older clients (OS/2 Win9x) use
2149 * this call so try fixing this by adding a terminating null to
2150 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2152 status = srvstr_push(
2154 pdata+l2_vol_szVolLabel, vname,
2155 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2156 STR_NOALIGN|STR_TERMINATE, &len);
2157 if (!NT_STATUS_IS_OK(status)) {
2160 SCVAL(pdata,l2_vol_cch,len);
2161 data_len = l2_vol_szVolLabel + len;
2162 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2163 "name = %s serial = 0x%04"PRIx32"\n",
2164 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2165 (unsigned)len, vname, serial));
2168 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2169 case SMB_FS_ATTRIBUTE_INFORMATION:
2171 additional_flags = 0;
2172 #if defined(HAVE_SYS_QUOTAS)
2173 additional_flags |= FILE_VOLUME_QUOTAS;
2176 if(lp_nt_acl_support(SNUM(conn))) {
2177 additional_flags |= FILE_PERSISTENT_ACLS;
2180 /* Capabilities are filled in at connection time through STATVFS call */
2181 additional_flags |= conn->fs_capabilities;
2182 additional_flags |= lp_parm_int(conn->params->service,
2183 "share", "fake_fscaps",
2186 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2187 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2188 additional_flags); /* FS ATTRIBUTES */
2190 SIVAL(pdata,4,255); /* Max filename component length */
2191 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2192 and will think we can't do long filenames */
2193 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2194 PTR_DIFF(end_data, pdata+12),
2196 if (!NT_STATUS_IS_OK(status)) {
2200 data_len = 12 + len;
2201 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2202 /* the client only requested a portion of the
2204 data_len = max_data_bytes;
2205 status = STATUS_BUFFER_OVERFLOW;
2207 *fixed_portion = 16;
2210 case SMB_QUERY_FS_LABEL_INFO:
2211 case SMB_FS_LABEL_INFORMATION:
2212 status = srvstr_push(pdata, flags2, pdata+4, vname,
2213 PTR_DIFF(end_data, pdata+4), 0, &len);
2214 if (!NT_STATUS_IS_OK(status)) {
2221 case SMB_QUERY_FS_VOLUME_INFO:
2222 case SMB_FS_VOLUME_INFORMATION:
2223 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2224 pdata, &st.st_ex_btime);
2226 * Add volume serial number - hash of a combination of
2227 * the called hostname and the service name.
2229 serial = generate_volume_serial_number(lp_sub, snum);
2230 SIVAL(pdata,8,serial);
2232 /* Max label len is 32 characters. */
2233 status = srvstr_push(pdata, flags2, pdata+18, vname,
2234 PTR_DIFF(end_data, pdata+18),
2236 if (!NT_STATUS_IS_OK(status)) {
2239 SIVAL(pdata,12,len);
2242 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2243 "namelen = %d, vol=%s serv=%s "
2244 "serial=0x%04"PRIx32"\n",
2245 (int)strlen(vname),vname,
2246 lp_servicename(talloc_tos(), lp_sub, snum),
2248 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2249 /* the client only requested a portion of the
2251 data_len = max_data_bytes;
2252 status = STATUS_BUFFER_OVERFLOW;
2254 *fixed_portion = 24;
2257 case SMB_QUERY_FS_SIZE_INFO:
2258 case SMB_FS_SIZE_INFORMATION:
2260 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2262 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2264 if (df_ret == (uint64_t)-1) {
2265 return map_nt_error_from_unix(errno);
2267 block_size = lp_block_size(snum);
2268 if (bsize < block_size) {
2269 uint64_t factor = block_size/bsize;
2274 if (bsize > block_size) {
2275 uint64_t factor = bsize/block_size;
2280 sectors_per_unit = bsize/bytes_per_sector;
2281 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2282 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2283 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2284 SBIG_UINT(pdata,0,dsize);
2285 SBIG_UINT(pdata,8,dfree);
2286 SIVAL(pdata,16,sectors_per_unit);
2287 SIVAL(pdata,20,bytes_per_sector);
2288 *fixed_portion = 24;
2292 case SMB_FS_FULL_SIZE_INFORMATION:
2294 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2296 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2298 if (df_ret == (uint64_t)-1) {
2299 return map_nt_error_from_unix(errno);
2301 block_size = lp_block_size(snum);
2302 if (bsize < block_size) {
2303 uint64_t factor = block_size/bsize;
2308 if (bsize > block_size) {
2309 uint64_t factor = bsize/block_size;
2314 sectors_per_unit = bsize/bytes_per_sector;
2315 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2316 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2317 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2318 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2319 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2320 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2321 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2322 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2323 *fixed_portion = 32;
2327 case SMB_QUERY_FS_DEVICE_INFO:
2328 case SMB_FS_DEVICE_INFORMATION:
2330 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2332 if (!CAN_WRITE(conn)) {
2333 characteristics |= FILE_READ_ONLY_DEVICE;
2336 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2337 SIVAL(pdata,4,characteristics);
2342 #ifdef HAVE_SYS_QUOTAS
2343 case SMB_FS_QUOTA_INFORMATION:
2345 * what we have to send --metze:
2347 * Unknown1: 24 NULL bytes
2348 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2349 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2350 * Quota Flags: 2 byte :
2351 * Unknown3: 6 NULL bytes
2355 * details for Quota Flags:
2357 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2358 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2359 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2360 * 0x0001 Enable Quotas: enable quota for this fs
2364 /* we need to fake up a fsp here,
2365 * because its not send in this call
2367 files_struct tmpfsp;
2368 SMB_NTQUOTA_STRUCT quotas;
2370 ZERO_STRUCT(tmpfsp);
2371 ZERO_STRUCT(quotas);
2374 tmpfsp.fnum = FNUM_FIELD_INVALID;
2377 if (get_current_uid(conn) != 0) {
2378 DEBUG(0,("get_user_quota: access_denied "
2379 "service [%s] user [%s]\n",
2380 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2381 conn->session_info->unix_info->unix_name));
2382 return NT_STATUS_ACCESS_DENIED;
2385 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2387 if (!NT_STATUS_IS_OK(status)) {
2388 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2394 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2395 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2397 /* Unknown1 24 NULL bytes*/
2398 SBIG_UINT(pdata,0,(uint64_t)0);
2399 SBIG_UINT(pdata,8,(uint64_t)0);
2400 SBIG_UINT(pdata,16,(uint64_t)0);
2402 /* Default Soft Quota 8 bytes */
2403 SBIG_UINT(pdata,24,quotas.softlim);
2405 /* Default Hard Quota 8 bytes */
2406 SBIG_UINT(pdata,32,quotas.hardlim);
2408 /* Quota flag 2 bytes */
2409 SSVAL(pdata,40,quotas.qflags);
2411 /* Unknown3 6 NULL bytes */
2417 #endif /* HAVE_SYS_QUOTAS */
2418 case SMB_FS_OBJECTID_INFORMATION:
2420 unsigned char objid[16];
2421 struct smb_extended_info extended_info;
2422 memcpy(pdata,create_volume_objectid(conn, objid),16);
2423 samba_extended_info_version (&extended_info);
2424 SIVAL(pdata,16,extended_info.samba_magic);
2425 SIVAL(pdata,20,extended_info.samba_version);
2426 SIVAL(pdata,24,extended_info.samba_subversion);
2427 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2428 memcpy(pdata+36,extended_info.samba_version_string,28);
2433 case SMB_FS_SECTOR_SIZE_INFORMATION:
2437 * These values match a physical Windows Server 2012
2438 * share backed by NTFS atop spinning rust.
2440 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2441 /* logical_bytes_per_sector */
2442 SIVAL(pdata, 0, bytes_per_sector);
2443 /* phys_bytes_per_sector_atomic */
2444 SIVAL(pdata, 4, bytes_per_sector);
2445 /* phys_bytes_per_sector_perf */
2446 SIVAL(pdata, 8, bytes_per_sector);
2447 /* fs_effective_phys_bytes_per_sector_atomic */
2448 SIVAL(pdata, 12, bytes_per_sector);
2450 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2451 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2452 /* byte_off_sector_align */
2453 SIVAL(pdata, 20, 0);
2454 /* byte_off_partition_align */
2455 SIVAL(pdata, 24, 0);
2456 *fixed_portion = 28;
2461 #if defined(WITH_SMB1SERVER)
2463 * Query the version and capabilities of the CIFS UNIX extensions
2467 case SMB_QUERY_CIFS_UNIX_INFO:
2469 bool large_write = lp_min_receive_file_size() &&
2470 !smb1_srv_is_signing_active(xconn);
2471 bool large_read = !smb1_srv_is_signing_active(xconn);
2472 int encrypt_caps = 0;
2474 if (!lp_smb1_unix_extensions()) {
2475 return NT_STATUS_INVALID_LEVEL;
2478 switch (conn->encrypt_level) {
2479 case SMB_SIGNING_OFF:
2482 case SMB_SIGNING_DESIRED:
2483 case SMB_SIGNING_IF_REQUIRED:
2484 case SMB_SIGNING_DEFAULT:
2485 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2487 case SMB_SIGNING_REQUIRED:
2488 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2489 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2490 large_write = false;
2496 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2497 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2499 /* We have POSIX ACLs, pathname, encryption,
2500 * large read/write, and locking capability. */
2502 SBIG_UINT(pdata,4,((uint64_t)(
2503 CIFS_UNIX_POSIX_ACLS_CAP|
2504 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2505 CIFS_UNIX_FCNTL_LOCKS_CAP|
2506 CIFS_UNIX_EXTATTR_CAP|
2507 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2509 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2511 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2516 case SMB_QUERY_POSIX_FS_INFO:
2517 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2520 struct vfs_statvfs_struct svfs;
2522 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2523 return NT_STATUS_INVALID_LEVEL;
2526 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2530 SIVAL(pdata,0,svfs.OptimalTransferSize);
2531 SIVAL(pdata,4,svfs.BlockSize);
2532 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2533 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2534 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2535 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2536 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2537 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2538 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2540 } else if (rc == EOPNOTSUPP) {
2541 return NT_STATUS_INVALID_LEVEL;
2542 #endif /* EOPNOTSUPP */
2544 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2545 return NT_STATUS_DOS(ERRSRV, ERRerror);
2550 case SMB_QUERY_POSIX_WHOAMI:
2556 if (!lp_smb1_unix_extensions()) {
2557 return NT_STATUS_INVALID_LEVEL;
2560 if (max_data_bytes < 40) {
2561 return NT_STATUS_BUFFER_TOO_SMALL;
2564 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2565 flags |= SMB_WHOAMI_GUEST;
2568 /* NOTE: 8 bytes for UID/GID, irrespective of native
2569 * platform size. This matches
2570 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2572 data_len = 4 /* flags */
2579 + 4 /* pad/reserved */
2580 + (conn->session_info->unix_token->ngroups * 8)
2582 + (conn->session_info->security_token->num_sids *
2586 SIVAL(pdata, 0, flags);
2587 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2589 (uint64_t)conn->session_info->unix_token->uid);
2590 SBIG_UINT(pdata, 16,
2591 (uint64_t)conn->session_info->unix_token->gid);
2594 if (data_len >= max_data_bytes) {
2595 /* Potential overflow, skip the GIDs and SIDs. */
2597 SIVAL(pdata, 24, 0); /* num_groups */
2598 SIVAL(pdata, 28, 0); /* num_sids */
2599 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2600 SIVAL(pdata, 36, 0); /* reserved */
2606 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2607 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2609 /* We walk the SID list twice, but this call is fairly
2610 * infrequent, and I don't expect that it's performance
2611 * sensitive -- jpeach
2613 for (i = 0, sid_bytes = 0;
2614 i < conn->session_info->security_token->num_sids; ++i) {
2615 sid_bytes += ndr_size_dom_sid(
2616 &conn->session_info->security_token->sids[i],
2620 /* SID list byte count */
2621 SIVAL(pdata, 32, sid_bytes);
2623 /* 4 bytes pad/reserved - must be zero */
2624 SIVAL(pdata, 36, 0);
2628 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2629 SBIG_UINT(pdata, data_len,
2630 (uint64_t)conn->session_info->unix_token->groups[i]);
2636 i < conn->session_info->security_token->num_sids; ++i) {
2637 int sid_len = ndr_size_dom_sid(
2638 &conn->session_info->security_token->sids[i],
2641 sid_linearize((uint8_t *)(pdata + data_len),
2643 &conn->session_info->security_token->sids[i]);
2644 data_len += sid_len;
2650 case SMB_MAC_QUERY_FS_INFO:
2652 * Thursby MAC extension... ONLY on NTFS filesystems
2653 * once we do streams then we don't need this
2655 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2657 SIVAL(pdata,84,0x100); /* Don't support mac... */
2663 return NT_STATUS_INVALID_LEVEL;
2666 *ret_data_len = data_len;
2670 NTSTATUS smb_set_fsquota(connection_struct *conn,
2671 struct smb_request *req,
2673 const DATA_BLOB *qdata)
2675 const struct loadparm_substitution *lp_sub =
2676 loadparm_s3_global_substitution();
2678 SMB_NTQUOTA_STRUCT quotas;
2680 ZERO_STRUCT(quotas);
2683 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2684 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2685 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2686 conn->session_info->unix_info->unix_name);
2687 return NT_STATUS_ACCESS_DENIED;
2690 if (!check_fsp_ntquota_handle(conn, req,
2692 DBG_WARNING("no valid QUOTA HANDLE\n");
2693 return NT_STATUS_INVALID_HANDLE;
2696 /* note: normally there're 48 bytes,
2697 * but we didn't use the last 6 bytes for now
2700 if (qdata->length < 42) {
2701 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2703 return NT_STATUS_INVALID_PARAMETER;
2706 /* unknown_1 24 NULL bytes in pdata*/
2708 /* the soft quotas 8 bytes (uint64_t)*/
2709 quotas.softlim = BVAL(qdata->data,24);
2711 /* the hard quotas 8 bytes (uint64_t)*/
2712 quotas.hardlim = BVAL(qdata->data,32);
2714 /* quota_flags 2 bytes **/
2715 quotas.qflags = SVAL(qdata->data,40);
2717 /* unknown_2 6 NULL bytes follow*/
2719 /* now set the quotas */
2720 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2721 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2722 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2723 status = map_nt_error_from_unix(errno);
2725 status = NT_STATUS_OK;
2730 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2731 struct smb_request *req,
2732 TALLOC_CTX *mem_ctx,
2733 uint16_t info_level,
2735 const DATA_BLOB *pdata)
2737 switch (info_level) {
2738 case SMB_FS_QUOTA_INFORMATION:
2740 return smb_set_fsquota(conn,
2749 return NT_STATUS_INVALID_LEVEL;
2752 /****************************************************************************
2753 Store the FILE_UNIX_BASIC info.
2754 ****************************************************************************/
2756 char *store_file_unix_basic(connection_struct *conn,
2759 const SMB_STRUCT_STAT *psbuf)
2763 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2764 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2766 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2769 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2772 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2773 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2774 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2777 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2781 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2785 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2788 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2789 devno = psbuf->st_ex_rdev;
2791 devno = psbuf->st_ex_dev;
2794 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2798 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2802 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2805 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2809 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2816 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2817 * the chflags(2) (or equivalent) flags.
2819 * XXX: this really should be behind the VFS interface. To do this, we would
2820 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2821 * Each VFS module could then implement its own mapping as appropriate for the
2822 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2824 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2828 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2832 { UF_IMMUTABLE, EXT_IMMUTABLE },
2836 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2840 { UF_HIDDEN, EXT_HIDDEN },
2843 /* Do not remove. We need to guarantee that this array has at least one
2844 * entry to build on HP-UX.
2850 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2851 uint32_t *smb_fflags, uint32_t *smb_fmask)
2855 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2856 *smb_fmask |= info2_flags_map[i].smb_fflag;
2857 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2858 *smb_fflags |= info2_flags_map[i].smb_fflag;
2863 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2864 const uint32_t smb_fflags,
2865 const uint32_t smb_fmask,
2868 uint32_t max_fmask = 0;
2871 *stat_fflags = psbuf->st_ex_flags;
2873 /* For each flags requested in smb_fmask, check the state of the
2874 * corresponding flag in smb_fflags and set or clear the matching
2878 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2879 max_fmask |= info2_flags_map[i].smb_fflag;
2880 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2881 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2882 *stat_fflags |= info2_flags_map[i].stat_fflag;
2884 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2889 /* If smb_fmask is asking to set any bits that are not supported by
2890 * our flag mappings, we should fail.
2892 if ((smb_fmask & max_fmask) != smb_fmask) {
2900 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2901 * of file flags and birth (create) time.
2903 char *store_file_unix_basic_info2(connection_struct *conn,
2906 const SMB_STRUCT_STAT *psbuf)
2908 uint32_t file_flags = 0;
2909 uint32_t flags_mask = 0;
2911 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2913 /* Create (birth) time 64 bit */
2914 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2917 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2918 SIVAL(pdata, 0, file_flags); /* flags */
2919 SIVAL(pdata, 4, flags_mask); /* mask */
2925 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2926 const struct stream_struct *streams,
2928 unsigned int max_data_bytes,
2929 unsigned int *data_size)
2932 unsigned int ofs = 0;
2934 if (max_data_bytes < 32) {
2935 return NT_STATUS_INFO_LENGTH_MISMATCH;
2938 for (i = 0; i < num_streams; i++) {
2939 unsigned int next_offset;
2941 smb_ucs2_t *namebuf;
2943 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2944 streams[i].name, &namelen) ||
2947 return NT_STATUS_INVALID_PARAMETER;
2951 * name_buf is now null-terminated, we need to marshall as not
2958 * We cannot overflow ...
2960 if ((ofs + 24 + namelen) > max_data_bytes) {
2961 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2963 TALLOC_FREE(namebuf);
2964 return STATUS_BUFFER_OVERFLOW;
2967 SIVAL(data, ofs+4, namelen);
2968 SOFF_T(data, ofs+8, streams[i].size);
2969 SOFF_T(data, ofs+16, streams[i].alloc_size);
2970 memcpy(data+ofs+24, namebuf, namelen);
2971 TALLOC_FREE(namebuf);
2973 next_offset = ofs + 24 + namelen;
2975 if (i == num_streams-1) {
2976 SIVAL(data, ofs, 0);
2979 unsigned int align = ndr_align_size(next_offset, 8);
2981 if ((next_offset + align) > max_data_bytes) {
2982 DEBUG(10, ("refusing to overflow align "
2983 "reply at stream %u\n",
2985 TALLOC_FREE(namebuf);
2986 return STATUS_BUFFER_OVERFLOW;
2989 memset(data+next_offset, 0, align);
2990 next_offset += align;
2992 SIVAL(data, ofs, next_offset - ofs);
2999 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3003 return NT_STATUS_OK;
3006 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3007 TALLOC_CTX *mem_ctx,
3008 struct smb_request *req,
3009 uint16_t info_level,
3011 struct smb_filename *smb_fname,
3012 bool delete_pending,
3013 struct timespec write_time_ts,
3014 struct ea_list *ea_list,
3016 unsigned int max_data_bytes,
3017 size_t *fixed_portion,
3019 unsigned int *pdata_size)
3021 char *pdata = *ppdata;
3022 char *dstart, *dend;
3023 unsigned int data_size;
3024 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3025 SMB_STRUCT_STAT *psbuf = NULL;
3026 SMB_STRUCT_STAT *base_sp = NULL;
3033 uint64_t file_size = 0;
3035 uint64_t allocation_size = 0;
3036 uint64_t file_id = 0;
3037 uint32_t access_mask = 0;
3040 if (INFO_LEVEL_IS_UNIX(info_level)) {
3043 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3044 DBG_DEBUG("SMB1 unix extensions activated\n");
3048 if (conn_using_smb2(conn->sconn) &&
3049 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN))
3051 DBG_DEBUG("SMB2 posix open\n");
3056 return NT_STATUS_INVALID_LEVEL;
3060 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3061 smb_fname_str_dbg(smb_fname),
3063 info_level, max_data_bytes);
3066 * In case of querying a symlink in POSIX context,
3067 * fsp will be NULL. fdos_mode() deals with it.
3070 smb_fname = fsp->fsp_name;
3072 mode = fdos_mode(fsp);
3073 psbuf = &smb_fname->st;
3076 base_sp = fsp->base_fsp ?
3077 &fsp->base_fsp->fsp_name->st :
3080 base_sp = &smb_fname->st;
3083 nlink = psbuf->st_ex_nlink;
3085 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3089 if ((nlink > 0) && delete_pending) {
3093 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3094 return NT_STATUS_INVALID_PARAMETER;
3097 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3098 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3099 if (*ppdata == NULL) {
3100 return NT_STATUS_NO_MEMORY;
3104 dend = dstart + data_size - 1;
3106 if (!is_omit_timespec(&write_time_ts) &&
3107 !INFO_LEVEL_IS_UNIX(info_level))
3109 update_stat_ex_mtime(psbuf, write_time_ts);
3112 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3113 mtime_ts = psbuf->st_ex_mtime;
3114 atime_ts = psbuf->st_ex_atime;
3115 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3117 if (lp_dos_filetime_resolution(SNUM(conn))) {
3118 dos_filetime_timespec(&create_time_ts);
3119 dos_filetime_timespec(&mtime_ts);
3120 dos_filetime_timespec(&atime_ts);
3121 dos_filetime_timespec(&ctime_ts);
3124 p = strrchr_m(smb_fname->base_name,'/');
3126 base_name = smb_fname->base_name;
3131 /* NT expects the name to be in an exact form of the *full*
3132 filename. See the trans2 torture test */
3133 if (ISDOT(base_name)) {
3134 dos_fname = talloc_strdup(mem_ctx, "\\");
3136 return NT_STATUS_NO_MEMORY;
3139 dos_fname = talloc_asprintf(mem_ctx,
3141 smb_fname->base_name);
3143 return NT_STATUS_NO_MEMORY;
3145 if (is_named_stream(smb_fname)) {
3146 dos_fname = talloc_asprintf(dos_fname, "%s",
3147 smb_fname->stream_name);
3149 return NT_STATUS_NO_MEMORY;
3153 string_replace(dos_fname, '/', '\\');
3156 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3158 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3159 /* Do we have this path open ? */
3160 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3161 files_struct *fsp1 = file_find_di_first(
3162 conn->sconn, fileid, true);
3163 if (fsp1 && fsp1->initial_allocation_size) {
3164 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3168 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3169 file_size = get_file_size_stat(psbuf);
3173 pos = fh_get_position_information(fsp->fh);
3177 access_mask = fsp->access_mask;
3179 /* GENERIC_EXECUTE mapping from Windows */
3180 access_mask = 0x12019F;
3183 /* This should be an index number - looks like
3186 I think this causes us to fail the IFSKIT
3187 BasicFileInformationTest. -tpot */
3188 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3192 switch (info_level) {
3193 case SMB_INFO_STANDARD:
3194 DBG_DEBUG("SMB_INFO_STANDARD\n");
3196 srv_put_dos_date2_ts(pdata,
3199 srv_put_dos_date2_ts(pdata,
3202 srv_put_dos_date2_ts(pdata,
3204 mtime_ts); /* write time */
3205 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3206 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3207 SSVAL(pdata,l1_attrFile,mode);
3210 case SMB_INFO_QUERY_EA_SIZE:
3212 unsigned int ea_size =
3213 estimate_ea_size(smb_fname->fsp);
3214 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3216 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3217 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3218 srv_put_dos_date2_ts(pdata,
3220 mtime_ts); /* write time */
3221 SIVAL(pdata,12,(uint32_t)file_size);
3222 SIVAL(pdata,16,(uint32_t)allocation_size);
3223 SSVAL(pdata,20,mode);
3224 SIVAL(pdata,22,ea_size);
3228 case SMB_INFO_IS_NAME_VALID:
3229 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3231 /* os/2 needs this ? really ?*/
3232 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3234 /* This is only reached for qpathinfo */
3238 case SMB_INFO_QUERY_EAS_FROM_LIST:
3240 size_t total_ea_len = 0;
3241 struct ea_list *ea_file_list = NULL;
3242 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3245 get_ea_list_from_fsp(mem_ctx,
3247 &total_ea_len, &ea_file_list);
3248 if (!NT_STATUS_IS_OK(status)) {
3252 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3254 if (!ea_list || (total_ea_len > data_size)) {
3256 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3260 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3264 case SMB_INFO_QUERY_ALL_EAS:
3266 /* We have data_size bytes to put EA's into. */
3267 size_t total_ea_len = 0;
3268 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3270 status = get_ea_list_from_fsp(mem_ctx,
3272 &total_ea_len, &ea_list);
3273 if (!NT_STATUS_IS_OK(status)) {
3277 if (!ea_list || (total_ea_len > data_size)) {
3279 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3283 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3287 case SMB2_FILE_FULL_EA_INFORMATION:
3289 /* We have data_size bytes to put EA's into. */
3290 size_t total_ea_len = 0;
3291 struct ea_list *ea_file_list = NULL;
3293 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3295 /*TODO: add filtering and index handling */
3298 get_ea_list_from_fsp(mem_ctx,
3300 &total_ea_len, &ea_file_list);
3301 if (!NT_STATUS_IS_OK(status)) {
3304 if (!ea_file_list) {
3305 return NT_STATUS_NO_EAS_ON_FILE;
3308 status = fill_ea_chained_buffer(mem_ctx,
3312 conn, ea_file_list);
3313 if (!NT_STATUS_IS_OK(status)) {
3319 case SMB_FILE_BASIC_INFORMATION:
3320 case SMB_QUERY_FILE_BASIC_INFO:
3322 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3323 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3324 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3326 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3330 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3331 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3332 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3333 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3334 SIVAL(pdata,32,mode);
3336 DBG_INFO("SMB_QFBI - create: %s access: %s "
3337 "write: %s change: %s mode: %x\n",
3338 ctime(&create_time_ts.tv_sec),
3339 ctime(&atime_ts.tv_sec),
3340 ctime(&mtime_ts.tv_sec),
3341 ctime(&ctime_ts.tv_sec),
3343 *fixed_portion = data_size;
3346 case SMB_FILE_STANDARD_INFORMATION:
3347 case SMB_QUERY_FILE_STANDARD_INFO:
3349 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3351 SOFF_T(pdata,0,allocation_size);
3352 SOFF_T(pdata,8,file_size);
3353 SIVAL(pdata,16,nlink);
3354 SCVAL(pdata,20,delete_pending?1:0);
3355 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3356 SSVAL(pdata,22,0); /* Padding. */
3357 *fixed_portion = 24;
3360 case SMB_FILE_EA_INFORMATION:
3361 case SMB_QUERY_FILE_EA_INFO:
3363 unsigned int ea_size =
3364 estimate_ea_size(smb_fname->fsp);
3365 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3368 SIVAL(pdata,0,ea_size);
3372 /* Get the 8.3 name - used if NT SMB was negotiated. */
3373 case SMB_QUERY_FILE_ALT_NAME_INFO:
3374 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3376 char mangled_name[13];
3377 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3378 if (!name_to_8_3(base_name,mangled_name,
3379 True,conn->params)) {
3380 return NT_STATUS_NO_MEMORY;
3382 status = srvstr_push(dstart, flags2,
3383 pdata+4, mangled_name,
3384 PTR_DIFF(dend, pdata+4),
3386 if (!NT_STATUS_IS_OK(status)) {
3389 data_size = 4 + len;
3395 case SMB_QUERY_FILE_NAME_INFO:
3398 this must be *exactly* right for ACLs on mapped drives to work
3400 status = srvstr_push(dstart, flags2,
3402 PTR_DIFF(dend, pdata+4),
3404 if (!NT_STATUS_IS_OK(status)) {
3407 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3408 data_size = 4 + len;
3413 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3415 char *nfname = NULL;
3418 !conn_using_smb2(fsp->conn->sconn)) {
3419 return NT_STATUS_INVALID_LEVEL;
3422 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3423 if (nfname == NULL) {
3424 return NT_STATUS_NO_MEMORY;
3427 if (ISDOT(nfname)) {
3430 string_replace(nfname, '/', '\\');
3432 if (fsp_is_alternate_stream(fsp)) {
3433 const char *s = smb_fname->stream_name;
3434 const char *e = NULL;
3437 SMB_ASSERT(s[0] != '\0');
3440 * smb_fname->stream_name is in form
3441 * of ':StrEam:$DATA', but we should only
3442 * append ':StrEam' here.
3445 e = strchr(&s[1], ':');
3451 nfname = talloc_strndup_append(nfname, s, n);
3452 if (nfname == NULL) {
3453 return NT_STATUS_NO_MEMORY;
3457 status = srvstr_push(dstart, flags2,
3459 PTR_DIFF(dend, pdata+4),
3461 if (!NT_STATUS_IS_OK(status)) {
3464 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3465 data_size = 4 + len;
3471 case SMB_FILE_ALLOCATION_INFORMATION:
3472 case SMB_QUERY_FILE_ALLOCATION_INFO:
3473 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3475 SOFF_T(pdata,0,allocation_size);
3478 case SMB_FILE_END_OF_FILE_INFORMATION:
3479 case SMB_QUERY_FILE_END_OF_FILEINFO:
3480 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3482 SOFF_T(pdata,0,file_size);
3485 case SMB_QUERY_FILE_ALL_INFO:
3486 case SMB_FILE_ALL_INFORMATION:
3488 unsigned int ea_size =
3489 estimate_ea_size(smb_fname->fsp);
3490 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3491 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3492 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3493 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3494 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3495 SIVAL(pdata,32,mode);
3496 SIVAL(pdata,36,0); /* padding. */
3498 SOFF_T(pdata,0,allocation_size);
3499 SOFF_T(pdata,8,file_size);
3500 SIVAL(pdata,16,nlink);
3501 SCVAL(pdata,20,delete_pending);
3502 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3505 SIVAL(pdata,0,ea_size);
3506 pdata += 4; /* EA info */
3507 status = srvstr_push(dstart, flags2,
3509 PTR_DIFF(dend, pdata+4),
3511 if (!NT_STATUS_IS_OK(status)) {
3516 data_size = PTR_DIFF(pdata,(*ppdata));
3517 *fixed_portion = 10;
3521 case SMB2_FILE_ALL_INFORMATION:
3523 unsigned int ea_size =
3524 estimate_ea_size(smb_fname->fsp);
3525 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3526 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3527 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3528 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3529 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3530 SIVAL(pdata, 0x20, mode);
3531 SIVAL(pdata, 0x24, 0); /* padding. */
3532 SBVAL(pdata, 0x28, allocation_size);
3533 SBVAL(pdata, 0x30, file_size);
3534 SIVAL(pdata, 0x38, nlink);
3535 SCVAL(pdata, 0x3C, delete_pending);
3536 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3537 SSVAL(pdata, 0x3E, 0); /* padding */
3538 SBVAL(pdata, 0x40, file_id);
3539 SIVAL(pdata, 0x48, ea_size);
3540 SIVAL(pdata, 0x4C, access_mask);
3541 SBVAL(pdata, 0x50, pos);
3542 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3543 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3547 status = srvstr_push(dstart, flags2,
3549 PTR_DIFF(dend, pdata+4),
3551 if (!NT_STATUS_IS_OK(status)) {
3556 data_size = PTR_DIFF(pdata,(*ppdata));
3557 *fixed_portion = 104;
3560 case SMB_FILE_INTERNAL_INFORMATION:
3562 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3563 SBVAL(pdata, 0, file_id);
3568 case SMB_FILE_ACCESS_INFORMATION:
3569 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3570 SIVAL(pdata, 0, access_mask);
3575 case SMB_FILE_NAME_INFORMATION:
3576 /* Pathname with leading '\'. */
3579 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3580 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3581 SIVAL(pdata,0,byte_len);
3582 data_size = 4 + byte_len;
3586 case SMB_FILE_DISPOSITION_INFORMATION:
3587 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3589 SCVAL(pdata,0,delete_pending);
3593 case SMB_FILE_POSITION_INFORMATION:
3594 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3596 SOFF_T(pdata,0,pos);
3600 case SMB_FILE_MODE_INFORMATION:
3601 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3602 SIVAL(pdata,0,mode);
3607 case SMB_FILE_ALIGNMENT_INFORMATION:
3608 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3609 SIVAL(pdata,0,0); /* No alignment needed. */
3615 * NT4 server just returns "invalid query" to this - if we try
3616 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3619 /* The first statement above is false - verified using Thursby
3620 * client against NT4 -- gcolley.
3622 case SMB_QUERY_FILE_STREAM_INFO:
3623 case SMB_FILE_STREAM_INFORMATION: {
3624 unsigned int num_streams = 0;
3625 struct stream_struct *streams = NULL;
3627 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3629 if (is_ntfs_stream_smb_fname(smb_fname)) {
3630 return NT_STATUS_INVALID_PARAMETER;
3633 status = vfs_fstreaminfo(fsp,
3638 if (!NT_STATUS_IS_OK(status)) {
3639 DBG_DEBUG("could not get stream info: %s\n",
3644 status = marshall_stream_info(num_streams, streams,
3645 pdata, max_data_bytes,
3648 if (!NT_STATUS_IS_OK(status)) {
3649 DBG_DEBUG("marshall_stream_info failed: %s\n",
3651 TALLOC_FREE(streams);
3655 TALLOC_FREE(streams);
3657 *fixed_portion = 32;
3661 case SMB_QUERY_COMPRESSION_INFO:
3662 case SMB_FILE_COMPRESSION_INFORMATION:
3663 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3664 SOFF_T(pdata,0,file_size);
3665 SIVAL(pdata,8,0); /* ??? */
3666 SIVAL(pdata,12,0); /* ??? */
3668 *fixed_portion = 16;
3671 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3672 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3673 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3674 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3675 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3676 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3677 SOFF_T(pdata,32,allocation_size);
3678 SOFF_T(pdata,40,file_size);
3679 SIVAL(pdata,48,mode);
3680 SIVAL(pdata,52,0); /* ??? */
3682 *fixed_portion = 56;
3685 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: {
3687 uint8_t *data = NULL;
3690 DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3692 (void)fsctl_get_reparse_point(fsp,
3700 SIVAL(pdata, 0, mode);
3701 SIVAL(pdata, 4, tag);
3707 * SMB2 UNIX Extensions.
3709 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3711 struct smb3_file_posix_information info = {};
3712 uint8_t buf[sizeof(info)];
3713 struct ndr_push ndr = {
3715 .alloc_size = sizeof(buf),
3716 .fixed_buf_size = true,
3718 enum ndr_err_code ndr_err;
3720 if (!conn_using_smb2(conn->sconn)) {
3721 return NT_STATUS_INVALID_LEVEL;
3724 return NT_STATUS_INVALID_HANDLE;
3726 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3727 return NT_STATUS_INVALID_LEVEL;
3730 smb3_file_posix_information_init(
3731 conn, &smb_fname->st, 0, mode, &info);
3733 ndr_err = ndr_push_smb3_file_posix_information(
3734 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3735 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3736 return NT_STATUS_INSUFFICIENT_RESOURCES;
3739 memcpy(pdata, buf, ndr.offset);
3740 data_size = ndr.offset;
3745 return NT_STATUS_INVALID_LEVEL;
3748 *pdata_size = data_size;
3749 return NT_STATUS_OK;
3752 /****************************************************************************
3753 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3755 ****************************************************************************/
3757 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3758 connection_struct *conn,
3759 struct smb_request *req,
3760 bool overwrite_if_exists,
3761 const struct smb_filename *smb_fname_old,
3762 struct smb_filename *smb_fname_new)
3764 NTSTATUS status = NT_STATUS_OK;
3767 struct smb_filename *parent_fname_old = NULL;
3768 struct smb_filename *base_name_old = NULL;
3769 struct smb_filename *parent_fname_new = NULL;
3770 struct smb_filename *base_name_new = NULL;
3772 /* source must already exist. */
3773 if (!VALID_STAT(smb_fname_old->st)) {
3774 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3778 /* No links from a directory. */
3779 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3780 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3784 /* Setting a hardlink to/from a stream isn't currently supported. */
3785 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3787 DBG_DEBUG("Old name has streams\n");
3788 status = NT_STATUS_INVALID_PARAMETER;
3791 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3793 DBG_DEBUG("New name has streams\n");
3794 status = NT_STATUS_INVALID_PARAMETER;
3798 if (smb_fname_old->twrp != 0) {
3799 status = NT_STATUS_NOT_SAME_DEVICE;
3803 status = parent_pathref(talloc_tos(),
3808 if (!NT_STATUS_IS_OK(status)) {
3812 status = parent_pathref(talloc_tos(),
3817 if (!NT_STATUS_IS_OK(status)) {
3821 if (VALID_STAT(smb_fname_new->st)) {
3822 if (overwrite_if_exists) {
3823 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3824 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3827 status = unlink_internals(conn,
3829 FILE_ATTRIBUTE_NORMAL,
3830 NULL, /* new_dirfsp */
3832 if (!NT_STATUS_IS_OK(status)) {
3836 /* Disallow if newname already exists. */
3837 status = NT_STATUS_OBJECT_NAME_COLLISION;
3842 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3843 smb_fname_old->base_name, smb_fname_new->base_name));
3845 ret = SMB_VFS_LINKAT(conn,
3846 parent_fname_old->fsp,
3848 parent_fname_new->fsp,
3853 status = map_nt_error_from_unix(errno);
3854 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3855 nt_errstr(status), smb_fname_old->base_name,
3856 smb_fname_new->base_name));
3861 TALLOC_FREE(parent_fname_old);
3862 TALLOC_FREE(parent_fname_new);
3866 /****************************************************************************
3867 Deal with setting the time from any of the setfilepathinfo functions.
3868 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3869 calling this function.
3870 ****************************************************************************/
3872 NTSTATUS smb_set_file_time(connection_struct *conn,
3874 struct smb_filename *smb_fname,
3875 struct smb_file_time *ft,
3876 bool setting_write_time)
3878 struct files_struct *set_fsp = NULL;
3879 struct timeval_buf tbuf[4];
3881 FILE_NOTIFY_CHANGE_LAST_ACCESS
3882 |FILE_NOTIFY_CHANGE_LAST_WRITE
3883 |FILE_NOTIFY_CHANGE_CREATION;
3886 if (!VALID_STAT(smb_fname->st)) {
3887 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3892 return NT_STATUS_OK;
3895 set_fsp = metadata_fsp(fsp);
3897 /* get some defaults (no modifications) if any info is zero or -1. */
3898 if (is_omit_timespec(&ft->create_time)) {
3899 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3902 if (is_omit_timespec(&ft->atime)) {
3903 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3906 if (is_omit_timespec(&ft->mtime)) {
3907 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3910 if (!setting_write_time) {
3911 /* ft->mtime comes from change time, not write time. */
3912 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3915 /* Ensure the resolution is the correct for
3916 * what we can store on this filesystem. */
3918 round_timespec(conn->ts_res, &ft->create_time);
3919 round_timespec(conn->ts_res, &ft->ctime);
3920 round_timespec(conn->ts_res, &ft->atime);
3921 round_timespec(conn->ts_res, &ft->mtime);
3923 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3924 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3925 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3926 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3927 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3928 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3929 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3930 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3932 if (setting_write_time) {
3934 * This was a Windows setfileinfo on an open file.
3935 * NT does this a lot. We also need to
3936 * set the time here, as it can be read by
3937 * FindFirst/FindNext and with the patch for bug #2045
3938 * in smbd/fileio.c it ensures that this timestamp is
3939 * kept sticky even after a write. We save the request
3940 * away and will set it on file close and after a write. JRA.
3943 DBG_DEBUG("setting pending modtime to %s\n",
3944 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3946 if (set_fsp != NULL) {
3947 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3949 set_sticky_write_time_path(
3950 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3955 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3957 ret = file_ntimes(conn, set_fsp, ft);
3959 return map_nt_error_from_unix(errno);
3962 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3963 smb_fname->base_name);
3964 return NT_STATUS_OK;
3967 /****************************************************************************
3968 Deal with setting the dosmode from any of the setfilepathinfo functions.
3969 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3970 done before calling this function.
3971 ****************************************************************************/
3973 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3974 struct files_struct *fsp,
3977 struct files_struct *dos_fsp = NULL;
3978 uint32_t current_dosmode;
3981 if (!VALID_STAT(fsp->fsp_name->st)) {
3982 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3985 dos_fsp = metadata_fsp(fsp);
3988 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3989 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3991 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3995 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3997 /* check the mode isn't different, before changing it */
3999 return NT_STATUS_OK;
4001 current_dosmode = fdos_mode(dos_fsp);
4002 if (dosmode == current_dosmode) {
4003 return NT_STATUS_OK;
4006 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4007 fsp_str_dbg(dos_fsp), dosmode);
4009 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4011 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4012 fsp_str_dbg(dos_fsp), strerror(errno));
4013 return map_nt_error_from_unix(errno);
4016 return NT_STATUS_OK;
4019 /****************************************************************************
4020 Deal with setting the size from any of the setfilepathinfo functions.
4021 ****************************************************************************/
4023 NTSTATUS smb_set_file_size(connection_struct *conn,
4024 struct smb_request *req,
4026 struct smb_filename *smb_fname,
4027 const SMB_STRUCT_STAT *psbuf,
4029 bool fail_after_createfile)
4031 NTSTATUS status = NT_STATUS_OK;
4032 files_struct *new_fsp = NULL;
4034 if (!VALID_STAT(*psbuf)) {
4035 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4038 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4040 get_file_size_stat(psbuf));
4042 if (size == get_file_size_stat(psbuf)) {
4044 return NT_STATUS_OK;
4046 if (!fsp->fsp_flags.modified) {
4047 return NT_STATUS_OK;
4049 trigger_write_time_update_immediate(fsp);
4050 return NT_STATUS_OK;
4053 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4054 smb_fname_str_dbg(smb_fname), (double)size));
4057 !fsp->fsp_flags.is_pathref &&
4058 fsp_get_io_fd(fsp) != -1)
4060 /* Handle based call. */
4061 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4062 if (!NT_STATUS_IS_OK(status)) {
4066 if (vfs_set_filelen(fsp, size) == -1) {
4067 return map_nt_error_from_unix(errno);
4069 trigger_write_time_update_immediate(fsp);
4070 return NT_STATUS_OK;
4073 status = SMB_VFS_CREATE_FILE(
4077 smb_fname, /* fname */
4078 FILE_WRITE_DATA, /* access_mask */
4079 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4081 FILE_OPEN, /* create_disposition*/
4082 0, /* create_options */
4083 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4084 0, /* oplock_request */
4086 0, /* allocation_size */
4087 0, /* private_flags */
4090 &new_fsp, /* result */
4092 NULL, NULL); /* create context */
4094 if (!NT_STATUS_IS_OK(status)) {
4095 /* NB. We check for open_was_deferred in the caller. */
4099 /* See RAW-SFILEINFO-END-OF-FILE */
4100 if (fail_after_createfile) {
4101 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4102 return NT_STATUS_INVALID_LEVEL;
4105 if (vfs_set_filelen(new_fsp, size) == -1) {
4106 status = map_nt_error_from_unix(errno);
4107 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4111 trigger_write_time_update_immediate(new_fsp);
4112 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4113 return NT_STATUS_OK;
4116 /****************************************************************************
4117 Deal with SMB_INFO_SET_EA.
4118 ****************************************************************************/
4120 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4124 struct smb_filename *smb_fname)
4126 struct ea_list *ea_list = NULL;
4127 TALLOC_CTX *ctx = NULL;
4128 NTSTATUS status = NT_STATUS_OK;
4130 if (total_data < 10) {
4132 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4133 length. They seem to have no effect. Bug #3212. JRA */
4135 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4136 /* We're done. We only get EA info in this call. */
4137 return NT_STATUS_OK;
4140 return NT_STATUS_INVALID_PARAMETER;
4143 if (IVAL(pdata,0) > total_data) {
4144 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4145 IVAL(pdata,0), (unsigned int)total_data));
4146 return NT_STATUS_INVALID_PARAMETER;
4150 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4152 return NT_STATUS_INVALID_PARAMETER;
4157 * The only way fsp can be NULL here is if
4158 * smb_fname points at a symlink and
4159 * and we're in POSIX context.
4160 * Ensure this is the case.
4162 * In this case we cannot set the EA.
4164 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4165 return NT_STATUS_ACCESS_DENIED;
4168 status = set_ea(conn, fsp, ea_list);
4173 /****************************************************************************
4174 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4175 ****************************************************************************/
4177 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4182 struct ea_list *ea_list = NULL;
4186 return NT_STATUS_INVALID_HANDLE;
4189 if (!lp_ea_support(SNUM(conn))) {
4190 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4191 "EA's not supported.\n",
4192 (unsigned int)total_data));
4193 return NT_STATUS_EAS_NOT_SUPPORTED;
4196 if (total_data < 10) {
4197 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4199 (unsigned int)total_data));
4200 return NT_STATUS_INVALID_PARAMETER;
4203 ea_list = read_nttrans_ea_list(talloc_tos(),
4208 return NT_STATUS_INVALID_PARAMETER;
4211 status = set_ea(conn, fsp, ea_list);
4213 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4214 smb_fname_str_dbg(fsp->fsp_name),
4215 nt_errstr(status) ));
4221 /****************************************************************************
4222 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4223 ****************************************************************************/
4225 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4229 struct smb_filename *smb_fname)
4231 NTSTATUS status = NT_STATUS_OK;
4232 bool delete_on_close;
4233 uint32_t dosmode = 0;
4235 if (total_data < 1) {
4236 return NT_STATUS_INVALID_PARAMETER;
4240 return NT_STATUS_INVALID_HANDLE;
4243 delete_on_close = (CVAL(pdata,0) ? True : False);
4244 dosmode = fdos_mode(fsp);
4246 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4247 "delete_on_close = %u\n",
4248 smb_fname_str_dbg(smb_fname),
4249 (unsigned int)dosmode,
4250 (unsigned int)delete_on_close ));
4252 if (delete_on_close) {
4253 status = can_set_delete_on_close(fsp, dosmode);
4254 if (!NT_STATUS_IS_OK(status)) {
4259 /* The set is across all open files on this dev/inode pair. */
4260 if (!set_delete_on_close(fsp, delete_on_close,
4261 conn->session_info->security_token,
4262 conn->session_info->unix_token)) {
4263 return NT_STATUS_ACCESS_DENIED;
4265 return NT_STATUS_OK;
4268 /****************************************************************************
4269 Deal with SMB_FILE_POSITION_INFORMATION.
4270 ****************************************************************************/
4272 static NTSTATUS smb_file_position_information(connection_struct *conn,
4277 uint64_t position_information;
4279 if (total_data < 8) {
4280 return NT_STATUS_INVALID_PARAMETER;
4284 /* Ignore on pathname based set. */
4285 return NT_STATUS_OK;
4288 position_information = (uint64_t)IVAL(pdata,0);
4289 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4291 DEBUG(10,("smb_file_position_information: Set file position "
4292 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4293 (double)position_information));
4294 fh_set_position_information(fsp->fh, position_information);
4295 return NT_STATUS_OK;
4298 /****************************************************************************
4299 Deal with SMB_FILE_MODE_INFORMATION.
4300 ****************************************************************************/
4302 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4308 if (total_data < 4) {
4309 return NT_STATUS_INVALID_PARAMETER;
4311 mode = IVAL(pdata,0);
4312 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4313 return NT_STATUS_INVALID_PARAMETER;
4315 return NT_STATUS_OK;
4318 /****************************************************************************
4319 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4320 ****************************************************************************/
4322 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4323 struct smb_request *req,
4327 struct smb_filename *smb_fname_src)
4331 char *newname = NULL;
4332 struct files_struct *dst_dirfsp = NULL;
4333 struct smb_filename *smb_fname_dst = NULL;
4334 const char *dst_original_lcomp = NULL;
4335 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4336 NTSTATUS status = NT_STATUS_OK;
4337 TALLOC_CTX *ctx = talloc_tos();
4340 return NT_STATUS_INVALID_HANDLE;
4343 if (total_data < 20) {
4344 return NT_STATUS_INVALID_PARAMETER;
4347 overwrite = (CVAL(pdata,0) ? True : False);
4348 len = IVAL(pdata,16);
4350 if (len > (total_data - 20) || (len == 0)) {
4351 return NT_STATUS_INVALID_PARAMETER;
4354 (void)srvstr_pull_talloc(ctx,
4362 if (newname == NULL) {
4363 return NT_STATUS_INVALID_PARAMETER;
4366 /* SMB2 rename paths are never DFS. */
4367 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4368 ucf_flags &= ~UCF_DFS_PATHNAME;
4370 status = check_path_syntax(newname,
4371 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4372 if (!NT_STATUS_IS_OK(status)) {
4376 DBG_DEBUG("got name |%s|\n", newname);
4378 if (newname[0] == ':') {
4379 /* Create an smb_fname to call rename_internals_fsp() with. */
4380 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4381 fsp->base_fsp->fsp_name->base_name,
4384 fsp->base_fsp->fsp_name->twrp,
4385 fsp->base_fsp->fsp_name->flags);
4386 if (smb_fname_dst == NULL) {
4387 status = NT_STATUS_NO_MEMORY;
4391 status = filename_convert_dirfsp(ctx,
4395 0, /* Never a TWRP. */
4398 if (!NT_STATUS_IS_OK(status)) {
4404 * Set the original last component, since
4405 * rename_internals_fsp() requires it.
4407 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4411 if (dst_original_lcomp == NULL) {
4412 status = NT_STATUS_NO_MEMORY;
4416 DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4419 smb_fname_str_dbg(smb_fname_dst));
4421 status = rename_internals_fsp(conn,
4425 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4429 TALLOC_FREE(smb_fname_dst);
4433 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4434 struct smb_request *req,
4438 struct smb_filename *smb_fname_src)
4442 char *newname = NULL;
4443 struct files_struct *dst_dirfsp = NULL;
4444 struct smb_filename *smb_fname_dst = NULL;
4445 NTSTATUS status = NT_STATUS_OK;
4446 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4448 TALLOC_CTX *ctx = talloc_tos();
4451 return NT_STATUS_INVALID_HANDLE;
4454 if (total_data < 20) {
4455 return NT_STATUS_INVALID_PARAMETER;
4458 overwrite = (CVAL(pdata,0) ? true : false);
4459 len = IVAL(pdata,16);
4461 if (len > (total_data - 20) || (len == 0)) {
4462 return NT_STATUS_INVALID_PARAMETER;
4465 ret = srvstr_pull_talloc(ctx,
4473 if (ret == (size_t)-1 || newname == NULL) {
4474 return NT_STATUS_INVALID_PARAMETER;
4477 /* SMB2 hardlink paths are never DFS. */
4478 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4479 ucf_flags &= ~UCF_DFS_PATHNAME;
4481 status = check_path_syntax(newname,
4482 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4483 if (!NT_STATUS_IS_OK(status)) {
4487 DBG_DEBUG("got name |%s|\n", newname);
4489 status = filename_convert_dirfsp(ctx,
4496 if (!NT_STATUS_IS_OK(status)) {
4500 if (fsp->base_fsp) {
4501 /* No stream names. */
4502 return NT_STATUS_NOT_SUPPORTED;
4505 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4506 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4507 smb_fname_str_dbg(smb_fname_dst));
4508 status = hardlink_internals(ctx,
4515 TALLOC_FREE(smb_fname_dst);
4519 static NTSTATUS smb_file_link_information(connection_struct *conn,
4520 struct smb_request *req,
4524 struct smb_filename *smb_fname_src)
4528 char *newname = NULL;
4529 struct files_struct *dst_dirfsp = NULL;
4530 struct smb_filename *smb_fname_dst = NULL;
4531 NTSTATUS status = NT_STATUS_OK;
4532 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4533 NTTIME dst_twrp = 0;
4534 TALLOC_CTX *ctx = talloc_tos();
4537 return NT_STATUS_INVALID_HANDLE;
4540 if (total_data < 20) {
4541 return NT_STATUS_INVALID_PARAMETER;
4544 overwrite = (CVAL(pdata,0) ? true : false);
4545 len = IVAL(pdata,16);
4547 if (len > (total_data - 20) || (len == 0)) {
4548 return NT_STATUS_INVALID_PARAMETER;
4551 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4552 srvstr_get_path_posix(ctx,
4560 ucf_flags |= UCF_POSIX_PATHNAMES;
4562 srvstr_get_path(ctx,
4571 if (!NT_STATUS_IS_OK(status)) {
4575 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4578 if (ucf_flags & UCF_GMT_PATHNAME) {
4579 extract_snapshot_token(newname, &dst_twrp);
4581 /* hardlink paths are never DFS. */
4582 ucf_flags &= ~UCF_DFS_PATHNAME;
4584 status = filename_convert_dirfsp(ctx,
4591 if (!NT_STATUS_IS_OK(status)) {
4595 if (fsp->base_fsp) {
4596 /* No stream names. */
4597 return NT_STATUS_NOT_SUPPORTED;
4600 DEBUG(10,("smb_file_link_information: "
4601 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4602 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4603 smb_fname_str_dbg(smb_fname_dst)));
4604 status = hardlink_internals(ctx,
4611 TALLOC_FREE(smb_fname_dst);
4616 /****************************************************************************
4617 Deal with SMB_FILE_RENAME_INFORMATION.
4618 ****************************************************************************/
4620 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4621 struct smb_request *req,
4625 struct smb_filename *smb_fname_src)
4630 char *newname = NULL;
4631 struct files_struct *dst_dirfsp = NULL;
4632 struct smb_filename *smb_fname_dst = NULL;
4633 const char *dst_original_lcomp = NULL;
4634 NTSTATUS status = NT_STATUS_OK;
4636 TALLOC_CTX *ctx = talloc_tos();
4638 if (total_data < 13) {
4639 return NT_STATUS_INVALID_PARAMETER;
4642 overwrite = (CVAL(pdata,0) != 0);
4643 root_fid = IVAL(pdata,4);
4644 len = IVAL(pdata,8);
4646 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4647 return NT_STATUS_INVALID_PARAMETER;
4650 if (req->posix_pathnames) {
4651 srvstr_get_path_posix(ctx,
4660 srvstr_get_path(ctx,
4669 if (!NT_STATUS_IS_OK(status)) {
4673 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4676 /* Check the new name has no '/' characters. */
4677 if (strchr_m(newname, '/')) {
4678 return NT_STATUS_NOT_SUPPORTED;
4681 if (fsp && fsp->base_fsp) {
4682 /* newname must be a stream name. */
4683 if (newname[0] != ':') {
4684 return NT_STATUS_NOT_SUPPORTED;
4687 /* Create an smb_fname to call rename_internals_fsp() with. */
4688 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4689 fsp->base_fsp->fsp_name->base_name,
4692 fsp->base_fsp->fsp_name->twrp,
4693 fsp->base_fsp->fsp_name->flags);
4694 if (smb_fname_dst == NULL) {
4695 status = NT_STATUS_NO_MEMORY;
4700 * Get the original last component, since
4701 * rename_internals_fsp() requires it.
4703 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4707 if (dst_original_lcomp == NULL) {
4708 status = NT_STATUS_NO_MEMORY;
4714 * Build up an smb_fname_dst based on the filename passed in.
4715 * We basically just strip off the last component, and put on
4716 * the newname instead.
4718 char *base_name = NULL;
4719 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4720 NTTIME dst_twrp = 0;
4722 /* newname must *not* be a stream name. */
4723 if (newname[0] == ':') {
4724 return NT_STATUS_NOT_SUPPORTED;
4728 * Strip off the last component (filename) of the path passed
4731 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4733 return NT_STATUS_NO_MEMORY;
4735 p = strrchr_m(base_name, '/');
4739 base_name = talloc_strdup(ctx, "");
4741 return NT_STATUS_NO_MEMORY;
4744 /* Append the new name. */
4745 base_name = talloc_asprintf_append(base_name,
4749 return NT_STATUS_NO_MEMORY;
4752 if (ucf_flags & UCF_GMT_PATHNAME) {
4753 extract_snapshot_token(base_name, &dst_twrp);
4756 /* The newname is *not* a DFS path. */
4757 ucf_flags &= ~UCF_DFS_PATHNAME;
4759 status = filename_convert_dirfsp(ctx,
4767 if (!NT_STATUS_IS_OK(status)) {
4770 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4774 if (dst_original_lcomp == NULL) {
4775 status = NT_STATUS_NO_MEMORY;
4780 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4781 DEBUG(10,("smb_file_rename_information: "
4782 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4783 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4784 smb_fname_str_dbg(smb_fname_dst)));
4785 status = rename_internals_fsp(conn,
4792 DEBUG(10,("smb_file_rename_information: "
4793 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4794 smb_fname_str_dbg(smb_fname_src),
4795 smb_fname_str_dbg(smb_fname_dst)));
4796 status = rename_internals(ctx,
4799 NULL, /* src_dirfsp */
4805 FILE_WRITE_ATTRIBUTES);
4808 TALLOC_FREE(smb_fname_dst);
4812 /****************************************************************************
4813 Deal with SMB_SET_FILE_BASIC_INFO.
4814 ****************************************************************************/
4816 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4820 struct smb_filename *smb_fname)
4822 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4823 struct smb_file_time ft;
4824 uint32_t dosmode = 0;
4825 NTSTATUS status = NT_STATUS_OK;
4827 init_smb_file_time(&ft);
4829 if (total_data < 36) {
4830 return NT_STATUS_INVALID_PARAMETER;
4834 return NT_STATUS_INVALID_HANDLE;
4837 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4838 if (!NT_STATUS_IS_OK(status)) {
4842 /* Set the attributes */
4843 dosmode = IVAL(pdata,32);
4844 status = smb_set_file_dosmode(conn, fsp, dosmode);
4845 if (!NT_STATUS_IS_OK(status)) {
4850 ft.create_time = pull_long_date_full_timespec(pdata);
4853 ft.atime = pull_long_date_full_timespec(pdata+8);
4856 ft.mtime = pull_long_date_full_timespec(pdata+16);
4859 ft.ctime = pull_long_date_full_timespec(pdata+24);
4861 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4862 smb_fname_str_dbg(smb_fname)));
4864 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4865 if (!NT_STATUS_IS_OK(status)) {
4869 if (fsp->fsp_flags.modified) {
4870 trigger_write_time_update_immediate(fsp);
4872 return NT_STATUS_OK;
4875 /****************************************************************************
4876 Deal with SMB_INFO_STANDARD.
4877 ****************************************************************************/
4879 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4883 struct smb_filename *smb_fname)
4886 struct smb_file_time ft;
4888 init_smb_file_time(&ft);
4890 if (total_data < 12) {
4891 return NT_STATUS_INVALID_PARAMETER;
4895 return NT_STATUS_INVALID_HANDLE;
4899 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4901 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4903 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4905 DEBUG(10,("smb_set_info_standard: file %s\n",
4906 smb_fname_str_dbg(smb_fname)));
4908 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4909 if (!NT_STATUS_IS_OK(status)) {
4913 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4914 if (!NT_STATUS_IS_OK(status)) {
4918 if (fsp->fsp_flags.modified) {
4919 trigger_write_time_update_immediate(fsp);
4921 return NT_STATUS_OK;
4924 /****************************************************************************
4925 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4926 ****************************************************************************/
4928 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4929 struct smb_request *req,
4933 struct smb_filename *smb_fname)
4935 uint64_t allocation_size = 0;
4936 NTSTATUS status = NT_STATUS_OK;
4937 files_struct *new_fsp = NULL;
4939 if (!VALID_STAT(smb_fname->st)) {
4940 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4943 if (total_data < 8) {
4944 return NT_STATUS_INVALID_PARAMETER;
4947 allocation_size = (uint64_t)IVAL(pdata,0);
4948 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4949 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4950 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4951 (double)allocation_size));
4953 if (allocation_size) {
4954 allocation_size = smb_roundup(conn, allocation_size);
4957 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4958 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4959 (double)allocation_size));
4962 !fsp->fsp_flags.is_pathref &&
4963 fsp_get_io_fd(fsp) != -1)
4965 /* Open file handle. */
4966 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4967 if (!NT_STATUS_IS_OK(status)) {
4971 /* Only change if needed. */
4972 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4973 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4974 return map_nt_error_from_unix(errno);
4977 /* But always update the time. */
4979 * This is equivalent to a write. Ensure it's seen immediately
4980 * if there are no pending writes.
4982 trigger_write_time_update_immediate(fsp);
4983 return NT_STATUS_OK;
4986 /* Pathname or stat or directory file. */
4987 status = SMB_VFS_CREATE_FILE(
4991 smb_fname, /* fname */
4992 FILE_WRITE_DATA, /* access_mask */
4993 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4995 FILE_OPEN, /* create_disposition*/
4996 0, /* create_options */
4997 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4998 0, /* oplock_request */
5000 0, /* allocation_size */
5001 0, /* private_flags */
5004 &new_fsp, /* result */
5006 NULL, NULL); /* create context */
5008 if (!NT_STATUS_IS_OK(status)) {
5009 /* NB. We check for open_was_deferred in the caller. */
5013 /* Only change if needed. */
5014 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5015 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5016 status = map_nt_error_from_unix(errno);
5017 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5022 /* Changing the allocation size should set the last mod time. */
5024 * This is equivalent to a write. Ensure it's seen immediately
5025 * if there are no pending writes.
5027 trigger_write_time_update_immediate(new_fsp);
5028 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5029 return NT_STATUS_OK;
5032 /****************************************************************************
5033 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5034 ****************************************************************************/
5036 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5037 struct smb_request *req,
5041 struct smb_filename *smb_fname,
5042 bool fail_after_createfile)
5046 if (total_data < 8) {
5047 return NT_STATUS_INVALID_PARAMETER;
5050 size = IVAL(pdata,0);
5051 size |= (((off_t)IVAL(pdata,4)) << 32);
5052 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5053 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5056 return smb_set_file_size(conn, req,
5061 fail_after_createfile);
5064 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5065 struct smb_request *req,
5066 TALLOC_CTX *mem_ctx,
5067 uint16_t info_level,
5069 struct smb_filename *smb_fname,
5070 char **ppdata, int total_data,
5073 char *pdata = *ppdata;
5074 NTSTATUS status = NT_STATUS_OK;
5075 int data_return_size = 0;
5079 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5080 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5082 info_level, total_data));
5084 switch (info_level) {
5086 case SMB_INFO_STANDARD:
5088 status = smb_set_info_standard(conn,
5096 case SMB_INFO_SET_EA:
5098 status = smb_info_set_ea(conn,
5106 case SMB_SET_FILE_BASIC_INFO:
5107 case SMB_FILE_BASIC_INFORMATION:
5109 status = smb_set_file_basic_info(conn,
5117 case SMB_FILE_ALLOCATION_INFORMATION:
5118 case SMB_SET_FILE_ALLOCATION_INFO:
5120 status = smb_set_file_allocation_info(conn, req,
5128 case SMB_FILE_END_OF_FILE_INFORMATION:
5129 case SMB_SET_FILE_END_OF_FILE_INFO:
5132 * XP/Win7 both fail after the createfile with
5133 * SMB_SET_FILE_END_OF_FILE_INFO but not
5134 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5135 * The level is known here, so pass it down
5139 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5141 status = smb_set_file_end_of_file_info(conn, req,
5150 case SMB_FILE_DISPOSITION_INFORMATION:
5151 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5154 /* JRA - We used to just ignore this on a path ?
5155 * Shouldn't this be invalid level on a pathname
5158 if (tran_call != TRANSACT2_SETFILEINFO) {
5159 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5162 status = smb_set_file_disposition_info(conn,
5170 case SMB_FILE_POSITION_INFORMATION:
5172 status = smb_file_position_information(conn,
5179 case SMB_FILE_FULL_EA_INFORMATION:
5181 status = smb_set_file_full_ea_info(conn,
5188 /* From tridge Samba4 :
5189 * MODE_INFORMATION in setfileinfo (I have no
5190 * idea what "mode information" on a file is - it takes a value of 0,
5191 * 2, 4 or 6. What could it be?).
5194 case SMB_FILE_MODE_INFORMATION:
5196 status = smb_file_mode_information(conn,
5202 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5203 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5204 case SMB_FILE_SHORT_NAME_INFORMATION:
5205 return NT_STATUS_NOT_SUPPORTED;
5207 case SMB_FILE_RENAME_INFORMATION:
5209 status = smb_file_rename_information(conn, req,
5215 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5217 /* SMB2 rename information. */
5218 status = smb2_file_rename_information(conn, req,
5224 case SMB_FILE_LINK_INFORMATION:
5226 if (conn_using_smb2(conn->sconn)) {
5227 status = smb2_file_link_information(conn,
5234 status = smb_file_link_information(conn,
5245 return NT_STATUS_INVALID_LEVEL;
5248 if (!NT_STATUS_IS_OK(status)) {
5252 *ret_data_size = data_return_size;
5253 return NT_STATUS_OK;
5256 static uint32_t generate_volume_serial_number(
5257 const struct loadparm_substitution *lp_sub,
5260 int serial = lp_volume_serial_number(snum);
5261 return serial != -1 ? serial:
5262 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5263 (str_checksum(get_local_machine_name())<<16);