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 bool refuse_symlink_fsp(const files_struct
*fsp
)
66 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
69 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
72 if (fsp_get_pathref_fd(fsp
) == -1) {
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 refuse
= refuse_symlink_fsp(fsp
);
204 return NT_STATUS_ACCESS_DENIED
;
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
) || 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;
716 if (!lp_ea_support(SNUM(conn
))) {
717 return NT_STATUS_EAS_NOT_SUPPORTED
;
721 return NT_STATUS_INVALID_HANDLE
;
724 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
726 refuse
= refuse_symlink_fsp(fsp
);
728 return NT_STATUS_ACCESS_DENIED
;
731 status
= check_any_access_fsp(fsp
, FILE_WRITE_EA
);
732 if (!NT_STATUS_IS_OK(status
)) {
736 /* Setting EAs on streams isn't supported. */
737 if (fsp_is_alternate_stream(fsp
)) {
738 return NT_STATUS_INVALID_PARAMETER
;
742 * Filter out invalid Windows EA names - before
743 * we set *any* of them.
746 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
747 return STATUS_INVALID_EA_NAME
;
750 for (;ea_list
; ea_list
= ea_list
->next
) {
752 fstring unix_ea_name
;
755 * Complementing the forward mapping from POSIX EAs to
756 * Windows EAs in get_ea_list_from_fsp(), here we map in the
757 * opposite direction from Windows EAs to the 'user' namespace
758 * of POSIX EAs. Hence, all POSIX EA names the we set here must
759 * start with a 'user.' prefix.
761 fstrcpy(unix_ea_name
, "user.");
762 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
764 canonicalize_ea_name(fsp
, unix_ea_name
);
766 DBG_DEBUG("ea_name %s ealen = %zu\n",
768 ea_list
->ea
.value
.length
);
770 if (samba_private_attr_name(unix_ea_name
)) {
771 DBG_DEBUG("ea name %s is a private Samba name.\n",
773 return NT_STATUS_ACCESS_DENIED
;
776 if (ea_list
->ea
.value
.length
== 0) {
777 /* Remove the attribute. */
778 DBG_DEBUG("deleting ea name %s on "
779 "file %s by file descriptor.\n",
780 unix_ea_name
, fsp_str_dbg(fsp
));
781 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
783 /* Removing a non existent attribute always succeeds. */
784 if (ret
== -1 && errno
== ENOATTR
) {
785 DBG_DEBUG("deleting ea name %s didn't exist - "
786 "succeeding by default.\n",
792 DBG_DEBUG("setting ea name %s on file "
793 "%s by file descriptor.\n",
796 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
797 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
802 if (errno
== ENOTSUP
) {
803 return NT_STATUS_EAS_NOT_SUPPORTED
;
806 return map_nt_error_from_unix(errno
);
813 /****************************************************************************
814 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
815 ****************************************************************************/
817 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
819 struct ea_list
*ea_list_head
= NULL
;
821 size_t bytes_used
= 0;
823 while (offset
< data_size
) {
824 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
830 DLIST_ADD_END(ea_list_head
, eal
);
831 offset
+= bytes_used
;
837 /****************************************************************************
838 Count the total EA size needed.
839 ****************************************************************************/
841 static size_t ea_list_size(struct ea_list
*ealist
)
844 struct ea_list
*listp
;
847 for (listp
= ealist
; listp
; listp
= listp
->next
) {
848 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
849 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
851 /* Add on 4 for total length. */
859 /****************************************************************************
860 Return a union of EA's from a file list and a list of names.
861 The TALLOC context for the two lists *MUST* be identical as we steal
862 memory from one list to add to another. JRA.
863 ****************************************************************************/
865 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
867 struct ea_list
*nlistp
, *flistp
;
869 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
870 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
871 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
877 /* Copy the data from this entry. */
878 nlistp
->ea
.flags
= flistp
->ea
.flags
;
879 nlistp
->ea
.value
= flistp
->ea
.value
;
882 nlistp
->ea
.flags
= 0;
883 ZERO_STRUCT(nlistp
->ea
.value
);
887 *total_ea_len
= ea_list_size(name_list
);
891 /****************************************************************************
892 Map wire perms onto standard UNIX permissions. Obey share restrictions.
893 ****************************************************************************/
895 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
896 const SMB_STRUCT_STAT
*psbuf
,
902 if (perms
== SMB_MODE_NO_CHANGE
) {
903 if (!VALID_STAT(*psbuf
)) {
904 return NT_STATUS_INVALID_PARAMETER
;
906 *ret_perms
= psbuf
->st_ex_mode
;
910 ret
= wire_perms_to_unix(perms
);
916 /****************************************************************************
917 Get a level dependent lanman2 dir entry.
918 ****************************************************************************/
920 struct smbd_dirptr_lanman2_state
{
921 connection_struct
*conn
;
923 bool check_mangled_names
;
927 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
933 struct smbd_dirptr_lanman2_state
*state
=
934 (struct smbd_dirptr_lanman2_state
*)private_data
;
936 char mangled_name
[13]; /* mangled 8.3 name. */
940 /* Mangle fname if it's an illegal name. */
941 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
943 * Slow path - ensure we can push the original name as UCS2. If
944 * not, then just don't return this name.
948 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
949 uint8_t *tmp
= talloc_array(talloc_tos(),
953 status
= srvstr_push(NULL
,
954 FLAGS2_UNICODE_STRINGS
,
963 if (!NT_STATUS_IS_OK(status
)) {
967 ok
= name_to_8_3(dname
, mangled_name
,
968 true, state
->conn
->params
);
972 fname
= mangled_name
;
977 got_match
= mask_match(fname
, mask
,
978 state
->case_sensitive
);
980 if(!got_match
&& state
->check_mangled_names
&&
981 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
983 * It turns out that NT matches wildcards against
984 * both long *and* short names. This may explain some
985 * of the wildcard weirdness from old DOS clients
986 * that some people have been seeing.... JRA.
988 /* Force the mangling into 8.3. */
989 ok
= name_to_8_3(fname
, mangled_name
,
990 false, state
->conn
->params
);
995 got_match
= mask_match(mangled_name
, mask
,
996 state
->case_sensitive
);
1003 *_fname
= talloc_strdup(ctx
, fname
);
1004 if (*_fname
== NULL
) {
1011 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1013 uint32_t ea_size
= IO_REPARSE_TAG_DFS
;
1015 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1016 (void)fsctl_get_reparse_tag(fsp
, &ea_size
);
1018 ea_size
= estimate_ea_size(fsp
);
1024 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1025 connection_struct
*conn
,
1027 uint32_t info_level
,
1028 struct ea_list
*name_list
,
1029 bool check_mangled_names
,
1030 bool requires_resume_key
,
1033 const struct smb_filename
*smb_fname
,
1034 int space_remaining
,
1040 uint64_t *last_entry_off
)
1042 char *p
, *q
, *pdata
= *ppdata
;
1044 uint64_t file_size
= 0;
1045 uint64_t allocation_size
= 0;
1046 uint64_t file_id
= 0;
1048 struct timespec mdate_ts
= {0};
1049 struct timespec adate_ts
= {0};
1050 struct timespec cdate_ts
= {0};
1051 struct timespec create_date_ts
= {0};
1053 char *last_entry_ptr
;
1058 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1061 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1062 file_size
= get_file_size_stat(&smb_fname
->st
);
1064 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1067 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1070 if (smb_fname
->fsp
!= NULL
&&
1071 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1072 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1074 &readdir_attr_data
);
1075 if (!NT_STATUS_IS_OK(status
)) {
1076 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1083 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1085 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1086 adate_ts
= smb_fname
->st
.st_ex_atime
;
1087 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1088 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1090 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1091 dos_filetime_timespec(&create_date_ts
);
1092 dos_filetime_timespec(&mdate_ts
);
1093 dos_filetime_timespec(&adate_ts
);
1094 dos_filetime_timespec(&cdate_ts
);
1097 /* align the record */
1098 SMB_ASSERT(align
>= 1);
1100 off
= (int)PTR_DIFF(pdata
, base_data
);
1101 pad
= (off
+ (align
-1)) & ~(align
-1);
1104 if (pad
&& pad
> space_remaining
) {
1105 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1106 "for padding (wanted %u, had %d)\n",
1109 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1113 /* initialize padding to 0 */
1115 memset(pdata
, 0, pad
);
1117 space_remaining
-= pad
;
1119 DBG_DEBUG("space_remaining = %d\n", space_remaining
);
1128 switch (info_level
) {
1129 case SMB_FIND_INFO_STANDARD
:
1130 DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1131 if(requires_resume_key
) {
1135 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1136 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1137 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1138 SIVAL(p
,12,(uint32_t)file_size
);
1139 SIVAL(p
,16,(uint32_t)allocation_size
);
1143 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1144 p
+= ucs2_align(base_data
, p
, 0);
1146 status
= srvstr_push(base_data
, flags2
, p
,
1147 fname
, PTR_DIFF(end_data
, p
),
1148 STR_TERMINATE
, &len
);
1149 if (!NT_STATUS_IS_OK(status
)) {
1152 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1154 SCVAL(nameptr
, -1, len
- 2);
1156 SCVAL(nameptr
, -1, 0);
1160 SCVAL(nameptr
, -1, len
- 1);
1162 SCVAL(nameptr
, -1, 0);
1168 case SMB_FIND_EA_SIZE
:
1169 DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1170 if (requires_resume_key
) {
1174 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1175 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1176 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1177 SIVAL(p
,12,(uint32_t)file_size
);
1178 SIVAL(p
,16,(uint32_t)allocation_size
);
1181 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1182 SIVAL(p
,22,ea_size
); /* Extended attributes */
1186 status
= srvstr_push(base_data
, flags2
,
1187 p
, fname
, PTR_DIFF(end_data
, p
),
1188 STR_TERMINATE
| STR_NOALIGN
, &len
);
1189 if (!NT_STATUS_IS_OK(status
)) {
1192 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1205 SCVAL(nameptr
,0,len
);
1207 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1210 case SMB_FIND_EA_LIST
:
1212 struct ea_list
*file_list
= NULL
;
1215 DBG_DEBUG("SMB_FIND_EA_LIST\n");
1217 return NT_STATUS_INVALID_PARAMETER
;
1219 if (requires_resume_key
) {
1223 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1224 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1225 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1226 SIVAL(p
,12,(uint32_t)file_size
);
1227 SIVAL(p
,16,(uint32_t)allocation_size
);
1229 p
+= 22; /* p now points to the EA area. */
1231 status
= get_ea_list_from_fsp(ctx
,
1233 &ea_len
, &file_list
);
1234 if (!NT_STATUS_IS_OK(status
)) {
1237 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1239 /* We need to determine if this entry will fit in the space available. */
1240 /* Max string size is 255 bytes. */
1241 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1242 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1243 "(wanted %u, had %d)\n",
1244 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1246 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1249 /* Push the ea_data followed by the name. */
1250 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1252 status
= srvstr_push(base_data
, flags2
,
1253 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1254 STR_TERMINATE
| STR_NOALIGN
, &len
);
1255 if (!NT_STATUS_IS_OK(status
)) {
1258 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1271 SCVAL(nameptr
,0,len
);
1273 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1277 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1278 DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1279 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1281 SIVAL(p
,0,reskey
); p
+= 4;
1282 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1283 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1284 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1285 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1286 SOFF_T(p
,0,file_size
); p
+= 8;
1287 SOFF_T(p
,0,allocation_size
); p
+= 8;
1288 SIVAL(p
,0,mode
); p
+= 4;
1289 q
= p
; p
+= 4; /* q is placeholder for name length. */
1290 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1291 SIVAL(p
, 0, ea_size
);
1293 /* Clear the short name buffer. This is
1294 * IMPORTANT as not doing so will trigger
1295 * a Win2k client bug. JRA.
1297 if (!was_8_3
&& check_mangled_names
) {
1298 char mangled_name
[13]; /* mangled 8.3 name. */
1299 if (!name_to_8_3(fname
,mangled_name
,True
,
1301 /* Error - mangle failed ! */
1302 memset(mangled_name
,'\0',12);
1304 mangled_name
[12] = 0;
1305 status
= srvstr_push(base_data
, flags2
,
1306 p
+2, mangled_name
, 24,
1307 STR_UPPER
|STR_UNICODE
, &len
);
1308 if (!NT_STATUS_IS_OK(status
)) {
1312 memset(p
+ 2 + len
,'\0',24 - len
);
1319 status
= srvstr_push(base_data
, flags2
, p
,
1320 fname
, PTR_DIFF(end_data
, p
),
1321 STR_TERMINATE_ASCII
, &len
);
1322 if (!NT_STATUS_IS_OK(status
)) {
1328 len
= PTR_DIFF(p
, pdata
);
1329 pad
= (len
+ (align
-1)) & ~(align
-1);
1331 * offset to the next entry, the caller
1332 * will overwrite it for the last entry
1333 * that's why we always include the padding
1337 * set padding to zero
1340 memset(p
, 0, pad
- len
);
1347 case SMB_FIND_FILE_DIRECTORY_INFO
:
1348 DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1350 SIVAL(p
,0,reskey
); p
+= 4;
1351 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1352 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1353 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1354 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1355 SOFF_T(p
,0,file_size
); p
+= 8;
1356 SOFF_T(p
,0,allocation_size
); p
+= 8;
1357 SIVAL(p
,0,mode
); p
+= 4;
1358 status
= srvstr_push(base_data
, flags2
,
1359 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1360 STR_TERMINATE_ASCII
, &len
);
1361 if (!NT_STATUS_IS_OK(status
)) {
1367 len
= PTR_DIFF(p
, pdata
);
1368 pad
= (len
+ (align
-1)) & ~(align
-1);
1370 * offset to the next entry, the caller
1371 * will overwrite it for the last entry
1372 * that's why we always include the padding
1376 * set padding to zero
1379 memset(p
, 0, pad
- len
);
1386 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1387 DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1389 SIVAL(p
,0,reskey
); p
+= 4;
1390 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1391 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1392 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1393 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1394 SOFF_T(p
,0,file_size
); p
+= 8;
1395 SOFF_T(p
,0,allocation_size
); p
+= 8;
1396 SIVAL(p
,0,mode
); p
+= 4;
1397 q
= p
; p
+= 4; /* q is placeholder for name length. */
1398 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1399 SIVAL(p
, 0, ea_size
);
1401 status
= srvstr_push(base_data
, flags2
, p
,
1402 fname
, PTR_DIFF(end_data
, p
),
1403 STR_TERMINATE_ASCII
, &len
);
1404 if (!NT_STATUS_IS_OK(status
)) {
1410 len
= PTR_DIFF(p
, pdata
);
1411 pad
= (len
+ (align
-1)) & ~(align
-1);
1413 * offset to the next entry, the caller
1414 * will overwrite it for the last entry
1415 * that's why we always include the padding
1419 * set padding to zero
1422 memset(p
, 0, pad
- len
);
1429 case SMB_FIND_FILE_NAMES_INFO
:
1430 DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1432 SIVAL(p
,0,reskey
); p
+= 4;
1434 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1435 acl on a dir (tridge) */
1436 status
= srvstr_push(base_data
, flags2
, p
,
1437 fname
, PTR_DIFF(end_data
, p
),
1438 STR_TERMINATE_ASCII
, &len
);
1439 if (!NT_STATUS_IS_OK(status
)) {
1445 len
= PTR_DIFF(p
, pdata
);
1446 pad
= (len
+ (align
-1)) & ~(align
-1);
1448 * offset to the next entry, the caller
1449 * will overwrite it for the last entry
1450 * that's why we always include the padding
1454 * set padding to zero
1457 memset(p
, 0, pad
- len
);
1464 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1465 DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1467 SIVAL(p
,0,reskey
); p
+= 4;
1468 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1469 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1470 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1471 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1472 SOFF_T(p
,0,file_size
); p
+= 8;
1473 SOFF_T(p
,0,allocation_size
); p
+= 8;
1474 SIVAL(p
,0,mode
); p
+= 4;
1475 q
= p
; p
+= 4; /* q is placeholder for name length. */
1476 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1477 SIVAL(p
, 0, ea_size
);
1479 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1480 SBVAL(p
,0,file_id
); p
+= 8;
1481 status
= srvstr_push(base_data
, flags2
, p
,
1482 fname
, PTR_DIFF(end_data
, p
),
1483 STR_TERMINATE_ASCII
, &len
);
1484 if (!NT_STATUS_IS_OK(status
)) {
1490 len
= PTR_DIFF(p
, pdata
);
1491 pad
= (len
+ (align
-1)) & ~(align
-1);
1493 * offset to the next entry, the caller
1494 * will overwrite it for the last entry
1495 * that's why we always include the padding
1499 * set padding to zero
1502 memset(p
, 0, pad
- len
);
1509 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1510 DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1511 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1513 SIVAL(p
,0,reskey
); p
+= 4;
1514 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1515 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1516 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1517 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1518 SOFF_T(p
,0,file_size
); p
+= 8;
1519 SOFF_T(p
,0,allocation_size
); p
+= 8;
1520 SIVAL(p
,0,mode
); p
+= 4;
1521 q
= p
; p
+= 4; /* q is placeholder for name length */
1522 if (readdir_attr_data
&&
1523 readdir_attr_data
->type
== RDATTR_AAPL
) {
1525 * OS X specific SMB2 extension negotiated via
1526 * AAPL create context: return max_access in
1529 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1531 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1533 SIVAL(p
,0,ea_size
); /* Extended attributes */
1536 if (readdir_attr_data
&&
1537 readdir_attr_data
->type
== RDATTR_AAPL
) {
1539 * OS X specific SMB2 extension negotiated via
1540 * AAPL create context: return resource fork
1541 * length and compressed FinderInfo in
1544 * According to documentation short_name_len
1545 * should be 0, but on the wire behaviour
1546 * shows its set to 24 by clients.
1550 /* Resourefork length */
1551 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1553 /* Compressed FinderInfo */
1554 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1555 } else if (!was_8_3
&& check_mangled_names
) {
1556 char mangled_name
[13]; /* mangled 8.3 name. */
1557 if (!name_to_8_3(fname
,mangled_name
,True
,
1559 /* Error - mangle failed ! */
1560 memset(mangled_name
,'\0',12);
1562 mangled_name
[12] = 0;
1563 status
= srvstr_push(base_data
, flags2
,
1564 p
+2, mangled_name
, 24,
1565 STR_UPPER
|STR_UNICODE
, &len
);
1566 if (!NT_STATUS_IS_OK(status
)) {
1571 memset(p
+ 2 + len
,'\0',24 - len
);
1575 /* Clear the short name buffer. This is
1576 * IMPORTANT as not doing so will trigger
1577 * a Win2k client bug. JRA.
1584 if (readdir_attr_data
&&
1585 readdir_attr_data
->type
== RDATTR_AAPL
) {
1587 * OS X specific SMB2 extension negotiated via
1588 * AAPL create context: return UNIX mode in
1591 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1592 SSVAL(p
, 0, aapl_mode
);
1598 SBVAL(p
,0,file_id
); p
+= 8;
1599 status
= srvstr_push(base_data
, flags2
, p
,
1600 fname
, PTR_DIFF(end_data
, p
),
1601 STR_TERMINATE_ASCII
, &len
);
1602 if (!NT_STATUS_IS_OK(status
)) {
1608 len
= PTR_DIFF(p
, pdata
);
1609 pad
= (len
+ (align
-1)) & ~(align
-1);
1611 * offset to the next entry, the caller
1612 * will overwrite it for the last entry
1613 * that's why we always include the padding
1617 * set padding to zero
1620 memset(p
, 0, pad
- len
);
1627 /* CIFS UNIX Extension. */
1629 case SMB_FIND_FILE_UNIX
:
1630 case SMB_FIND_FILE_UNIX_INFO2
:
1632 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1634 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1636 if (info_level
== SMB_FIND_FILE_UNIX
) {
1637 DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1638 p
= store_file_unix_basic(conn
, p
,
1639 NULL
, &smb_fname
->st
);
1640 status
= srvstr_push(base_data
, flags2
, p
,
1641 fname
, PTR_DIFF(end_data
, p
),
1642 STR_TERMINATE
, &len
);
1643 if (!NT_STATUS_IS_OK(status
)) {
1647 DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1648 p
= store_file_unix_basic_info2(conn
, p
,
1649 NULL
, &smb_fname
->st
);
1652 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1653 PTR_DIFF(end_data
, p
), 0, &len
);
1654 if (!NT_STATUS_IS_OK(status
)) {
1657 SIVAL(nameptr
, 0, len
);
1662 len
= PTR_DIFF(p
, pdata
);
1663 pad
= (len
+ (align
-1)) & ~(align
-1);
1665 * offset to the next entry, the caller
1666 * will overwrite it for the last entry
1667 * that's why we always include the padding
1671 * set padding to zero
1674 memset(p
, 0, pad
- len
);
1679 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1683 /* SMB2 UNIX Extension. */
1685 case SMB2_FILE_POSIX_INFORMATION
:
1687 struct smb3_file_posix_information info
= {};
1688 uint8_t buf
[sizeof(info
)];
1689 struct ndr_push ndr
= {
1691 .alloc_size
= sizeof(buf
),
1692 .fixed_buf_size
= true,
1694 enum ndr_err_code ndr_err
;
1697 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1700 SIVAL(p
,0,reskey
); p
+= 4;
1702 if (!conn_using_smb2(conn
->sconn
)) {
1703 return NT_STATUS_INVALID_LEVEL
;
1706 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1707 status
= fsctl_get_reparse_tag(smb_fname
->fsp
,
1709 if (!NT_STATUS_IS_OK(status
)) {
1710 DBG_DEBUG("Could not get reparse "
1712 smb_fname_str_dbg(smb_fname
),
1718 smb3_file_posix_information_init(
1719 conn
, &smb_fname
->st
, tag
, mode
, &info
);
1721 ndr_err
= ndr_push_smb3_file_posix_information(
1722 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
1723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1724 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1727 memcpy(p
, buf
, ndr
.offset
);
1732 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1733 PTR_DIFF(end_data
, p
), 0, &len
);
1734 if (!NT_STATUS_IS_OK(status
)) {
1737 SIVAL(nameptr
, 0, len
);
1741 len
= PTR_DIFF(p
, pdata
);
1742 pad
= (len
+ (align
-1)) & ~(align
-1);
1744 * offset to the next entry, the caller
1745 * will overwrite it for the last entry
1746 * that's why we always include the padding
1753 return NT_STATUS_INVALID_LEVEL
;
1756 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1757 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1758 "(wanted %u, had %d)\n",
1759 (unsigned int)PTR_DIFF(p
,pdata
),
1761 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1764 /* Setup the last entry pointer, as an offset from base_data */
1765 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1766 /* Advance the data pointer to the next slot */
1769 return NT_STATUS_OK
;
1772 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1773 connection_struct
*conn
,
1774 struct dptr_struct
*dirptr
,
1776 const char *path_mask
,
1779 int requires_resume_key
,
1788 int space_remaining
,
1789 struct smb_filename
**_smb_fname
,
1790 int *_last_entry_off
,
1791 struct ea_list
*name_list
,
1792 struct file_id
*file_id
)
1795 const char *mask
= NULL
;
1798 struct smb_filename
*smb_fname
= NULL
;
1799 struct smbd_dirptr_lanman2_state state
;
1801 uint64_t last_entry_off
= 0;
1803 enum mangled_names_options mangled_names
;
1804 bool marshall_with_83_names
;
1806 mangled_names
= lp_mangled_names(conn
->params
);
1810 state
.info_level
= info_level
;
1811 if (mangled_names
!= MANGLED_NAMES_NO
) {
1812 state
.check_mangled_names
= true;
1814 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1816 p
= strrchr_m(path_mask
,'/');
1827 ok
= smbd_dirptr_get_entry(ctx
,
1834 smbd_dirptr_lanman2_match_fn
,
1840 return NT_STATUS_END_OF_FILE
;
1843 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1845 status
= smbd_marshall_dir_entry(ctx
,
1850 marshall_with_83_names
,
1851 requires_resume_key
,
1862 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1863 DEBUG(1,("Conversion error: illegal character: %s\n",
1864 smb_fname_str_dbg(smb_fname
)));
1867 if (file_id
!= NULL
) {
1868 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1871 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1872 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1875 if (!NT_STATUS_IS_OK(status
)) {
1876 TALLOC_FREE(smb_fname
);
1881 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1883 if (_smb_fname
!= NULL
) {
1885 * smb_fname is already talloc'ed off ctx.
1886 * We just need to make sure we don't return
1887 * any stream_name, and replace base_name
1888 * with fname in case base_name got mangled.
1889 * This allows us to preserve any smb_fname->fsp
1890 * for asynchronous handle lookups.
1892 TALLOC_FREE(smb_fname
->stream_name
);
1895 * smbd_dirptr_set_last_name_sent() above consumed
1898 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1900 if (smb_fname
->base_name
== NULL
) {
1901 TALLOC_FREE(smb_fname
);
1903 return NT_STATUS_NO_MEMORY
;
1905 *_smb_fname
= smb_fname
;
1907 TALLOC_FREE(smb_fname
);
1911 *_last_entry_off
= last_entry_off
;
1912 return NT_STATUS_OK
;
1915 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1917 const struct loadparm_substitution
*lp_sub
=
1918 loadparm_s3_global_substitution();
1920 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1924 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1926 SMB_ASSERT(extended_info
!= NULL
);
1928 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1929 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1930 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1931 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1932 #ifdef SAMBA_VERSION_REVISION
1933 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1935 extended_info
->samba_subversion
= 0;
1936 #ifdef SAMBA_VERSION_RC_RELEASE
1937 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1939 #ifdef SAMBA_VERSION_PRE_RELEASE
1940 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
1943 #ifdef SAMBA_VERSION_VENDOR_PATCH
1944 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
1946 extended_info
->samba_gitcommitdate
= 0;
1947 #ifdef SAMBA_VERSION_COMMIT_TIME
1948 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
1951 memset(extended_info
->samba_version_string
, 0,
1952 sizeof(extended_info
->samba_version_string
));
1954 snprintf (extended_info
->samba_version_string
,
1955 sizeof(extended_info
->samba_version_string
),
1956 "%s", samba_version_string());
1959 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
1960 struct files_struct
*fsp
,
1961 uint16_t info_level
)
1963 if (conn_using_smb2(conn
->sconn
) &&
1964 fsp
->fsp_flags
.posix_open
&&
1965 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
)
1969 #if defined(SMB1SERVER)
1970 if (lp_smb1_unix_extensions() &&
1971 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
1979 * fsp is only valid for SMB2.
1981 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
1982 connection_struct
*conn
,
1983 TALLOC_CTX
*mem_ctx
,
1984 uint16_t info_level
,
1986 unsigned int max_data_bytes
,
1987 size_t *fixed_portion
,
1988 struct files_struct
*fsp
,
1989 struct smb_filename
*fname
,
1993 const struct loadparm_substitution
*lp_sub
=
1994 loadparm_s3_global_substitution();
1995 char *pdata
, *end_data
;
1998 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
1999 int snum
= SNUM(conn
);
2000 const char *fstype
= lp_fstype(SNUM(conn
));
2001 const char *filename
= NULL
;
2002 uint64_t bytes_per_sector
= 512;
2003 struct smb_filename smb_fname
;
2005 NTSTATUS status
= NT_STATUS_OK
;
2009 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2012 filename
= fname
->base_name
;
2016 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2017 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2018 "info level (0x%x) on IPC$.\n",
2019 (unsigned int)info_level
));
2020 return NT_STATUS_ACCESS_DENIED
;
2024 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2026 smb_fname
= (struct smb_filename
) {
2027 .base_name
= discard_const_p(char, filename
),
2028 .flags
= fname
? fname
->flags
: 0,
2029 .twrp
= fname
? fname
->twrp
: 0,
2032 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2033 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2034 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2035 return map_nt_error_from_unix(errno
);
2040 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2041 return NT_STATUS_INVALID_PARAMETER
;
2044 *ppdata
= (char *)SMB_REALLOC(
2045 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2046 if (*ppdata
== NULL
) {
2047 return NT_STATUS_NO_MEMORY
;
2051 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2052 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2056 switch (info_level
) {
2057 case SMB_INFO_ALLOCATION
:
2059 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2061 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2063 if (df_ret
== (uint64_t)-1) {
2064 return map_nt_error_from_unix(errno
);
2067 block_size
= lp_block_size(snum
);
2068 if (bsize
< block_size
) {
2069 uint64_t factor
= block_size
/bsize
;
2074 if (bsize
> block_size
) {
2075 uint64_t factor
= bsize
/block_size
;
2080 sectors_per_unit
= bsize
/bytes_per_sector
;
2082 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2083 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2084 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2087 * For large drives, return max values and not modulo.
2089 dsize
= MIN(dsize
, UINT32_MAX
);
2090 dfree
= MIN(dfree
, UINT32_MAX
);
2092 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2093 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2094 SIVAL(pdata
,l1_cUnit
,dsize
);
2095 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2096 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2100 case SMB_INFO_VOLUME
:
2101 /* Return volume name */
2103 * Add volume serial number - hash of a combination of
2104 * the called hostname and the service name.
2106 serial
= generate_volume_serial_number(lp_sub
, snum
);
2107 SIVAL(pdata
,0,serial
);
2109 * Win2k3 and previous mess this up by sending a name length
2110 * one byte short. I believe only older clients (OS/2 Win9x) use
2111 * this call so try fixing this by adding a terminating null to
2112 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2114 status
= srvstr_push(
2116 pdata
+l2_vol_szVolLabel
, vname
,
2117 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2118 STR_NOALIGN
|STR_TERMINATE
, &len
);
2119 if (!NT_STATUS_IS_OK(status
)) {
2122 SCVAL(pdata
,l2_vol_cch
,len
);
2123 data_len
= l2_vol_szVolLabel
+ len
;
2124 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2125 "name = %s serial = 0x%04"PRIx32
"\n",
2126 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2127 (unsigned)len
, vname
, serial
));
2130 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2131 case SMB_FS_ATTRIBUTE_INFORMATION
:
2133 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2134 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2135 conn
->fs_capabilities
); /* FS ATTRIBUTES */
2137 SIVAL(pdata
,4,255); /* Max filename component length */
2138 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2139 and will think we can't do long filenames */
2140 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2141 PTR_DIFF(end_data
, pdata
+12),
2143 if (!NT_STATUS_IS_OK(status
)) {
2147 data_len
= 12 + len
;
2148 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2149 /* the client only requested a portion of the
2151 data_len
= max_data_bytes
;
2152 status
= STATUS_BUFFER_OVERFLOW
;
2154 *fixed_portion
= 16;
2157 case SMB_QUERY_FS_LABEL_INFO
:
2158 case SMB_FS_LABEL_INFORMATION
:
2159 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2160 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2161 if (!NT_STATUS_IS_OK(status
)) {
2168 case SMB_QUERY_FS_VOLUME_INFO
:
2169 case SMB_FS_VOLUME_INFORMATION
:
2170 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2171 pdata
, &st
.st_ex_btime
);
2173 * Add volume serial number - hash of a combination of
2174 * the called hostname and the service name.
2176 serial
= generate_volume_serial_number(lp_sub
, snum
);
2177 SIVAL(pdata
,8,serial
);
2179 /* Max label len is 32 characters. */
2180 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2181 PTR_DIFF(end_data
, pdata
+18),
2183 if (!NT_STATUS_IS_OK(status
)) {
2186 SIVAL(pdata
,12,len
);
2189 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2190 "namelen = %d, vol=%s serv=%s "
2191 "serial=0x%04"PRIx32
"\n",
2192 (int)strlen(vname
),vname
,
2193 lp_servicename(talloc_tos(), lp_sub
, snum
),
2195 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2196 /* the client only requested a portion of the
2198 data_len
= max_data_bytes
;
2199 status
= STATUS_BUFFER_OVERFLOW
;
2201 *fixed_portion
= 24;
2204 case SMB_QUERY_FS_SIZE_INFO
:
2205 case SMB_FS_SIZE_INFORMATION
:
2207 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2209 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2211 if (df_ret
== (uint64_t)-1) {
2212 return map_nt_error_from_unix(errno
);
2214 block_size
= lp_block_size(snum
);
2215 if (bsize
< block_size
) {
2216 uint64_t factor
= block_size
/bsize
;
2221 if (bsize
> block_size
) {
2222 uint64_t factor
= bsize
/block_size
;
2227 sectors_per_unit
= bsize
/bytes_per_sector
;
2228 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2229 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2230 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2231 SBIG_UINT(pdata
,0,dsize
);
2232 SBIG_UINT(pdata
,8,dfree
);
2233 SIVAL(pdata
,16,sectors_per_unit
);
2234 SIVAL(pdata
,20,bytes_per_sector
);
2235 *fixed_portion
= 24;
2239 case SMB_FS_FULL_SIZE_INFORMATION
:
2241 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2243 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2245 if (df_ret
== (uint64_t)-1) {
2246 return map_nt_error_from_unix(errno
);
2248 block_size
= lp_block_size(snum
);
2249 if (bsize
< block_size
) {
2250 uint64_t factor
= block_size
/bsize
;
2255 if (bsize
> block_size
) {
2256 uint64_t factor
= bsize
/block_size
;
2261 sectors_per_unit
= bsize
/bytes_per_sector
;
2262 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2263 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2264 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2265 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2266 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2267 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2268 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2269 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2270 *fixed_portion
= 32;
2274 case SMB_QUERY_FS_DEVICE_INFO
:
2275 case SMB_FS_DEVICE_INFORMATION
:
2277 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2279 if (!CAN_WRITE(conn
)) {
2280 characteristics
|= FILE_READ_ONLY_DEVICE
;
2283 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2284 SIVAL(pdata
,4,characteristics
);
2289 #ifdef HAVE_SYS_QUOTAS
2290 case SMB_FS_QUOTA_INFORMATION
:
2292 * what we have to send --metze:
2294 * Unknown1: 24 NULL bytes
2295 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2296 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2297 * Quota Flags: 2 byte :
2298 * Unknown3: 6 NULL bytes
2302 * details for Quota Flags:
2304 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2305 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2306 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2307 * 0x0001 Enable Quotas: enable quota for this fs
2311 /* we need to fake up a fsp here,
2312 * because its not send in this call
2314 files_struct tmpfsp
= {
2316 .fnum
= FNUM_FIELD_INVALID
,
2318 SMB_NTQUOTA_STRUCT quotas
= {};
2321 if (get_current_uid(conn
) != 0) {
2322 DEBUG(0,("get_user_quota: access_denied "
2323 "service [%s] user [%s]\n",
2324 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2325 conn
->session_info
->unix_info
->unix_name
));
2326 return NT_STATUS_ACCESS_DENIED
;
2329 status
= vfs_get_ntquota(&tmpfsp
, SMB_USER_FS_QUOTA_TYPE
,
2331 if (!NT_STATUS_IS_OK(status
)) {
2332 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2338 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2339 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2341 /* Unknown1 24 NULL bytes*/
2342 SBIG_UINT(pdata
,0,(uint64_t)0);
2343 SBIG_UINT(pdata
,8,(uint64_t)0);
2344 SBIG_UINT(pdata
,16,(uint64_t)0);
2346 /* Default Soft Quota 8 bytes */
2347 SBIG_UINT(pdata
,24,quotas
.softlim
);
2349 /* Default Hard Quota 8 bytes */
2350 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2352 /* Quota flag 2 bytes */
2353 SSVAL(pdata
,40,quotas
.qflags
);
2355 /* Unknown3 6 NULL bytes */
2361 #endif /* HAVE_SYS_QUOTAS */
2362 case SMB_FS_OBJECTID_INFORMATION
:
2364 unsigned char objid
[16];
2365 struct smb_extended_info extended_info
;
2366 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2367 samba_extended_info_version (&extended_info
);
2368 SIVAL(pdata
,16,extended_info
.samba_magic
);
2369 SIVAL(pdata
,20,extended_info
.samba_version
);
2370 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2371 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2372 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2377 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2379 uint32_t bps_logical
= lp_parm_ulong(
2381 "fs", "logical bytes per sector",
2383 uint32_t bps_aligned
= lp_parm_ulong(
2385 "fs", "aligned bytes per sector",
2387 uint32_t bps_performance
= lp_parm_ulong(
2389 "fs", "performance bytes per sector",
2391 uint32_t bps_effective
= lp_parm_ulong(
2393 "fs", "effective aligned bytes per sector",
2398 * These values match a physical Windows Server 2012
2399 * share backed by NTFS atop spinning rust.
2401 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2402 /* logical_bytes_per_sector */
2403 SIVAL(pdata
, 0, bps_logical
);
2404 /* phys_bytes_per_sector_atomic */
2405 SIVAL(pdata
, 4, bps_aligned
);
2406 /* phys_bytes_per_sector_perf */
2407 SIVAL(pdata
, 8, bps_performance
);
2408 /* fs_effective_phys_bytes_per_sector_atomic */
2409 SIVAL(pdata
, 12, bps_effective
);
2411 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2412 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2413 /* byte_off_sector_align */
2414 SIVAL(pdata
, 20, 0);
2415 /* byte_off_partition_align */
2416 SIVAL(pdata
, 24, 0);
2417 *fixed_portion
= 28;
2422 #if defined(WITH_SMB1SERVER)
2424 * Query the version and capabilities of the CIFS UNIX extensions
2428 case SMB_QUERY_CIFS_UNIX_INFO
:
2430 bool large_write
= lp_min_receive_file_size() &&
2431 !smb1_srv_is_signing_active(xconn
);
2432 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2433 int encrypt_caps
= 0;
2435 if (!lp_smb1_unix_extensions()) {
2436 return NT_STATUS_INVALID_LEVEL
;
2439 switch (conn
->encrypt_level
) {
2440 case SMB_SIGNING_OFF
:
2443 case SMB_SIGNING_DESIRED
:
2444 case SMB_SIGNING_IF_REQUIRED
:
2445 case SMB_SIGNING_DEFAULT
:
2446 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2448 case SMB_SIGNING_REQUIRED
:
2449 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2450 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2451 large_write
= false;
2457 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2458 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2460 /* We have POSIX ACLs, pathname, encryption,
2461 * large read/write, and locking capability. */
2463 SBIG_UINT(pdata
,4,((uint64_t)(
2464 CIFS_UNIX_POSIX_ACLS_CAP
|
2465 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2466 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2467 CIFS_UNIX_EXTATTR_CAP
|
2468 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2470 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2472 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2477 case SMB_QUERY_POSIX_FS_INFO
:
2478 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2481 struct vfs_statvfs_struct svfs
;
2483 if (!fsinfo_unix_valid_level(conn
, fsp
, info_level
)) {
2484 return NT_STATUS_INVALID_LEVEL
;
2487 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2491 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2492 SIVAL(pdata
,4,svfs
.BlockSize
);
2493 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2494 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2495 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2496 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2497 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2498 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2499 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2501 } else if (rc
== EOPNOTSUPP
) {
2502 return NT_STATUS_INVALID_LEVEL
;
2503 #endif /* EOPNOTSUPP */
2505 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2506 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2511 case SMB_QUERY_POSIX_WHOAMI
:
2517 if (!lp_smb1_unix_extensions()) {
2518 return NT_STATUS_INVALID_LEVEL
;
2521 if (max_data_bytes
< 40) {
2522 return NT_STATUS_BUFFER_TOO_SMALL
;
2525 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2526 flags
|= SMB_WHOAMI_GUEST
;
2529 /* NOTE: 8 bytes for UID/GID, irrespective of native
2530 * platform size. This matches
2531 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2533 data_len
= 4 /* flags */
2540 + 4 /* pad/reserved */
2541 + (conn
->session_info
->unix_token
->ngroups
* 8)
2543 + (conn
->session_info
->security_token
->num_sids
*
2547 SIVAL(pdata
, 0, flags
);
2548 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2550 (uint64_t)conn
->session_info
->unix_token
->uid
);
2551 SBIG_UINT(pdata
, 16,
2552 (uint64_t)conn
->session_info
->unix_token
->gid
);
2555 if (data_len
>= max_data_bytes
) {
2556 /* Potential overflow, skip the GIDs and SIDs. */
2558 SIVAL(pdata
, 24, 0); /* num_groups */
2559 SIVAL(pdata
, 28, 0); /* num_sids */
2560 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2561 SIVAL(pdata
, 36, 0); /* reserved */
2567 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2568 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2570 /* We walk the SID list twice, but this call is fairly
2571 * infrequent, and I don't expect that it's performance
2572 * sensitive -- jpeach
2574 for (i
= 0, sid_bytes
= 0;
2575 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2576 sid_bytes
+= ndr_size_dom_sid(
2577 &conn
->session_info
->security_token
->sids
[i
],
2581 /* SID list byte count */
2582 SIVAL(pdata
, 32, sid_bytes
);
2584 /* 4 bytes pad/reserved - must be zero */
2585 SIVAL(pdata
, 36, 0);
2589 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2590 SBIG_UINT(pdata
, data_len
,
2591 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2597 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2598 int sid_len
= ndr_size_dom_sid(
2599 &conn
->session_info
->security_token
->sids
[i
],
2602 sid_linearize((uint8_t *)(pdata
+ data_len
),
2604 &conn
->session_info
->security_token
->sids
[i
]);
2605 data_len
+= sid_len
;
2611 case SMB_MAC_QUERY_FS_INFO
:
2613 * Thursby MAC extension... ONLY on NTFS filesystems
2614 * once we do streams then we don't need this
2616 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2618 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2624 return NT_STATUS_INVALID_LEVEL
;
2627 *ret_data_len
= data_len
;
2631 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2632 struct smb_request
*req
,
2634 const DATA_BLOB
*qdata
)
2636 const struct loadparm_substitution
*lp_sub
=
2637 loadparm_s3_global_substitution();
2639 SMB_NTQUOTA_STRUCT quotas
;
2641 ZERO_STRUCT(quotas
);
2644 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2645 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2646 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2647 conn
->session_info
->unix_info
->unix_name
);
2648 return NT_STATUS_ACCESS_DENIED
;
2651 if (!check_fsp_ntquota_handle(conn
, req
,
2653 DBG_WARNING("no valid QUOTA HANDLE\n");
2654 return NT_STATUS_INVALID_HANDLE
;
2657 /* note: normally there're 48 bytes,
2658 * but we didn't use the last 6 bytes for now
2661 if (qdata
->length
< 42) {
2662 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2664 return NT_STATUS_INVALID_PARAMETER
;
2667 /* unknown_1 24 NULL bytes in pdata*/
2669 /* the soft quotas 8 bytes (uint64_t)*/
2670 quotas
.softlim
= BVAL(qdata
->data
,24);
2672 /* the hard quotas 8 bytes (uint64_t)*/
2673 quotas
.hardlim
= BVAL(qdata
->data
,32);
2675 /* quota_flags 2 bytes **/
2676 quotas
.qflags
= SVAL(qdata
->data
,40);
2678 /* unknown_2 6 NULL bytes follow*/
2680 /* now set the quotas */
2681 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2682 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2683 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)));
2684 status
= map_nt_error_from_unix(errno
);
2686 status
= NT_STATUS_OK
;
2691 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2692 struct smb_request
*req
,
2693 TALLOC_CTX
*mem_ctx
,
2694 uint16_t info_level
,
2696 const DATA_BLOB
*pdata
)
2698 switch (info_level
) {
2699 case SMB_FS_QUOTA_INFORMATION
:
2701 return smb_set_fsquota(conn
,
2710 return NT_STATUS_INVALID_LEVEL
;
2713 /****************************************************************************
2714 Store the FILE_UNIX_BASIC info.
2715 ****************************************************************************/
2717 char *store_file_unix_basic(connection_struct
*conn
,
2720 const SMB_STRUCT_STAT
*psbuf
)
2724 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2725 DBG_NOTICE("st_mode=%o\n", (int)psbuf
->st_ex_mode
);
2727 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2730 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2733 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2734 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2735 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2738 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2742 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2746 SIVAL(pdata
, 0, unix_filetype_to_wire(psbuf
->st_ex_mode
));
2749 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2750 devno
= psbuf
->st_ex_rdev
;
2752 devno
= psbuf
->st_ex_dev
;
2755 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2759 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2763 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2766 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2770 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2777 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2778 * the chflags(2) (or equivalent) flags.
2780 * XXX: this really should be behind the VFS interface. To do this, we would
2781 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2782 * Each VFS module could then implement its own mapping as appropriate for the
2783 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2785 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2789 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2793 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2797 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2801 { UF_HIDDEN
, EXT_HIDDEN
},
2804 /* Do not remove. We need to guarantee that this array has at least one
2805 * entry to build on HP-UX.
2811 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2812 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2816 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2817 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2818 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2819 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2824 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2825 const uint32_t smb_fflags
,
2826 const uint32_t smb_fmask
,
2829 uint32_t max_fmask
= 0;
2832 *stat_fflags
= psbuf
->st_ex_flags
;
2834 /* For each flags requested in smb_fmask, check the state of the
2835 * corresponding flag in smb_fflags and set or clear the matching
2839 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2840 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2841 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2842 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2843 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2845 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2850 /* If smb_fmask is asking to set any bits that are not supported by
2851 * our flag mappings, we should fail.
2853 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2861 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2862 * of file flags and birth (create) time.
2864 char *store_file_unix_basic_info2(connection_struct
*conn
,
2867 const SMB_STRUCT_STAT
*psbuf
)
2869 uint32_t file_flags
= 0;
2870 uint32_t flags_mask
= 0;
2872 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2874 /* Create (birth) time 64 bit */
2875 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2878 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2879 SIVAL(pdata
, 0, file_flags
); /* flags */
2880 SIVAL(pdata
, 4, flags_mask
); /* mask */
2886 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2887 const struct stream_struct
*streams
,
2889 unsigned int max_data_bytes
,
2890 unsigned int *data_size
)
2893 unsigned int ofs
= 0;
2895 if (max_data_bytes
< 32) {
2896 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2899 for (i
= 0; i
< num_streams
; i
++) {
2900 unsigned int next_offset
;
2902 smb_ucs2_t
*namebuf
;
2904 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2905 streams
[i
].name
, &namelen
) ||
2908 return NT_STATUS_INVALID_PARAMETER
;
2912 * name_buf is now null-terminated, we need to marshall as not
2919 * We cannot overflow ...
2921 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2922 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2924 TALLOC_FREE(namebuf
);
2925 return STATUS_BUFFER_OVERFLOW
;
2928 SIVAL(data
, ofs
+4, namelen
);
2929 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2930 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2931 memcpy(data
+ofs
+24, namebuf
, namelen
);
2932 TALLOC_FREE(namebuf
);
2934 next_offset
= ofs
+ 24 + namelen
;
2936 if (i
== num_streams
-1) {
2937 SIVAL(data
, ofs
, 0);
2940 unsigned int align
= ndr_align_size(next_offset
, 8);
2942 if ((next_offset
+ align
) > max_data_bytes
) {
2943 DEBUG(10, ("refusing to overflow align "
2944 "reply at stream %u\n",
2946 TALLOC_FREE(namebuf
);
2947 return STATUS_BUFFER_OVERFLOW
;
2950 memset(data
+next_offset
, 0, align
);
2951 next_offset
+= align
;
2953 SIVAL(data
, ofs
, next_offset
- ofs
);
2960 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
2964 return NT_STATUS_OK
;
2967 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
2968 TALLOC_CTX
*mem_ctx
,
2969 struct smb_request
*req
,
2970 uint16_t info_level
,
2972 struct smb_filename
*smb_fname
,
2973 bool delete_pending
,
2974 struct timespec write_time_ts
,
2975 struct ea_list
*ea_list
,
2977 unsigned int max_data_bytes
,
2978 size_t *fixed_portion
,
2980 unsigned int *pdata_size
)
2982 char *pdata
= *ppdata
;
2983 char *dstart
, *dend
;
2984 unsigned int data_size
;
2985 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
2986 SMB_STRUCT_STAT
*psbuf
= NULL
;
2987 SMB_STRUCT_STAT
*base_sp
= NULL
;
2994 uint64_t file_size
= 0;
2996 uint64_t allocation_size
= 0;
2997 uint64_t file_id
= 0;
2998 uint32_t access_mask
= 0;
3001 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3004 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3005 DBG_DEBUG("SMB1 unix extensions activated\n");
3009 if (conn_using_smb2(conn
->sconn
) &&
3010 fsp
->fsp_flags
.posix_open
)
3012 DBG_DEBUG("SMB2 posix open\n");
3017 return NT_STATUS_INVALID_LEVEL
;
3021 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3022 smb_fname_str_dbg(smb_fname
),
3024 info_level
, max_data_bytes
);
3027 * In case of querying a symlink in POSIX context,
3028 * fsp will be NULL. fdos_mode() deals with it.
3031 smb_fname
= fsp
->fsp_name
;
3033 mode
= fdos_mode(fsp
);
3034 psbuf
= &smb_fname
->st
;
3037 base_sp
= fsp
->base_fsp
?
3038 &fsp
->base_fsp
->fsp_name
->st
:
3041 base_sp
= &smb_fname
->st
;
3044 nlink
= psbuf
->st_ex_nlink
;
3046 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3050 if ((nlink
> 0) && delete_pending
) {
3054 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3055 return NT_STATUS_INVALID_PARAMETER
;
3058 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3059 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3060 if (*ppdata
== NULL
) {
3061 return NT_STATUS_NO_MEMORY
;
3065 dend
= dstart
+ data_size
- 1;
3067 if (!is_omit_timespec(&write_time_ts
) &&
3068 !INFO_LEVEL_IS_UNIX(info_level
))
3070 update_stat_ex_mtime(psbuf
, write_time_ts
);
3073 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3074 mtime_ts
= psbuf
->st_ex_mtime
;
3075 atime_ts
= psbuf
->st_ex_atime
;
3076 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3078 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3079 dos_filetime_timespec(&create_time_ts
);
3080 dos_filetime_timespec(&mtime_ts
);
3081 dos_filetime_timespec(&atime_ts
);
3082 dos_filetime_timespec(&ctime_ts
);
3085 p
= strrchr_m(smb_fname
->base_name
,'/');
3087 base_name
= smb_fname
->base_name
;
3092 /* NT expects the name to be in an exact form of the *full*
3093 filename. See the trans2 torture test */
3094 if (ISDOT(base_name
)) {
3095 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3097 return NT_STATUS_NO_MEMORY
;
3100 dos_fname
= talloc_asprintf(mem_ctx
,
3102 smb_fname
->base_name
);
3104 return NT_STATUS_NO_MEMORY
;
3106 if (is_named_stream(smb_fname
)) {
3107 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3108 smb_fname
->stream_name
);
3110 return NT_STATUS_NO_MEMORY
;
3114 string_replace(dos_fname
, '/', '\\');
3117 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3119 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3120 /* Do we have this path open ? */
3121 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3122 files_struct
*fsp1
= file_find_di_first(
3123 conn
->sconn
, fileid
, true);
3124 if (fsp1
&& fsp1
->initial_allocation_size
) {
3125 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3129 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3130 file_size
= get_file_size_stat(psbuf
);
3134 pos
= fh_get_position_information(fsp
->fh
);
3138 access_mask
= fsp
->access_mask
;
3140 /* GENERIC_EXECUTE mapping from Windows */
3141 access_mask
= 0x12019F;
3144 /* This should be an index number - looks like
3147 I think this causes us to fail the IFSKIT
3148 BasicFileInformationTest. -tpot */
3149 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3153 switch (info_level
) {
3154 case SMB_INFO_STANDARD
:
3155 DBG_DEBUG("SMB_INFO_STANDARD\n");
3157 srv_put_dos_date2_ts(pdata
,
3160 srv_put_dos_date2_ts(pdata
,
3163 srv_put_dos_date2_ts(pdata
,
3165 mtime_ts
); /* write time */
3166 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3167 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3168 SSVAL(pdata
,l1_attrFile
,mode
);
3171 case SMB_INFO_QUERY_EA_SIZE
:
3173 unsigned int ea_size
=
3174 estimate_ea_size(smb_fname
->fsp
);
3175 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3177 srv_put_dos_date2_ts(pdata
, 0, create_time_ts
);
3178 srv_put_dos_date2_ts(pdata
, 4, atime_ts
);
3179 srv_put_dos_date2_ts(pdata
,
3181 mtime_ts
); /* write time */
3182 SIVAL(pdata
,12,(uint32_t)file_size
);
3183 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3184 SSVAL(pdata
,20,mode
);
3185 SIVAL(pdata
,22,ea_size
);
3189 case SMB_INFO_IS_NAME_VALID
:
3190 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3192 /* os/2 needs this ? really ?*/
3193 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3195 /* This is only reached for qpathinfo */
3199 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3201 size_t total_ea_len
= 0;
3202 struct ea_list
*ea_file_list
= NULL
;
3203 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3206 get_ea_list_from_fsp(mem_ctx
,
3208 &total_ea_len
, &ea_file_list
);
3209 if (!NT_STATUS_IS_OK(status
)) {
3213 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3215 if (!ea_list
|| (total_ea_len
> data_size
)) {
3217 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3221 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3225 case SMB_INFO_QUERY_ALL_EAS
:
3227 /* We have data_size bytes to put EA's into. */
3228 size_t total_ea_len
= 0;
3229 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3231 status
= get_ea_list_from_fsp(mem_ctx
,
3233 &total_ea_len
, &ea_list
);
3234 if (!NT_STATUS_IS_OK(status
)) {
3238 if (!ea_list
|| (total_ea_len
> data_size
)) {
3240 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3244 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3248 case SMB2_FILE_FULL_EA_INFORMATION
:
3250 /* We have data_size bytes to put EA's into. */
3251 size_t total_ea_len
= 0;
3252 struct ea_list
*ea_file_list
= NULL
;
3254 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3256 /*TODO: add filtering and index handling */
3259 get_ea_list_from_fsp(mem_ctx
,
3261 &total_ea_len
, &ea_file_list
);
3262 if (!NT_STATUS_IS_OK(status
)) {
3265 if (!ea_file_list
) {
3266 return NT_STATUS_NO_EAS_ON_FILE
;
3269 status
= fill_ea_chained_buffer(mem_ctx
,
3273 conn
, ea_file_list
);
3274 if (!NT_STATUS_IS_OK(status
)) {
3280 case SMB_FILE_BASIC_INFORMATION
:
3281 case SMB_QUERY_FILE_BASIC_INFO
:
3283 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3284 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3285 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3287 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3291 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3292 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3293 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3294 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3295 SIVAL(pdata
,32,mode
);
3297 DBG_INFO("SMB_QFBI - create: %s access: %s "
3298 "write: %s change: %s mode: %x\n",
3299 ctime(&create_time_ts
.tv_sec
),
3300 ctime(&atime_ts
.tv_sec
),
3301 ctime(&mtime_ts
.tv_sec
),
3302 ctime(&ctime_ts
.tv_sec
),
3304 *fixed_portion
= data_size
;
3307 case SMB_FILE_STANDARD_INFORMATION
:
3308 case SMB_QUERY_FILE_STANDARD_INFO
:
3310 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3312 SOFF_T(pdata
,0,allocation_size
);
3313 SOFF_T(pdata
,8,file_size
);
3314 SIVAL(pdata
,16,nlink
);
3315 SCVAL(pdata
,20,delete_pending
?1:0);
3316 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3317 SSVAL(pdata
,22,0); /* Padding. */
3318 *fixed_portion
= 24;
3321 case SMB_FILE_EA_INFORMATION
:
3322 case SMB_QUERY_FILE_EA_INFO
:
3324 unsigned int ea_size
=
3325 estimate_ea_size(smb_fname
->fsp
);
3326 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3329 SIVAL(pdata
,0,ea_size
);
3333 /* Get the 8.3 name - used if NT SMB was negotiated. */
3334 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3335 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3337 char mangled_name
[13];
3338 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3339 if (!name_to_8_3(base_name
,mangled_name
,
3340 True
,conn
->params
)) {
3341 return NT_STATUS_NO_MEMORY
;
3343 status
= srvstr_push(dstart
, flags2
,
3344 pdata
+4, mangled_name
,
3345 PTR_DIFF(dend
, pdata
+4),
3347 if (!NT_STATUS_IS_OK(status
)) {
3350 data_size
= 4 + len
;
3356 case SMB_QUERY_FILE_NAME_INFO
:
3359 this must be *exactly* right for ACLs on mapped drives to work
3361 status
= srvstr_push(dstart
, flags2
,
3363 PTR_DIFF(dend
, pdata
+4),
3365 if (!NT_STATUS_IS_OK(status
)) {
3368 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3369 data_size
= 4 + len
;
3374 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3376 char *nfname
= NULL
;
3379 !conn_using_smb2(fsp
->conn
->sconn
)) {
3380 return NT_STATUS_INVALID_LEVEL
;
3383 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3384 if (nfname
== NULL
) {
3385 return NT_STATUS_NO_MEMORY
;
3388 if (ISDOT(nfname
)) {
3391 string_replace(nfname
, '/', '\\');
3393 if (fsp_is_alternate_stream(fsp
)) {
3394 const char *s
= smb_fname
->stream_name
;
3395 const char *e
= NULL
;
3398 SMB_ASSERT(s
[0] != '\0');
3401 * smb_fname->stream_name is in form
3402 * of ':StrEam:$DATA', but we should only
3403 * append ':StrEam' here.
3406 e
= strchr(&s
[1], ':');
3412 nfname
= talloc_strndup_append(nfname
, s
, n
);
3413 if (nfname
== NULL
) {
3414 return NT_STATUS_NO_MEMORY
;
3418 status
= srvstr_push(dstart
, flags2
,
3420 PTR_DIFF(dend
, pdata
+4),
3422 if (!NT_STATUS_IS_OK(status
)) {
3425 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3426 data_size
= 4 + len
;
3432 case SMB_FILE_ALLOCATION_INFORMATION
:
3433 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3434 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3436 SOFF_T(pdata
,0,allocation_size
);
3439 case SMB_FILE_END_OF_FILE_INFORMATION
:
3440 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3441 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3443 SOFF_T(pdata
,0,file_size
);
3446 case SMB_QUERY_FILE_ALL_INFO
:
3447 case SMB_FILE_ALL_INFORMATION
:
3449 unsigned int ea_size
=
3450 estimate_ea_size(smb_fname
->fsp
);
3451 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3452 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3453 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3454 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3455 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3456 SIVAL(pdata
,32,mode
);
3457 SIVAL(pdata
,36,0); /* padding. */
3459 SOFF_T(pdata
,0,allocation_size
);
3460 SOFF_T(pdata
,8,file_size
);
3461 SIVAL(pdata
,16,nlink
);
3462 SCVAL(pdata
,20,delete_pending
);
3463 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3466 SIVAL(pdata
,0,ea_size
);
3467 pdata
+= 4; /* EA info */
3468 status
= srvstr_push(dstart
, flags2
,
3470 PTR_DIFF(dend
, pdata
+4),
3472 if (!NT_STATUS_IS_OK(status
)) {
3477 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3478 *fixed_portion
= 10;
3482 case SMB2_FILE_ALL_INFORMATION
:
3484 unsigned int ea_size
=
3485 estimate_ea_size(smb_fname
->fsp
);
3486 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3487 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3488 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3489 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3490 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3491 SIVAL(pdata
, 0x20, mode
);
3492 SIVAL(pdata
, 0x24, 0); /* padding. */
3493 SBVAL(pdata
, 0x28, allocation_size
);
3494 SBVAL(pdata
, 0x30, file_size
);
3495 SIVAL(pdata
, 0x38, nlink
);
3496 SCVAL(pdata
, 0x3C, delete_pending
);
3497 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3498 SSVAL(pdata
, 0x3E, 0); /* padding */
3499 SBVAL(pdata
, 0x40, file_id
);
3500 SIVAL(pdata
, 0x48, ea_size
);
3501 SIVAL(pdata
, 0x4C, access_mask
);
3502 SBVAL(pdata
, 0x50, pos
);
3503 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3504 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3508 status
= srvstr_push(dstart
, flags2
,
3510 PTR_DIFF(dend
, pdata
+4),
3512 if (!NT_STATUS_IS_OK(status
)) {
3517 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3518 *fixed_portion
= 104;
3521 case SMB_FILE_INTERNAL_INFORMATION
:
3523 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3524 SBVAL(pdata
, 0, file_id
);
3529 case SMB_FILE_ACCESS_INFORMATION
:
3530 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3531 SIVAL(pdata
, 0, access_mask
);
3536 case SMB_FILE_NAME_INFORMATION
:
3537 /* Pathname with leading '\'. */
3540 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3541 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3542 SIVAL(pdata
,0,byte_len
);
3543 data_size
= 4 + byte_len
;
3547 case SMB_FILE_DISPOSITION_INFORMATION
:
3548 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3550 SCVAL(pdata
,0,delete_pending
);
3554 case SMB_FILE_POSITION_INFORMATION
:
3555 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3557 SOFF_T(pdata
,0,pos
);
3561 case SMB_FILE_MODE_INFORMATION
:
3562 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3563 SIVAL(pdata
,0,mode
);
3568 case SMB_FILE_ALIGNMENT_INFORMATION
:
3569 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3570 SIVAL(pdata
,0,0); /* No alignment needed. */
3576 * NT4 server just returns "invalid query" to this - if we try
3577 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3580 /* The first statement above is false - verified using Thursby
3581 * client against NT4 -- gcolley.
3583 case SMB_QUERY_FILE_STREAM_INFO
:
3584 case SMB_FILE_STREAM_INFORMATION
: {
3585 unsigned int num_streams
= 0;
3586 struct stream_struct
*streams
= NULL
;
3588 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3590 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3591 return NT_STATUS_INVALID_PARAMETER
;
3594 status
= vfs_fstreaminfo(fsp
,
3599 if (!NT_STATUS_IS_OK(status
)) {
3600 DBG_DEBUG("could not get stream info: %s\n",
3605 status
= marshall_stream_info(num_streams
, streams
,
3606 pdata
, max_data_bytes
,
3609 if (!NT_STATUS_IS_OK(status
)) {
3610 DBG_DEBUG("marshall_stream_info failed: %s\n",
3612 TALLOC_FREE(streams
);
3616 TALLOC_FREE(streams
);
3618 *fixed_portion
= 32;
3622 case SMB_QUERY_COMPRESSION_INFO
:
3623 case SMB_FILE_COMPRESSION_INFORMATION
:
3624 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3625 SOFF_T(pdata
,0,file_size
);
3626 SIVAL(pdata
,8,0); /* ??? */
3627 SIVAL(pdata
,12,0); /* ??? */
3629 *fixed_portion
= 16;
3632 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3633 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3634 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3635 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3636 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3637 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3638 SOFF_T(pdata
,32,allocation_size
);
3639 SOFF_T(pdata
,40,file_size
);
3640 SIVAL(pdata
,48,mode
);
3641 SIVAL(pdata
,52,0); /* ??? */
3643 *fixed_portion
= 56;
3646 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
: {
3649 DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3651 (void)fsctl_get_reparse_tag(fsp
, &tag
);
3653 DBG_DEBUG("tag=%"PRIu32
"\n", tag
);
3655 SIVAL(pdata
, 0, mode
);
3656 SIVAL(pdata
, 4, tag
);
3662 * SMB2 UNIX Extensions.
3664 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3666 struct smb3_file_posix_information info
= {};
3667 uint8_t buf
[sizeof(info
)];
3668 struct ndr_push ndr
= {
3670 .alloc_size
= sizeof(buf
),
3671 .fixed_buf_size
= true,
3673 enum ndr_err_code ndr_err
;
3675 if (!conn_using_smb2(conn
->sconn
)) {
3676 return NT_STATUS_INVALID_LEVEL
;
3679 return NT_STATUS_INVALID_HANDLE
;
3681 if (!fsp
->fsp_flags
.posix_open
) {
3682 return NT_STATUS_INVALID_LEVEL
;
3685 smb3_file_posix_information_init(
3686 conn
, &smb_fname
->st
, 0, mode
, &info
);
3688 ndr_err
= ndr_push_smb3_file_posix_information(
3689 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
3690 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3691 return NT_STATUS_INSUFFICIENT_RESOURCES
;
3694 memcpy(pdata
, buf
, ndr
.offset
);
3695 data_size
= ndr
.offset
;
3700 return NT_STATUS_INVALID_LEVEL
;
3703 *pdata_size
= data_size
;
3704 return NT_STATUS_OK
;
3707 /****************************************************************************
3708 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3710 ****************************************************************************/
3712 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3713 connection_struct
*conn
,
3714 struct smb_request
*req
,
3715 bool overwrite_if_exists
,
3716 const struct smb_filename
*smb_fname_old
,
3717 struct smb_filename
*smb_fname_new
)
3719 NTSTATUS status
= NT_STATUS_OK
;
3722 struct smb_filename
*parent_fname_old
= NULL
;
3723 struct smb_filename
*base_name_old
= NULL
;
3724 struct smb_filename
*parent_fname_new
= NULL
;
3725 struct smb_filename
*base_name_new
= NULL
;
3727 /* source must already exist. */
3728 if (!VALID_STAT(smb_fname_old
->st
)) {
3729 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3733 /* No links from a directory. */
3734 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3735 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3739 /* Setting a hardlink to/from a stream isn't currently supported. */
3740 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3742 DBG_DEBUG("Old name has streams\n");
3743 status
= NT_STATUS_INVALID_PARAMETER
;
3746 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3748 DBG_DEBUG("New name has streams\n");
3749 status
= NT_STATUS_INVALID_PARAMETER
;
3753 if (smb_fname_old
->twrp
!= 0) {
3754 status
= NT_STATUS_NOT_SAME_DEVICE
;
3758 status
= parent_pathref(talloc_tos(),
3763 if (!NT_STATUS_IS_OK(status
)) {
3767 status
= parent_pathref(talloc_tos(),
3772 if (!NT_STATUS_IS_OK(status
)) {
3776 if (VALID_STAT(smb_fname_new
->st
)) {
3777 if (overwrite_if_exists
) {
3778 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3779 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3782 status
= unlink_internals(conn
,
3784 FILE_ATTRIBUTE_NORMAL
,
3785 NULL
, /* new_dirfsp */
3787 if (!NT_STATUS_IS_OK(status
)) {
3791 /* Disallow if newname already exists. */
3792 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3797 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3798 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3800 ret
= SMB_VFS_LINKAT(conn
,
3801 parent_fname_old
->fsp
,
3803 parent_fname_new
->fsp
,
3808 status
= map_nt_error_from_unix(errno
);
3809 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3810 nt_errstr(status
), smb_fname_old
->base_name
,
3811 smb_fname_new
->base_name
));
3816 NOTIFY_ACTION_ADDED
|
3817 NOTIFY_ACTION_DIRLEASE_BREAK
,
3818 FILE_NOTIFY_CHANGE_FILE_NAME
,
3820 fsp_get_smb2_lease(smb_fname_old
->fsp
));
3824 TALLOC_FREE(parent_fname_old
);
3825 TALLOC_FREE(parent_fname_new
);
3829 /****************************************************************************
3830 Deal with setting the time from any of the setfilepathinfo functions.
3831 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3832 calling this function.
3833 ****************************************************************************/
3835 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3837 struct smb_filename
*smb_fname
,
3838 struct smb_file_time
*ft
,
3839 bool setting_write_time
)
3841 const struct smb2_lease
*lease
= NULL
;
3842 struct files_struct
*set_fsp
= NULL
;
3843 struct timeval_buf tbuf
[4];
3844 uint32_t action
= NOTIFY_ACTION_MODIFIED
;
3846 FILE_NOTIFY_CHANGE_LAST_ACCESS
3847 |FILE_NOTIFY_CHANGE_LAST_WRITE
3848 |FILE_NOTIFY_CHANGE_CREATION
;
3851 if (!VALID_STAT(smb_fname
->st
)) {
3852 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3857 return NT_STATUS_OK
;
3860 set_fsp
= metadata_fsp(fsp
);
3862 /* get some defaults (no modifications) if any info is zero or -1. */
3863 if (is_omit_timespec(&ft
->create_time
)) {
3864 filter
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3867 if (is_omit_timespec(&ft
->atime
)) {
3868 filter
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3871 if (is_omit_timespec(&ft
->mtime
)) {
3872 filter
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3875 if (!setting_write_time
) {
3876 /* ft->mtime comes from change time, not write time. */
3877 filter
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3880 /* Ensure the resolution is the correct for
3881 * what we can store on this filesystem. */
3883 round_timespec(conn
->ts_res
, &ft
->create_time
);
3884 round_timespec(conn
->ts_res
, &ft
->ctime
);
3885 round_timespec(conn
->ts_res
, &ft
->atime
);
3886 round_timespec(conn
->ts_res
, &ft
->mtime
);
3888 DBG_DEBUG("actime: %s\n ",
3889 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3890 DBG_DEBUG("modtime: %s\n ",
3891 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3892 DBG_DEBUG("ctime: %s\n ",
3893 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3894 DBG_DEBUG("createtime: %s\n ",
3895 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3897 if (setting_write_time
) {
3899 * This was a Windows setfileinfo on an open file.
3900 * NT does this a lot. We also need to
3901 * set the time here, as it can be read by
3902 * FindFirst/FindNext and with the patch for bug #2045
3903 * in smbd/fileio.c it ensures that this timestamp is
3904 * kept sticky even after a write. We save the request
3905 * away and will set it on file close and after a write. JRA.
3908 DBG_DEBUG("setting pending modtime to %s\n",
3909 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3911 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3912 action
|= NOTIFY_ACTION_DIRLEASE_BREAK
;
3913 lease
= fsp_get_smb2_lease(fsp
);
3916 DBG_DEBUG("setting utimes to modified values.\n");
3918 ret
= file_ntimes(conn
, set_fsp
, ft
);
3920 return map_nt_error_from_unix(errno
);
3928 return NT_STATUS_OK
;
3931 /****************************************************************************
3932 Deal with setting the dosmode from any of the setfilepathinfo functions.
3933 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3934 done before calling this function.
3935 ****************************************************************************/
3937 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3938 struct files_struct
*fsp
,
3941 struct files_struct
*dos_fsp
= NULL
;
3942 uint32_t current_dosmode
;
3945 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3946 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3949 dos_fsp
= metadata_fsp(fsp
);
3952 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3953 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
3955 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
3959 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
3961 /* check the mode isn't different, before changing it */
3963 return NT_STATUS_OK
;
3965 current_dosmode
= fdos_mode(dos_fsp
);
3966 if (dosmode
== current_dosmode
) {
3967 return NT_STATUS_OK
;
3970 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
3971 fsp_str_dbg(dos_fsp
), dosmode
);
3973 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
3975 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3976 fsp_str_dbg(dos_fsp
), strerror(errno
));
3977 return map_nt_error_from_unix(errno
);
3980 return NT_STATUS_OK
;
3983 /****************************************************************************
3984 Deal with setting the size from any of the setfilepathinfo functions.
3985 ****************************************************************************/
3987 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
3988 struct smb_request
*req
,
3990 struct smb_filename
*smb_fname
,
3991 const SMB_STRUCT_STAT
*psbuf
,
3993 bool fail_after_createfile
)
3995 NTSTATUS status
= NT_STATUS_OK
;
3996 files_struct
*new_fsp
= NULL
;
3998 if (!VALID_STAT(*psbuf
)) {
3999 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4002 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4004 get_file_size_stat(psbuf
));
4006 if (size
== get_file_size_stat(psbuf
)) {
4008 return NT_STATUS_OK
;
4010 if (!fsp
->fsp_flags
.modified
) {
4011 return NT_STATUS_OK
;
4013 trigger_write_time_update_immediate(fsp
);
4014 return NT_STATUS_OK
;
4017 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4018 smb_fname_str_dbg(smb_fname
), (double)size
));
4021 !fsp
->fsp_flags
.is_pathref
&&
4022 fsp_get_io_fd(fsp
) != -1)
4024 /* Handle based call. */
4025 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4026 if (!NT_STATUS_IS_OK(status
)) {
4030 if (vfs_set_filelen(fsp
, size
) == -1) {
4031 return map_nt_error_from_unix(errno
);
4033 trigger_write_time_update_immediate(fsp
);
4034 return NT_STATUS_OK
;
4037 status
= SMB_VFS_CREATE_FILE(
4041 smb_fname
, /* fname */
4042 FILE_WRITE_DATA
, /* access_mask */
4043 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4045 FILE_OPEN
, /* create_disposition*/
4046 0, /* create_options */
4047 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4048 0, /* oplock_request */
4050 0, /* allocation_size */
4051 0, /* private_flags */
4054 &new_fsp
, /* result */
4056 NULL
, NULL
); /* create context */
4058 if (!NT_STATUS_IS_OK(status
)) {
4059 /* NB. We check for open_was_deferred in the caller. */
4063 /* See RAW-SFILEINFO-END-OF-FILE */
4064 if (fail_after_createfile
) {
4065 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4066 return NT_STATUS_INVALID_LEVEL
;
4069 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4070 status
= map_nt_error_from_unix(errno
);
4071 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4075 trigger_write_time_update_immediate(new_fsp
);
4076 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4077 return NT_STATUS_OK
;
4080 /****************************************************************************
4081 Deal with SMB_INFO_SET_EA.
4082 ****************************************************************************/
4084 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4088 struct smb_filename
*smb_fname
)
4090 struct ea_list
*ea_list
= NULL
;
4091 TALLOC_CTX
*ctx
= NULL
;
4092 NTSTATUS status
= NT_STATUS_OK
;
4094 if (total_data
< 10) {
4096 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4097 length. They seem to have no effect. Bug #3212. JRA */
4099 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4100 /* We're done. We only get EA info in this call. */
4101 return NT_STATUS_OK
;
4104 return NT_STATUS_INVALID_PARAMETER
;
4107 if (IVAL(pdata
,0) > total_data
) {
4108 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4109 IVAL(pdata
,0), (unsigned int)total_data
));
4110 return NT_STATUS_INVALID_PARAMETER
;
4114 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4116 return NT_STATUS_INVALID_PARAMETER
;
4121 * The only way fsp can be NULL here is if
4122 * smb_fname points at a symlink and
4123 * and we're in POSIX context.
4124 * Ensure this is the case.
4126 * In this case we cannot set the EA.
4128 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4129 return NT_STATUS_ACCESS_DENIED
;
4132 status
= set_ea(conn
, fsp
, ea_list
);
4137 /****************************************************************************
4138 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4139 ****************************************************************************/
4141 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4146 struct ea_list
*ea_list
= NULL
;
4150 return NT_STATUS_INVALID_HANDLE
;
4153 if (!lp_ea_support(SNUM(conn
))) {
4154 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4155 "EA's not supported.\n",
4156 (unsigned int)total_data
));
4157 return NT_STATUS_EAS_NOT_SUPPORTED
;
4160 if (total_data
< 10) {
4161 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4163 (unsigned int)total_data
));
4164 return NT_STATUS_INVALID_PARAMETER
;
4167 ea_list
= read_nttrans_ea_list(talloc_tos(),
4172 return NT_STATUS_INVALID_PARAMETER
;
4175 status
= set_ea(conn
, fsp
, ea_list
);
4177 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4178 smb_fname_str_dbg(fsp
->fsp_name
),
4179 nt_errstr(status
) ));
4185 /****************************************************************************
4186 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4187 ****************************************************************************/
4189 NTSTATUS
smb_check_file_disposition_info(struct files_struct
*fsp
,
4192 bool *_delete_on_close
)
4194 bool delete_on_close
;
4195 uint32_t dosmode
= 0;
4198 if (total_data
< 1) {
4199 return NT_STATUS_INVALID_PARAMETER
;
4203 return NT_STATUS_INVALID_HANDLE
;
4206 delete_on_close
= (PULL_LE_U8(data
, 0) ? true : false);
4207 *_delete_on_close
= delete_on_close
;
4209 dosmode
= fdos_mode(fsp
);
4211 DBG_DEBUG("file [%s] dosmode = %u, delete_on_close = %s\n",
4213 (unsigned int)dosmode
,
4214 delete_on_close
? "yes" : "no");
4216 if (!delete_on_close
) {
4217 return NT_STATUS_OK
;
4220 status
= can_set_delete_on_close(fsp
, dosmode
);
4221 if (!NT_STATUS_IS_OK(status
)) {
4225 return NT_STATUS_OK
;
4228 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4232 struct smb_filename
*smb_fname
)
4235 bool delete_on_close
;
4237 status
= smb_check_file_disposition_info(fsp
,
4241 if (!NT_STATUS_IS_OK(status
)) {
4245 /* The set is across all open files on this dev/inode pair. */
4246 if (!set_delete_on_close(fsp
, delete_on_close
,
4247 conn
->session_info
->security_token
,
4248 conn
->session_info
->unix_token
)) {
4249 return NT_STATUS_ACCESS_DENIED
;
4251 return NT_STATUS_OK
;
4254 /****************************************************************************
4255 Deal with SMB_FILE_POSITION_INFORMATION.
4256 ****************************************************************************/
4258 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4263 uint64_t position_information
;
4265 if (total_data
< 8) {
4266 return NT_STATUS_INVALID_PARAMETER
;
4270 /* Ignore on pathname based set. */
4271 return NT_STATUS_OK
;
4274 position_information
= (uint64_t)IVAL(pdata
,0);
4275 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4277 DEBUG(10,("smb_file_position_information: Set file position "
4278 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4279 (double)position_information
));
4280 fh_set_position_information(fsp
->fh
, position_information
);
4281 return NT_STATUS_OK
;
4284 /****************************************************************************
4285 Deal with SMB_FILE_MODE_INFORMATION.
4286 ****************************************************************************/
4288 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4294 if (total_data
< 4) {
4295 return NT_STATUS_INVALID_PARAMETER
;
4297 mode
= IVAL(pdata
,0);
4298 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4299 return NT_STATUS_INVALID_PARAMETER
;
4301 return NT_STATUS_OK
;
4304 /****************************************************************************
4305 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4306 ****************************************************************************/
4308 NTSTATUS
smb2_parse_file_rename_information(TALLOC_CTX
*ctx
,
4309 struct connection_struct
*conn
,
4310 struct smb_request
*req
,
4314 struct smb_filename
*smb_fname_src
,
4316 struct files_struct
**_dst_dirfsp
,
4317 struct smb_filename
**_smb_fname_dst
,
4318 char **_dst_original_lcomp
)
4320 char *newname
= NULL
;
4321 struct files_struct
*dst_dirfsp
= NULL
;
4322 struct smb_filename
*smb_fname_dst
= NULL
;
4323 char *dst_original_lcomp
= NULL
;
4324 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4325 bool overwrite
= false;
4330 return NT_STATUS_INVALID_HANDLE
;
4333 if (total_data
< 20) {
4334 return NT_STATUS_INVALID_PARAMETER
;
4337 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4338 len
= IVAL(pdata
,16);
4340 if (len
> (total_data
- 20) || (len
== 0)) {
4341 return NT_STATUS_INVALID_PARAMETER
;
4344 (void)srvstr_pull_talloc(ctx
,
4352 if (newname
== NULL
) {
4353 return NT_STATUS_INVALID_PARAMETER
;
4356 /* SMB2 rename paths are never DFS. */
4357 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4358 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4360 status
= check_path_syntax(newname
,
4361 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4362 if (!NT_STATUS_IS_OK(status
)) {
4363 TALLOC_FREE(newname
);
4367 DBG_DEBUG("got name |%s|\n", newname
);
4369 if (newname
[0] == ':') {
4370 /* Create an smb_fname to call rename_internals_fsp() with. */
4371 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4372 fsp
->base_fsp
->fsp_name
->base_name
,
4375 fsp
->base_fsp
->fsp_name
->twrp
,
4376 fsp
->base_fsp
->fsp_name
->flags
);
4377 if (smb_fname_dst
== NULL
) {
4378 TALLOC_FREE(newname
);
4379 return NT_STATUS_NO_MEMORY
;
4383 status
= filename_convert_dirfsp(ctx
,
4387 0, /* Never a TWRP. */
4390 if (!NT_STATUS_IS_OK(status
)) {
4396 * Set the original last component, since
4397 * rename_internals_fsp() requires it.
4399 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4403 if (dst_original_lcomp
== NULL
) {
4404 TALLOC_FREE(newname
);
4405 TALLOC_FREE(smb_fname_dst
);
4406 return NT_STATUS_NO_MEMORY
;
4410 *_overwrite
= overwrite
;
4411 *_dst_dirfsp
= dst_dirfsp
;
4412 *_smb_fname_dst
= smb_fname_dst
;
4413 *_dst_original_lcomp
= dst_original_lcomp
;
4414 return NT_STATUS_OK
;
4417 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4418 struct smb_request
*req
,
4422 struct share_mode_lock
**lck
,
4423 struct smb_filename
*smb_fname_src
)
4426 struct files_struct
*dst_dirfsp
= NULL
;
4427 struct smb_filename
*smb_fname_dst
= NULL
;
4428 char *dst_original_lcomp
= NULL
;
4429 NTSTATUS status
= NT_STATUS_OK
;
4430 TALLOC_CTX
*ctx
= talloc_tos();
4432 status
= smb2_parse_file_rename_information(ctx
,
4442 &dst_original_lcomp
);
4443 if (!NT_STATUS_IS_OK(status
)) {
4447 DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4450 smb_fname_str_dbg(smb_fname_dst
));
4452 status
= rename_internals_fsp(conn
,
4457 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4460 TALLOC_FREE(smb_fname_dst
);
4464 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4465 struct smb_request
*req
,
4469 struct smb_filename
*smb_fname_src
)
4473 char *newname
= NULL
;
4474 struct files_struct
*dst_dirfsp
= NULL
;
4475 struct smb_filename
*smb_fname_dst
= NULL
;
4476 NTSTATUS status
= NT_STATUS_OK
;
4477 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4479 TALLOC_CTX
*ctx
= talloc_tos();
4482 return NT_STATUS_INVALID_HANDLE
;
4485 if (total_data
< 20) {
4486 return NT_STATUS_INVALID_PARAMETER
;
4489 overwrite
= (CVAL(pdata
,0) ? true : false);
4490 len
= IVAL(pdata
,16);
4492 if (len
> (total_data
- 20) || (len
== 0)) {
4493 return NT_STATUS_INVALID_PARAMETER
;
4496 ret
= srvstr_pull_talloc(ctx
,
4504 if (ret
== (size_t)-1 || newname
== NULL
) {
4505 return NT_STATUS_INVALID_PARAMETER
;
4508 /* SMB2 hardlink paths are never DFS. */
4509 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4510 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4512 status
= check_path_syntax(newname
,
4513 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4514 if (!NT_STATUS_IS_OK(status
)) {
4518 DBG_DEBUG("got name |%s|\n", newname
);
4520 status
= filename_convert_dirfsp(ctx
,
4527 if (!NT_STATUS_IS_OK(status
)) {
4531 if (fsp
->base_fsp
) {
4532 /* No stream names. */
4533 return NT_STATUS_NOT_SUPPORTED
;
4536 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4537 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4538 smb_fname_str_dbg(smb_fname_dst
));
4539 status
= hardlink_internals(ctx
,
4546 TALLOC_FREE(smb_fname_dst
);
4550 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4551 struct smb_request
*req
,
4555 struct smb_filename
*smb_fname_src
)
4559 char *newname
= NULL
;
4560 struct files_struct
*dst_dirfsp
= NULL
;
4561 struct smb_filename
*smb_fname_dst
= NULL
;
4562 NTSTATUS status
= NT_STATUS_OK
;
4563 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4564 NTTIME dst_twrp
= 0;
4565 TALLOC_CTX
*ctx
= talloc_tos();
4568 return NT_STATUS_INVALID_HANDLE
;
4571 if (total_data
< 20) {
4572 return NT_STATUS_INVALID_PARAMETER
;
4575 overwrite
= (CVAL(pdata
,0) ? true : false);
4576 len
= IVAL(pdata
,16);
4578 if (len
> (total_data
- 20) || (len
== 0)) {
4579 return NT_STATUS_INVALID_PARAMETER
;
4582 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4583 srvstr_get_path_posix(ctx
,
4591 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4593 srvstr_get_path(ctx
,
4602 if (!NT_STATUS_IS_OK(status
)) {
4606 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4609 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4610 extract_snapshot_token(newname
, &dst_twrp
);
4612 /* hardlink paths are never DFS. */
4613 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4615 status
= filename_convert_dirfsp(ctx
,
4622 if (!NT_STATUS_IS_OK(status
)) {
4626 if (fsp
->base_fsp
) {
4627 /* No stream names. */
4628 return NT_STATUS_NOT_SUPPORTED
;
4631 DEBUG(10,("smb_file_link_information: "
4632 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4633 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4634 smb_fname_str_dbg(smb_fname_dst
)));
4635 status
= hardlink_internals(ctx
,
4642 TALLOC_FREE(smb_fname_dst
);
4647 /****************************************************************************
4648 Deal with SMB_FILE_RENAME_INFORMATION.
4649 ****************************************************************************/
4651 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4652 struct smb_request
*req
,
4656 struct smb_filename
*smb_fname_src
)
4661 char *newname
= NULL
;
4662 struct files_struct
*dst_dirfsp
= NULL
;
4663 struct smb_filename
*smb_fname_dst
= NULL
;
4664 const char *dst_original_lcomp
= NULL
;
4665 NTSTATUS status
= NT_STATUS_OK
;
4667 TALLOC_CTX
*ctx
= talloc_tos();
4669 if (total_data
< 13) {
4670 return NT_STATUS_INVALID_PARAMETER
;
4673 overwrite
= (CVAL(pdata
,0) != 0);
4674 root_fid
= IVAL(pdata
,4);
4675 len
= IVAL(pdata
,8);
4677 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4678 return NT_STATUS_INVALID_PARAMETER
;
4681 if (req
->posix_pathnames
) {
4682 srvstr_get_path_posix(ctx
,
4691 srvstr_get_path(ctx
,
4700 if (!NT_STATUS_IS_OK(status
)) {
4704 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4707 /* Check the new name has no '/' characters. */
4708 if (strchr_m(newname
, '/')) {
4709 return NT_STATUS_NOT_SUPPORTED
;
4712 if (fsp
&& fsp
->base_fsp
) {
4713 /* newname must be a stream name. */
4714 if (newname
[0] != ':') {
4715 return NT_STATUS_NOT_SUPPORTED
;
4718 /* Create an smb_fname to call rename_internals_fsp() with. */
4719 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4720 fsp
->base_fsp
->fsp_name
->base_name
,
4723 fsp
->base_fsp
->fsp_name
->twrp
,
4724 fsp
->base_fsp
->fsp_name
->flags
);
4725 if (smb_fname_dst
== NULL
) {
4726 status
= NT_STATUS_NO_MEMORY
;
4731 * Get the original last component, since
4732 * rename_internals_fsp() requires it.
4734 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4738 if (dst_original_lcomp
== NULL
) {
4739 status
= NT_STATUS_NO_MEMORY
;
4745 * Build up an smb_fname_dst based on the filename passed in.
4746 * We basically just strip off the last component, and put on
4747 * the newname instead.
4749 char *base_name
= NULL
;
4750 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4751 NTTIME dst_twrp
= 0;
4753 /* newname must *not* be a stream name. */
4754 if (newname
[0] == ':') {
4755 return NT_STATUS_NOT_SUPPORTED
;
4759 * Strip off the last component (filename) of the path passed
4762 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4764 return NT_STATUS_NO_MEMORY
;
4766 p
= strrchr_m(base_name
, '/');
4770 base_name
= talloc_strdup(ctx
, "");
4772 return NT_STATUS_NO_MEMORY
;
4775 /* Append the new name. */
4776 base_name
= talloc_asprintf_append(base_name
,
4780 return NT_STATUS_NO_MEMORY
;
4783 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4784 extract_snapshot_token(base_name
, &dst_twrp
);
4787 /* The newname is *not* a DFS path. */
4788 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4790 status
= filename_convert_dirfsp(ctx
,
4798 if (!NT_STATUS_IS_OK(status
)) {
4801 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4805 if (dst_original_lcomp
== NULL
) {
4806 status
= NT_STATUS_NO_MEMORY
;
4811 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4812 DEBUG(10,("smb_file_rename_information: "
4813 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4814 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4815 smb_fname_str_dbg(smb_fname_dst
)));
4818 * If no pathnames are open below this directory,
4821 if (have_file_open_below(fsp
)) {
4822 status
= NT_STATUS_ACCESS_DENIED
;
4826 status
= rename_internals_fsp(conn
,
4834 DEBUG(10,("smb_file_rename_information: "
4835 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4836 smb_fname_str_dbg(smb_fname_src
),
4837 smb_fname_str_dbg(smb_fname_dst
)));
4838 status
= rename_internals(ctx
,
4841 NULL
, /* src_dirfsp */
4847 FILE_WRITE_ATTRIBUTES
);
4850 TALLOC_FREE(smb_fname_dst
);
4854 /****************************************************************************
4855 Deal with SMB_SET_FILE_BASIC_INFO.
4856 ****************************************************************************/
4858 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4862 struct smb_filename
*smb_fname
)
4864 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4865 struct smb_file_time ft
;
4866 uint32_t dosmode
= 0;
4867 NTSTATUS status
= NT_STATUS_OK
;
4869 init_smb_file_time(&ft
);
4871 if (total_data
< 36) {
4872 return NT_STATUS_INVALID_PARAMETER
;
4876 return NT_STATUS_INVALID_HANDLE
;
4879 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4880 if (!NT_STATUS_IS_OK(status
)) {
4884 /* Set the attributes */
4885 dosmode
= IVAL(pdata
,32);
4886 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4887 if (!NT_STATUS_IS_OK(status
)) {
4892 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4895 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4898 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4901 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4903 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4904 smb_fname_str_dbg(smb_fname
)));
4906 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4907 if (!NT_STATUS_IS_OK(status
)) {
4911 if (fsp
->fsp_flags
.modified
) {
4912 trigger_write_time_update_immediate(fsp
);
4914 return NT_STATUS_OK
;
4917 /****************************************************************************
4918 Deal with SMB_INFO_STANDARD.
4919 ****************************************************************************/
4921 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4925 struct smb_filename
*smb_fname
)
4928 struct smb_file_time ft
;
4930 init_smb_file_time(&ft
);
4932 if (total_data
< 12) {
4933 return NT_STATUS_INVALID_PARAMETER
;
4937 return NT_STATUS_INVALID_HANDLE
;
4941 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4943 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4945 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4947 DEBUG(10,("smb_set_info_standard: file %s\n",
4948 smb_fname_str_dbg(smb_fname
)));
4950 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4951 if (!NT_STATUS_IS_OK(status
)) {
4955 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4956 if (!NT_STATUS_IS_OK(status
)) {
4960 if (fsp
->fsp_flags
.modified
) {
4961 trigger_write_time_update_immediate(fsp
);
4963 return NT_STATUS_OK
;
4966 /****************************************************************************
4967 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4968 ****************************************************************************/
4970 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4971 struct smb_request
*req
,
4975 struct smb_filename
*smb_fname
)
4977 uint64_t allocation_size
= 0;
4978 NTSTATUS status
= NT_STATUS_OK
;
4979 files_struct
*new_fsp
= NULL
;
4981 if (!VALID_STAT(smb_fname
->st
)) {
4982 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4985 if (total_data
< 8) {
4986 return NT_STATUS_INVALID_PARAMETER
;
4989 allocation_size
= (uint64_t)IVAL(pdata
,0);
4990 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4991 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4992 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4993 (double)allocation_size
));
4995 if (allocation_size
) {
4996 allocation_size
= smb_roundup(conn
, allocation_size
);
4999 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5000 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
5001 (double)allocation_size
));
5004 !fsp
->fsp_flags
.is_pathref
&&
5005 fsp_get_io_fd(fsp
) != -1)
5007 /* Open file handle. */
5008 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
5009 if (!NT_STATUS_IS_OK(status
)) {
5013 /* Only change if needed. */
5014 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5015 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5016 return map_nt_error_from_unix(errno
);
5019 /* But always update the time. */
5021 * This is equivalent to a write. Ensure it's seen immediately
5022 * if there are no pending writes.
5024 trigger_write_time_update_immediate(fsp
);
5025 return NT_STATUS_OK
;
5028 /* Pathname or stat or directory file. */
5029 status
= SMB_VFS_CREATE_FILE(
5033 smb_fname
, /* fname */
5034 FILE_WRITE_DATA
, /* access_mask */
5035 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5037 FILE_OPEN
, /* create_disposition*/
5038 0, /* create_options */
5039 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5040 0, /* oplock_request */
5042 0, /* allocation_size */
5043 0, /* private_flags */
5046 &new_fsp
, /* result */
5048 NULL
, NULL
); /* create context */
5050 if (!NT_STATUS_IS_OK(status
)) {
5051 /* NB. We check for open_was_deferred in the caller. */
5055 /* Only change if needed. */
5056 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5057 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5058 status
= map_nt_error_from_unix(errno
);
5059 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5064 /* Changing the allocation size should set the last mod time. */
5066 * This is equivalent to a write. Ensure it's seen immediately
5067 * if there are no pending writes.
5069 trigger_write_time_update_immediate(new_fsp
);
5070 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5071 return NT_STATUS_OK
;
5074 /****************************************************************************
5075 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5076 ****************************************************************************/
5078 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5079 struct smb_request
*req
,
5083 struct smb_filename
*smb_fname
,
5084 bool fail_after_createfile
)
5088 if (total_data
< 8) {
5089 return NT_STATUS_INVALID_PARAMETER
;
5092 size
= IVAL(pdata
,0);
5093 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5094 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5095 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5098 return smb_set_file_size(conn
, req
,
5103 fail_after_createfile
);
5109 * Called from the SMB1 and SMB2 code. For the path-based SMB1 code, there may
5110 * not be a full fsp from the FSA layer.
5112 * lck may be NULL, currently only passed for SMB2 rename requests.
5114 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5115 struct smb_request
*req
,
5116 TALLOC_CTX
*mem_ctx
,
5117 uint16_t info_level
,
5119 struct share_mode_lock
**lck
,
5120 struct smb_filename
*smb_fname
,
5125 NTSTATUS status
= NT_STATUS_OK
;
5126 int data_return_size
= 0;
5130 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5131 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5133 info_level
, total_data
));
5135 SMB_ASSERT(fsp
!= NULL
);
5137 switch (info_level
) {
5139 case SMB_INFO_STANDARD
:
5141 status
= smb_set_info_standard(conn
,
5149 case SMB_INFO_SET_EA
:
5151 status
= smb_info_set_ea(conn
,
5159 case SMB_SET_FILE_BASIC_INFO
:
5160 case SMB_FILE_BASIC_INFORMATION
:
5162 status
= smb_set_file_basic_info(conn
,
5170 case SMB_FILE_ALLOCATION_INFORMATION
:
5171 case SMB_SET_FILE_ALLOCATION_INFO
:
5173 status
= smb_set_file_allocation_info(conn
, req
,
5181 case SMB_FILE_END_OF_FILE_INFORMATION
:
5182 case SMB_SET_FILE_END_OF_FILE_INFO
:
5185 * XP/Win7 both fail after the createfile with
5186 * SMB_SET_FILE_END_OF_FILE_INFO but not
5187 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5188 * The level is known here, so pass it down
5192 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5194 status
= smb_set_file_end_of_file_info(conn
, req
,
5203 case SMB_FILE_DISPOSITION_INFORMATION
:
5204 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5206 status
= smb_set_file_disposition_info(conn
,
5214 case SMB_FILE_POSITION_INFORMATION
:
5216 status
= smb_file_position_information(conn
,
5223 case SMB_FILE_FULL_EA_INFORMATION
:
5225 status
= smb_set_file_full_ea_info(conn
,
5232 /* From tridge Samba4 :
5233 * MODE_INFORMATION in setfileinfo (I have no
5234 * idea what "mode information" on a file is - it takes a value of 0,
5235 * 2, 4 or 6. What could it be?).
5238 case SMB_FILE_MODE_INFORMATION
:
5240 status
= smb_file_mode_information(conn
,
5246 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5247 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5248 case SMB_FILE_SHORT_NAME_INFORMATION
:
5249 return NT_STATUS_NOT_SUPPORTED
;
5251 case SMB_FILE_RENAME_INFORMATION
:
5253 status
= smb_file_rename_information(conn
, req
,
5259 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5261 /* SMB2 rename information. */
5262 status
= smb2_file_rename_information(conn
,
5272 case SMB_FILE_LINK_INFORMATION
:
5274 if (conn_using_smb2(conn
->sconn
)) {
5275 status
= smb2_file_link_information(conn
,
5282 status
= smb_file_link_information(conn
,
5293 return NT_STATUS_INVALID_LEVEL
;
5296 if (!NT_STATUS_IS_OK(status
)) {
5300 *ret_data_size
= data_return_size
;
5301 return NT_STATUS_OK
;
5304 static uint32_t generate_volume_serial_number(
5305 const struct loadparm_substitution
*lp_sub
,
5308 int serial
= lp_volume_serial_number(snum
);
5309 return serial
!= -1 ? serial
:
5310 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5311 (str_checksum(get_local_machine_name())<<16);