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 "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct
*conn
,
54 const SMB_STRUCT_STAT
*psbuf
);
56 static char *store_file_unix_basic_info2(connection_struct
*conn
,
59 const SMB_STRUCT_STAT
*psbuf
);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS
refuse_symlink(connection_struct
*conn
,
66 const files_struct
*fsp
,
67 const struct smb_filename
*smb_fname
)
70 const SMB_STRUCT_STAT
*pst
= NULL
;
73 pst
= &fsp
->fsp_name
->st
;
78 if (!VALID_STAT(*pst
)) {
79 int ret
= vfs_stat_smb_basename(conn
,
82 if (ret
== -1 && errno
!= ENOENT
) {
83 return map_nt_error_from_unix(errno
);
84 } else if (ret
== -1) {
85 /* it's not a symlink.. */
91 if (S_ISLNK(pst
->st_ex_mode
)) {
92 return NT_STATUS_ACCESS_DENIED
;
97 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
100 if (!fsp
->fsp_flags
.is_fsa
) {
101 return smbd_check_access_rights_fsp(fsp
,
105 if (!(fsp
->access_mask
& access_mask
)) {
106 return NT_STATUS_ACCESS_DENIED
;
111 #if defined(HAVE_POSIX_ACLS)
112 /****************************************************************************
113 Utility function to open a fsp for a POSIX handle operation.
114 ****************************************************************************/
116 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
117 struct smb_request
*req
,
118 struct smb_filename
*smb_fname
,
119 uint32_t access_mask
,
120 files_struct
**ret_fsp
)
123 uint32_t create_disposition
= FILE_OPEN
;
124 uint32_t share_access
= FILE_SHARE_READ
|
127 struct smb2_create_blobs
*posx
= NULL
;
130 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
131 * but set reasonable defaults.
133 uint32_t file_attributes
= 0664;
134 uint32_t oplock
= NO_OPLOCK
;
135 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
137 /* File or directory must exist. */
138 if (!VALID_STAT(smb_fname
->st
)) {
139 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
141 /* Cannot be a symlink. */
142 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
143 return NT_STATUS_ACCESS_DENIED
;
145 /* Set options correctly for directory open. */
146 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
148 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
149 * directories, but set reasonable defaults.
151 file_attributes
= 0775;
152 create_options
= FILE_DIRECTORY_FILE
;
155 status
= make_smb2_posix_create_ctx(
156 talloc_tos(), &posx
, file_attributes
);
157 if (!NT_STATUS_IS_OK(status
)) {
158 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
163 status
= SMB_VFS_CREATE_FILE(
166 smb_fname
, /* fname */
167 access_mask
, /* access_mask */
168 share_access
, /* share_access */
169 create_disposition
,/* create_disposition*/
170 create_options
, /* create_options */
171 file_attributes
,/* file_attributes */
172 oplock
, /* oplock_request */
174 0, /* allocation_size */
175 0, /* private_flags */
178 ret_fsp
, /* result */
180 posx
, /* in_context */
181 NULL
); /* out_context */
189 /********************************************************************
190 Roundup a value to the nearest allocation roundup size boundary.
191 Only do this for Windows clients.
192 ********************************************************************/
194 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
196 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
198 /* Only roundup for Windows clients. */
199 enum remote_arch_types ra_type
= get_remote_arch();
200 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
201 val
= SMB_ROUNDUP(val
,rval
);
206 /****************************************************************************
207 Utility functions for dealing with extended attributes.
208 ****************************************************************************/
210 /****************************************************************************
211 Refuse to allow clients to overwrite our private xattrs.
212 ****************************************************************************/
214 bool samba_private_attr_name(const char *unix_ea_name
)
216 static const char * const prohibited_ea_names
[] = {
217 SAMBA_POSIX_INHERITANCE_EA_NAME
,
218 SAMBA_XATTR_DOS_ATTRIB
,
226 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
227 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
230 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
231 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
237 /****************************************************************************
238 Get one EA value. Fill in a struct ea_struct.
239 ****************************************************************************/
241 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
,
242 connection_struct
*conn
,
244 const struct smb_filename
*smb_fname
,
246 struct ea_struct
*pea
)
248 /* Get the value of this xattr. Max size is 64k. */
249 size_t attr_size
= 256;
255 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
257 return NT_STATUS_NO_MEMORY
;
260 if (fsp
&& !fsp
->fsp_flags
.is_pathref
&& fsp_get_io_fd(fsp
) != -1) {
261 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
263 sizeret
= SMB_VFS_GETXATTR(conn
, smb_fname
,
264 ea_name
, val
, attr_size
);
267 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
273 return map_nt_error_from_unix(errno
);
276 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
277 dump_data(10, (uint8_t *)val
, sizeret
);
280 if (strnequal(ea_name
, "user.", 5)) {
281 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
283 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
285 if (pea
->name
== NULL
) {
287 return NT_STATUS_NO_MEMORY
;
289 pea
->value
.data
= (unsigned char *)val
;
290 pea
->value
.length
= (size_t)sizeret
;
294 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
,
295 connection_struct
*conn
,
301 /* Get a list of all xattrs. Max namesize is 64k. */
302 size_t ea_namelist_size
= 1024;
303 char *ea_namelist
= smallbuf
;
304 char *to_free
= NULL
;
309 ssize_t sizeret
= -1;
319 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
320 * symlink. This is ok, handle it here, by just return no EA's
326 /* should be the case that fsp != NULL */
327 SMB_ASSERT(fsp
!= NULL
);
329 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
332 if ((sizeret
== -1) && (errno
== ERANGE
)) {
333 ea_namelist_size
= 65536;
334 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
335 if (ea_namelist
== NULL
) {
336 return NT_STATUS_NO_MEMORY
;
338 to_free
= ea_namelist
;
340 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
345 status
= map_nt_error_from_unix(errno
);
346 TALLOC_FREE(to_free
);
350 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
353 TALLOC_FREE(to_free
);
358 * Ensure the result is 0-terminated
361 if (ea_namelist
[sizeret
-1] != '\0') {
362 TALLOC_FREE(to_free
);
363 return NT_STATUS_INTERNAL_ERROR
;
371 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
375 *pnum_names
= num_names
;
377 if (pnames
== NULL
) {
378 TALLOC_FREE(to_free
);
382 names
= talloc_array(mem_ctx
, char *, num_names
);
384 DEBUG(0, ("talloc failed\n"));
385 TALLOC_FREE(to_free
);
386 return NT_STATUS_NO_MEMORY
;
389 if (ea_namelist
== smallbuf
) {
390 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
391 if (ea_namelist
== NULL
) {
393 return NT_STATUS_NO_MEMORY
;
396 talloc_steal(names
, ea_namelist
);
398 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
400 if (ea_namelist
== NULL
) {
402 return NT_STATUS_NO_MEMORY
;
408 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
409 names
[num_names
++] = p
;
417 /****************************************************************************
418 Return a linked list of the total EA's. Plus the total size
419 ****************************************************************************/
421 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
423 size_t *pea_total_len
,
424 struct ea_list
**ea_list
)
426 /* Get a list of all xattrs. Max namesize is 64k. */
429 struct ea_list
*ea_list_head
= NULL
;
430 bool posix_pathnames
= false;
441 if (!lp_ea_support(SNUM(fsp
->conn
))) {
445 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
446 return NT_STATUS_INVALID_PARAMETER
;
449 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
451 status
= get_ea_names_from_file(talloc_tos(),
457 if (!NT_STATUS_IS_OK(status
)) {
461 if (num_names
== 0) {
465 for (i
=0; i
<num_names
; i
++) {
466 struct ea_list
*listp
;
469 if (strnequal(names
[i
], "system.", 7)
470 || samba_private_attr_name(names
[i
]))
474 * Filter out any underlying POSIX EA names
475 * that a Windows client can't handle.
477 if (!posix_pathnames
&&
478 is_invalid_windows_ea_name(names
[i
])) {
482 listp
= talloc(mem_ctx
, struct ea_list
);
484 return NT_STATUS_NO_MEMORY
;
487 status
= get_ea_value(listp
,
494 if (!NT_STATUS_IS_OK(status
)) {
499 if (listp
->ea
.value
.length
== 0) {
501 * We can never return a zero length EA.
502 * Windows reports the EA's as corrupted.
508 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
511 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
513 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
514 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
515 (unsigned int)listp
->ea
.value
.length
));
517 DLIST_ADD_END(ea_list_head
, listp
);
521 /* Add on 4 for total length. */
522 if (*pea_total_len
) {
526 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
527 (unsigned int)*pea_total_len
));
529 *ea_list
= ea_list_head
;
533 /****************************************************************************
534 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
536 ****************************************************************************/
538 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
539 connection_struct
*conn
, struct ea_list
*ea_list
)
541 unsigned int ret_data_size
= 4;
544 SMB_ASSERT(total_data_size
>= 4);
546 if (!lp_ea_support(SNUM(conn
))) {
551 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
554 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
555 dos_namelen
= strlen(dos_ea_name
);
556 if (dos_namelen
> 255 || dos_namelen
== 0) {
559 if (ea_list
->ea
.value
.length
> 65535) {
562 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
566 /* We know we have room. */
567 SCVAL(p
,0,ea_list
->ea
.flags
);
568 SCVAL(p
,1,dos_namelen
);
569 SSVAL(p
,2,ea_list
->ea
.value
.length
);
570 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
571 if (ea_list
->ea
.value
.length
> 0) {
572 memcpy(p
+ 4 + dos_namelen
+ 1,
573 ea_list
->ea
.value
.data
,
574 ea_list
->ea
.value
.length
);
577 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
578 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
581 ret_data_size
= PTR_DIFF(p
, pdata
);
582 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
583 SIVAL(pdata
,0,ret_data_size
);
584 return ret_data_size
;
587 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
589 unsigned int total_data_size
,
590 unsigned int *ret_data_size
,
591 connection_struct
*conn
,
592 struct ea_list
*ea_list
)
594 uint8_t *p
= (uint8_t *)pdata
;
595 uint8_t *last_start
= NULL
;
596 bool do_store_data
= (pdata
!= NULL
);
600 if (!lp_ea_support(SNUM(conn
))) {
601 return NT_STATUS_NO_EAS_ON_FILE
;
604 for (; ea_list
; ea_list
= ea_list
->next
) {
610 if (last_start
!= NULL
&& do_store_data
) {
611 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
615 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
616 dos_namelen
= strlen(dos_ea_name
);
617 if (dos_namelen
> 255 || dos_namelen
== 0) {
618 return NT_STATUS_INTERNAL_ERROR
;
620 if (ea_list
->ea
.value
.length
> 65535) {
621 return NT_STATUS_INTERNAL_ERROR
;
624 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
627 pad
= (4 - (this_size
% 4)) % 4;
632 if (this_size
> total_data_size
) {
633 return NT_STATUS_INFO_LENGTH_MISMATCH
;
636 /* We know we have room. */
637 SIVAL(p
, 0x00, 0); /* next offset */
638 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
639 SCVAL(p
, 0x05, dos_namelen
);
640 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
641 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
642 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
644 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
648 total_data_size
-= this_size
;
654 *ret_data_size
= PTR_DIFF(p
, pdata
);
655 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
659 static unsigned int estimate_ea_size(files_struct
*fsp
)
661 size_t total_ea_len
= 0;
663 struct ea_list
*ea_list
= NULL
;
671 mem_ctx
= talloc_stackframe();
672 if (!lp_ea_support(SNUM(fsp
->conn
))) {
676 /* If this is a stream fsp, then we need to instead find the
677 * estimated ea len from the main file, not the stream
678 * (streams cannot have EAs), but the estimate isn't just 0 in
680 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
683 (void)get_ea_list_from_fsp(mem_ctx
,
688 if(fsp
->conn
->sconn
->using_smb2
) {
689 unsigned int ret_data_size
;
691 * We're going to be using fill_ea_chained_buffer() to
692 * marshall EA's - this size is significantly larger
693 * than the SMB1 buffer. Re-calculate the size without
696 status
= fill_ea_chained_buffer(mem_ctx
,
702 if (!NT_STATUS_IS_OK(status
)) {
705 total_ea_len
= ret_data_size
;
707 TALLOC_FREE(mem_ctx
);
711 /****************************************************************************
712 Ensure the EA name is case insensitive by matching any existing EA name.
713 ****************************************************************************/
715 static void canonicalize_ea_name(files_struct
*fsp
,
716 fstring unix_ea_name
)
719 TALLOC_CTX
*mem_ctx
= talloc_tos();
720 struct ea_list
*ea_list
;
721 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
725 if (!NT_STATUS_IS_OK(status
)) {
729 for (; ea_list
; ea_list
= ea_list
->next
) {
730 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
731 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
732 &unix_ea_name
[5], ea_list
->ea
.name
));
733 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
739 /****************************************************************************
740 Set or delete an extended attribute.
741 ****************************************************************************/
743 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
744 struct ea_list
*ea_list
)
747 bool posix_pathnames
= false;
749 if (!lp_ea_support(SNUM(conn
))) {
750 return NT_STATUS_EAS_NOT_SUPPORTED
;
753 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
755 status
= refuse_symlink(conn
, fsp
, fsp
->fsp_name
);
756 if (!NT_STATUS_IS_OK(status
)) {
760 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
761 if (!NT_STATUS_IS_OK(status
)) {
765 /* Setting EAs on streams isn't supported. */
766 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
767 return NT_STATUS_INVALID_PARAMETER
;
771 * Filter out invalid Windows EA names - before
772 * we set *any* of them.
775 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
776 return STATUS_INVALID_EA_NAME
;
779 for (;ea_list
; ea_list
= ea_list
->next
) {
781 fstring unix_ea_name
;
783 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
784 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
786 canonicalize_ea_name(fsp
, unix_ea_name
);
788 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
790 if (samba_private_attr_name(unix_ea_name
)) {
791 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
792 return NT_STATUS_ACCESS_DENIED
;
795 if (ea_list
->ea
.value
.length
== 0) {
796 /* Remove the attribute. */
797 if (!fsp
->fsp_flags
.is_pathref
&&
798 fsp_get_io_fd(fsp
) != -1)
800 DEBUG(10,("set_ea: deleting ea name %s on "
801 "file %s by file descriptor.\n",
802 unix_ea_name
, fsp_str_dbg(fsp
)));
803 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
805 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
806 unix_ea_name
, fsp
->fsp_name
->base_name
));
807 ret
= SMB_VFS_REMOVEXATTR(conn
,
812 /* Removing a non existent attribute always succeeds. */
813 if (ret
== -1 && errno
== ENOATTR
) {
814 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
820 if (!fsp
->fsp_flags
.is_pathref
&&
821 fsp_get_io_fd(fsp
) != -1)
823 DEBUG(10,("set_ea: setting ea name %s on file "
824 "%s by file descriptor.\n",
825 unix_ea_name
, fsp_str_dbg(fsp
)));
826 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
827 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
829 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
830 unix_ea_name
, fsp
->fsp_name
->base_name
));
831 ret
= SMB_VFS_SETXATTR(conn
,
834 ea_list
->ea
.value
.data
,
835 ea_list
->ea
.value
.length
,
842 if (errno
== ENOTSUP
) {
843 return NT_STATUS_EAS_NOT_SUPPORTED
;
846 return map_nt_error_from_unix(errno
);
852 /****************************************************************************
853 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
854 ****************************************************************************/
856 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
858 struct ea_list
*ea_list_head
= NULL
;
859 size_t converted_size
, offset
= 0;
861 while (offset
+ 2 < data_size
) {
862 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
863 unsigned int namelen
= CVAL(pdata
,offset
);
865 offset
++; /* Go past the namelen byte. */
867 /* integer wrap paranioa. */
868 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
869 (offset
> data_size
) || (namelen
> data_size
) ||
870 (offset
+ namelen
>= data_size
)) {
873 /* Ensure the name is null terminated. */
874 if (pdata
[offset
+ namelen
] != '\0') {
877 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
879 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
880 "failed: %s", strerror(errno
)));
886 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
887 DLIST_ADD_END(ea_list_head
, eal
);
888 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
894 /****************************************************************************
895 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
896 ****************************************************************************/
898 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
900 struct ea_list
*ea_list_head
= NULL
;
902 size_t bytes_used
= 0;
904 while (offset
< data_size
) {
905 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
911 DLIST_ADD_END(ea_list_head
, eal
);
912 offset
+= bytes_used
;
918 /****************************************************************************
919 Count the total EA size needed.
920 ****************************************************************************/
922 static size_t ea_list_size(struct ea_list
*ealist
)
925 struct ea_list
*listp
;
928 for (listp
= ealist
; listp
; listp
= listp
->next
) {
929 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
930 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
932 /* Add on 4 for total length. */
940 /****************************************************************************
941 Return a union of EA's from a file list and a list of names.
942 The TALLOC context for the two lists *MUST* be identical as we steal
943 memory from one list to add to another. JRA.
944 ****************************************************************************/
946 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
948 struct ea_list
*nlistp
, *flistp
;
950 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
951 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
952 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
958 /* Copy the data from this entry. */
959 nlistp
->ea
.flags
= flistp
->ea
.flags
;
960 nlistp
->ea
.value
= flistp
->ea
.value
;
963 nlistp
->ea
.flags
= 0;
964 ZERO_STRUCT(nlistp
->ea
.value
);
968 *total_ea_len
= ea_list_size(name_list
);
972 /****************************************************************************
973 Send the required number of replies back.
974 We assume all fields other than the data fields are
975 set correctly for the type of call.
976 HACK ! Always assumes smb_setup field is zero.
977 ****************************************************************************/
979 void send_trans2_replies(connection_struct
*conn
,
980 struct smb_request
*req
,
988 /* As we are using a protocol > LANMAN1 then the max_send
989 variable must have been set in the sessetupX call.
990 This takes precedence over the max_xmit field in the
991 global struct. These different max_xmit variables should
992 be merged as this is now too confusing */
994 int data_to_send
= datasize
;
995 int params_to_send
= paramsize
;
997 const char *pp
= params
;
998 const char *pd
= pdata
;
999 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
1000 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1001 int data_alignment_offset
= 0;
1002 bool overflow
= False
;
1003 struct smbXsrv_connection
*xconn
= req
->xconn
;
1004 int max_send
= xconn
->smb1
.sessions
.max_send
;
1006 /* Modify the data_to_send and datasize and set the error if
1007 we're trying to send more than max_data_bytes. We still send
1008 the part of the packet(s) that fit. Strange, but needed
1011 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
1012 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1013 max_data_bytes
, datasize
));
1014 datasize
= data_to_send
= max_data_bytes
;
1018 /* If there genuinely are no parameters or data to send just send the empty packet */
1020 if(params_to_send
== 0 && data_to_send
== 0) {
1021 reply_outbuf(req
, 10, 0);
1022 if (NT_STATUS_V(status
)) {
1025 ntstatus_to_dos(status
, &eclass
, &ecode
);
1026 error_packet_set((char *)req
->outbuf
,
1027 eclass
, ecode
, status
,
1030 show_msg((char *)req
->outbuf
);
1031 if (!srv_send_smb(xconn
,
1032 (char *)req
->outbuf
,
1033 true, req
->seqnum
+1,
1034 IS_CONN_ENCRYPTED(conn
),
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req
->outbuf
);
1042 /* When sending params and data ensure that both are nicely aligned */
1043 /* Only do this alignment when there is also data to send - else
1044 can cause NT redirector problems. */
1046 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
1047 data_alignment_offset
= 4 - (params_to_send
% 4);
1049 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1050 /* The alignment_offset is to align the param bytes on an even byte
1051 boundary. NT 4.0 Beta needs this to work correctly. */
1053 useable_space
= max_send
- (smb_size
1056 + data_alignment_offset
);
1058 if (useable_space
< 0) {
1059 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1060 "= %d!!!", useable_space
));
1061 exit_server_cleanly("send_trans2_replies: Not enough space");
1064 while (params_to_send
|| data_to_send
) {
1065 /* Calculate whether we will totally or partially fill this packet */
1067 total_sent_thistime
= params_to_send
+ data_to_send
;
1069 /* We can never send more than useable_space */
1071 * Note that 'useable_space' does not include the alignment offsets,
1072 * but we must include the alignment offsets in the calculation of
1073 * the length of the data we send over the wire, as the alignment offsets
1074 * are sent here. Fix from Marc_Jacobsen@hp.com.
1077 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
1079 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
1080 + data_alignment_offset
);
1082 /* Set total params and data to be sent */
1083 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1084 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1086 /* Calculate how many parameters and data we can fit into
1087 * this packet. Parameters get precedence
1090 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1091 data_sent_thistime
= useable_space
- params_sent_thistime
;
1092 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1094 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1096 /* smb_proff is the offset from the start of the SMB header to the
1097 parameter bytes, however the first 4 bytes of outbuf are
1098 the Netbios over TCP header. Thus use smb_base() to subtract
1099 them from the calculation */
1101 SSVAL(req
->outbuf
,smb_proff
,
1102 ((smb_buf(req
->outbuf
)+alignment_offset
)
1103 - smb_base(req
->outbuf
)));
1105 if(params_sent_thistime
== 0)
1106 SSVAL(req
->outbuf
,smb_prdisp
,0);
1108 /* Absolute displacement of param bytes sent in this packet */
1109 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1111 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1112 if(data_sent_thistime
== 0) {
1113 SSVAL(req
->outbuf
,smb_droff
,0);
1114 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1116 /* The offset of the data bytes is the offset of the
1117 parameter bytes plus the number of parameters being sent this time */
1118 SSVAL(req
->outbuf
, smb_droff
,
1119 ((smb_buf(req
->outbuf
)+alignment_offset
)
1120 - smb_base(req
->outbuf
))
1121 + params_sent_thistime
+ data_alignment_offset
);
1122 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1125 /* Initialize the padding for alignment */
1127 if (alignment_offset
!= 0) {
1128 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1131 /* Copy the param bytes into the packet */
1133 if(params_sent_thistime
) {
1134 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1135 params_sent_thistime
);
1138 /* Copy in the data bytes */
1139 if(data_sent_thistime
) {
1140 if (data_alignment_offset
!= 0) {
1141 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1142 params_sent_thistime
), 0,
1143 data_alignment_offset
);
1145 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1146 +params_sent_thistime
+data_alignment_offset
,
1147 pd
,data_sent_thistime
);
1150 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1151 params_sent_thistime
, data_sent_thistime
, useable_space
));
1152 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1153 params_to_send
, data_to_send
, paramsize
, datasize
));
1156 error_packet_set((char *)req
->outbuf
,
1157 ERRDOS
,ERRbufferoverflow
,
1158 STATUS_BUFFER_OVERFLOW
,
1160 } else if (NT_STATUS_V(status
)) {
1163 ntstatus_to_dos(status
, &eclass
, &ecode
);
1164 error_packet_set((char *)req
->outbuf
,
1165 eclass
, ecode
, status
,
1169 /* Send the packet */
1170 show_msg((char *)req
->outbuf
);
1171 if (!srv_send_smb(xconn
,
1172 (char *)req
->outbuf
,
1173 true, req
->seqnum
+1,
1174 IS_CONN_ENCRYPTED(conn
),
1176 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1178 TALLOC_FREE(req
->outbuf
);
1180 pp
+= params_sent_thistime
;
1181 pd
+= data_sent_thistime
;
1183 params_to_send
-= params_sent_thistime
;
1184 data_to_send
-= data_sent_thistime
;
1187 if(params_to_send
< 0 || data_to_send
< 0) {
1188 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1189 params_to_send
, data_to_send
));
1197 /****************************************************************************
1198 Reply to a TRANSACT2_OPEN.
1199 ****************************************************************************/
1201 static void call_trans2open(connection_struct
*conn
,
1202 struct smb_request
*req
,
1203 char **pparams
, int total_params
,
1204 char **ppdata
, int total_data
,
1205 unsigned int max_data_bytes
)
1207 struct smb_filename
*smb_fname
= NULL
;
1208 char *params
= *pparams
;
1209 char *pdata
= *ppdata
;
1212 bool oplock_request
;
1214 bool return_additional_info
;
1223 int fattr
=0,mtime
=0;
1224 SMB_INO_T inode
= 0;
1227 struct ea_list
*ea_list
= NULL
;
1230 uint32_t access_mask
;
1231 uint32_t share_mode
;
1232 uint32_t create_disposition
;
1233 uint32_t create_options
= 0;
1234 uint32_t private_flags
= 0;
1235 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1236 TALLOC_CTX
*ctx
= talloc_tos();
1239 * Ensure we have enough parameters to perform the operation.
1242 if (total_params
< 29) {
1243 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1247 flags
= SVAL(params
, 0);
1248 deny_mode
= SVAL(params
, 2);
1249 open_attr
= SVAL(params
,6);
1250 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1251 if (oplock_request
) {
1252 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1256 return_additional_info
= BITSETW(params
,0);
1257 open_sattr
= SVAL(params
, 4);
1258 open_time
= make_unix_date3(params
+8);
1260 open_ofun
= SVAL(params
,12);
1261 open_size
= IVAL(params
,14);
1262 pname
= ¶ms
[28];
1265 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1269 if (req
->posix_pathnames
) {
1270 srvstr_get_path_posix(ctx
,
1279 srvstr_get_path(ctx
,
1288 if (!NT_STATUS_IS_OK(status
)) {
1289 reply_nterror(req
, status
);
1293 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1294 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1295 (unsigned int)open_ofun
, open_size
));
1297 status
= filename_convert(ctx
,
1303 if (!NT_STATUS_IS_OK(status
)) {
1304 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1305 reply_botherror(req
,
1306 NT_STATUS_PATH_NOT_COVERED
,
1307 ERRSRV
, ERRbadpath
);
1310 reply_nterror(req
, status
);
1314 if (open_ofun
== 0) {
1315 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1319 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1321 &access_mask
, &share_mode
,
1322 &create_disposition
,
1325 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1329 /* Any data in this call is an EA list. */
1330 if (total_data
&& (total_data
!= 4)) {
1331 if (total_data
< 10) {
1332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1336 if (IVAL(pdata
,0) > total_data
) {
1337 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1338 IVAL(pdata
,0), (unsigned int)total_data
));
1339 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1343 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1350 if (!lp_ea_support(SNUM(conn
))) {
1351 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1355 if (!req
->posix_pathnames
&&
1356 ea_list_has_invalid_name(ea_list
)) {
1358 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1359 if(*pparams
== NULL
) {
1360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1364 memset(params
, '\0', param_len
);
1365 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1366 params
, param_len
, NULL
, 0, max_data_bytes
);
1371 status
= SMB_VFS_CREATE_FILE(
1374 smb_fname
, /* fname */
1375 access_mask
, /* access_mask */
1376 share_mode
, /* share_access */
1377 create_disposition
, /* create_disposition*/
1378 create_options
, /* create_options */
1379 open_attr
, /* file_attributes */
1380 oplock_request
, /* oplock_request */
1382 open_size
, /* allocation_size */
1385 ea_list
, /* ea_list */
1387 &smb_action
, /* psbuf */
1388 NULL
, NULL
); /* create context */
1390 if (!NT_STATUS_IS_OK(status
)) {
1391 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1392 /* We have re-scheduled this call. */
1396 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1397 reply_openerror(req
, status
);
1401 fsp
= fcb_or_dos_open(
1408 bool ok
= defer_smb1_sharing_violation(req
);
1412 reply_openerror(req
, status
);
1416 smb_action
= FILE_WAS_OPENED
;
1419 size
= get_file_size_stat(&smb_fname
->st
);
1420 fattr
= fdos_mode(fsp
);
1421 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1422 inode
= smb_fname
->st
.st_ex_ino
;
1423 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1424 close_file(req
, fsp
, ERROR_CLOSE
);
1425 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1429 /* Realloc the size of parameters and data we will return */
1430 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1431 if(*pparams
== NULL
) {
1432 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1437 SSVAL(params
,0,fsp
->fnum
);
1438 SSVAL(params
,2,fattr
);
1439 srv_put_dos_date2(params
,4, mtime
);
1440 SIVAL(params
,8, (uint32_t)size
);
1441 SSVAL(params
,12,deny_mode
);
1442 SSVAL(params
,14,0); /* open_type - file or directory. */
1443 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1445 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1446 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1449 SSVAL(params
,18,smb_action
);
1452 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1454 SIVAL(params
,20,inode
);
1455 SSVAL(params
,24,0); /* Padding. */
1457 uint32_t ea_size
= estimate_ea_size(smb_fname
->fsp
);
1458 SIVAL(params
, 26, ea_size
);
1460 SIVAL(params
, 26, 0);
1463 /* Send the required number of replies */
1464 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1466 TALLOC_FREE(smb_fname
);
1469 /*********************************************************
1470 Routine to check if a given string matches exactly.
1471 as a special case a mask of "." does NOT match. That
1472 is required for correct wildcard semantics
1473 Case can be significant or not.
1474 **********************************************************/
1476 static bool exact_match(bool has_wild
,
1477 bool case_sensitive
,
1481 if (mask
[0] == '.' && mask
[1] == 0) {
1489 if (case_sensitive
) {
1490 return strcmp(str
,mask
)==0;
1492 return strcasecmp_m(str
,mask
) == 0;
1496 /****************************************************************************
1497 Return the filetype for UNIX extensions.
1498 ****************************************************************************/
1500 static uint32_t unix_filetype(mode_t mode
)
1503 return UNIX_TYPE_FILE
;
1504 else if(S_ISDIR(mode
))
1505 return UNIX_TYPE_DIR
;
1507 else if(S_ISLNK(mode
))
1508 return UNIX_TYPE_SYMLINK
;
1511 else if(S_ISCHR(mode
))
1512 return UNIX_TYPE_CHARDEV
;
1515 else if(S_ISBLK(mode
))
1516 return UNIX_TYPE_BLKDEV
;
1519 else if(S_ISFIFO(mode
))
1520 return UNIX_TYPE_FIFO
;
1523 else if(S_ISSOCK(mode
))
1524 return UNIX_TYPE_SOCKET
;
1527 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1528 return UNIX_TYPE_UNKNOWN
;
1531 /****************************************************************************
1532 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1533 ****************************************************************************/
1535 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
1536 const SMB_STRUCT_STAT
*psbuf
,
1538 enum perm_type ptype
,
1543 if (perms
== SMB_MODE_NO_CHANGE
) {
1544 if (!VALID_STAT(*psbuf
)) {
1545 return NT_STATUS_INVALID_PARAMETER
;
1547 *ret_perms
= psbuf
->st_ex_mode
;
1548 return NT_STATUS_OK
;
1552 ret
= wire_perms_to_unix(perms
);
1554 if (ptype
== PERM_NEW_FILE
) {
1556 * "create mask"/"force create mode" are
1557 * only applied to new files, not existing ones.
1559 ret
&= lp_create_mask(SNUM(conn
));
1560 /* Add in force bits */
1561 ret
|= lp_force_create_mode(SNUM(conn
));
1562 } else if (ptype
== PERM_NEW_DIR
) {
1564 * "directory mask"/"force directory mode" are
1565 * only applied to new directories, not existing ones.
1567 ret
&= lp_directory_mask(SNUM(conn
));
1568 /* Add in force bits */
1569 ret
|= lp_force_directory_mode(SNUM(conn
));
1573 return NT_STATUS_OK
;
1576 /****************************************************************************
1577 Needed to show the msdfs symlinks as directories. Modifies psbuf
1578 to be a directory if it's a msdfs link.
1579 ****************************************************************************/
1581 static bool check_msdfs_link(connection_struct
*conn
,
1582 struct smb_filename
*smb_fname
)
1584 int saved_errno
= errno
;
1585 if(lp_host_msdfs() &&
1586 lp_msdfs_root(SNUM(conn
)) &&
1587 is_msdfs_link(conn
, smb_fname
)) {
1589 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1591 smb_fname
->base_name
));
1592 smb_fname
->st
.st_ex_mode
=
1593 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1594 errno
= saved_errno
;
1597 errno
= saved_errno
;
1602 /****************************************************************************
1603 Get a level dependent lanman2 dir entry.
1604 ****************************************************************************/
1606 struct smbd_dirptr_lanman2_state
{
1607 connection_struct
*conn
;
1608 uint32_t info_level
;
1609 bool check_mangled_names
;
1611 bool got_exact_match
;
1614 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1620 struct smbd_dirptr_lanman2_state
*state
=
1621 (struct smbd_dirptr_lanman2_state
*)private_data
;
1623 char mangled_name
[13]; /* mangled 8.3 name. */
1627 /* Mangle fname if it's an illegal name. */
1628 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1630 * Slow path - ensure we can push the original name as UCS2. If
1631 * not, then just don't return this name.
1635 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1636 uint8_t *tmp
= talloc_array(talloc_tos(),
1640 status
= srvstr_push(NULL
,
1641 FLAGS2_UNICODE_STRINGS
,
1650 if (!NT_STATUS_IS_OK(status
)) {
1654 ok
= name_to_8_3(dname
, mangled_name
,
1655 true, state
->conn
->params
);
1659 fname
= mangled_name
;
1664 got_match
= exact_match(state
->has_wild
,
1665 state
->conn
->case_sensitive
,
1667 state
->got_exact_match
= got_match
;
1669 got_match
= mask_match(fname
, mask
,
1670 state
->conn
->case_sensitive
);
1673 if(!got_match
&& state
->check_mangled_names
&&
1674 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1676 * It turns out that NT matches wildcards against
1677 * both long *and* short names. This may explain some
1678 * of the wildcard wierdness from old DOS clients
1679 * that some people have been seeing.... JRA.
1681 /* Force the mangling into 8.3. */
1682 ok
= name_to_8_3(fname
, mangled_name
,
1683 false, state
->conn
->params
);
1688 got_match
= exact_match(state
->has_wild
,
1689 state
->conn
->case_sensitive
,
1690 mangled_name
, mask
);
1691 state
->got_exact_match
= got_match
;
1693 got_match
= mask_match(mangled_name
, mask
,
1694 state
->conn
->case_sensitive
);
1702 *_fname
= talloc_strdup(ctx
, fname
);
1703 if (*_fname
== NULL
) {
1710 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1712 struct smb_filename
*smb_fname
,
1716 struct smbd_dirptr_lanman2_state
*state
=
1717 (struct smbd_dirptr_lanman2_state
*)private_data
;
1718 bool ms_dfs_link
= false;
1720 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
1721 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1722 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1723 "Couldn't lstat [%s] (%s)\n",
1724 smb_fname_str_dbg(smb_fname
),
1729 } else if (!VALID_STAT(smb_fname
->st
) &&
1730 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1731 /* Needed to show the msdfs symlinks as
1734 ms_dfs_link
= check_msdfs_link(state
->conn
,
1737 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1738 "Couldn't stat [%s] (%s)\n",
1739 smb_fname_str_dbg(smb_fname
),
1744 *_mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1752 *_mode
= fdos_mode(smb_fname
->fsp
);
1753 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1758 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1759 connection_struct
*conn
,
1761 uint32_t info_level
,
1762 struct ea_list
*name_list
,
1763 bool check_mangled_names
,
1764 bool requires_resume_key
,
1767 const struct smb_filename
*smb_fname
,
1768 int space_remaining
,
1774 uint64_t *last_entry_off
)
1776 char *p
, *q
, *pdata
= *ppdata
;
1778 uint64_t file_size
= 0;
1779 uint64_t allocation_size
= 0;
1780 uint64_t file_id
= 0;
1782 struct timespec mdate_ts
= {0};
1783 struct timespec adate_ts
= {0};
1784 struct timespec cdate_ts
= {0};
1785 struct timespec create_date_ts
= {0};
1786 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1788 char *last_entry_ptr
;
1793 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1795 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1796 file_size
= get_file_size_stat(&smb_fname
->st
);
1798 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1800 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1801 if (!NT_STATUS_IS_OK(status
)) {
1802 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1807 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1809 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1810 adate_ts
= smb_fname
->st
.st_ex_atime
;
1811 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1812 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1814 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1815 dos_filetime_timespec(&create_date_ts
);
1816 dos_filetime_timespec(&mdate_ts
);
1817 dos_filetime_timespec(&adate_ts
);
1818 dos_filetime_timespec(&cdate_ts
);
1821 create_date
= convert_timespec_to_time_t(create_date_ts
);
1822 mdate
= convert_timespec_to_time_t(mdate_ts
);
1823 adate
= convert_timespec_to_time_t(adate_ts
);
1825 /* align the record */
1826 SMB_ASSERT(align
>= 1);
1828 off
= (int)PTR_DIFF(pdata
, base_data
);
1829 pad
= (off
+ (align
-1)) & ~(align
-1);
1832 if (pad
&& pad
> space_remaining
) {
1833 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1834 "for padding (wanted %u, had %d)\n",
1837 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1841 /* initialize padding to 0 */
1843 memset(pdata
, 0, pad
);
1845 space_remaining
-= pad
;
1847 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1857 switch (info_level
) {
1858 case SMB_FIND_INFO_STANDARD
:
1859 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1860 if(requires_resume_key
) {
1864 srv_put_dos_date2(p
,0,create_date
);
1865 srv_put_dos_date2(p
,4,adate
);
1866 srv_put_dos_date2(p
,8,mdate
);
1867 SIVAL(p
,12,(uint32_t)file_size
);
1868 SIVAL(p
,16,(uint32_t)allocation_size
);
1872 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1873 p
+= ucs2_align(base_data
, p
, 0);
1875 status
= srvstr_push(base_data
, flags2
, p
,
1876 fname
, PTR_DIFF(end_data
, p
),
1877 STR_TERMINATE
, &len
);
1878 if (!NT_STATUS_IS_OK(status
)) {
1881 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1883 SCVAL(nameptr
, -1, len
- 2);
1885 SCVAL(nameptr
, -1, 0);
1889 SCVAL(nameptr
, -1, len
- 1);
1891 SCVAL(nameptr
, -1, 0);
1897 case SMB_FIND_EA_SIZE
:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1899 if (requires_resume_key
) {
1903 srv_put_dos_date2(p
,0,create_date
);
1904 srv_put_dos_date2(p
,4,adate
);
1905 srv_put_dos_date2(p
,8,mdate
);
1906 SIVAL(p
,12,(uint32_t)file_size
);
1907 SIVAL(p
,16,(uint32_t)allocation_size
);
1910 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1911 SIVAL(p
,22,ea_size
); /* Extended attributes */
1915 status
= srvstr_push(base_data
, flags2
,
1916 p
, fname
, PTR_DIFF(end_data
, p
),
1917 STR_TERMINATE
| STR_NOALIGN
, &len
);
1918 if (!NT_STATUS_IS_OK(status
)) {
1921 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1934 SCVAL(nameptr
,0,len
);
1936 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1939 case SMB_FIND_EA_LIST
:
1941 struct ea_list
*file_list
= NULL
;
1944 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1946 return NT_STATUS_INVALID_PARAMETER
;
1948 if (requires_resume_key
) {
1952 srv_put_dos_date2(p
,0,create_date
);
1953 srv_put_dos_date2(p
,4,adate
);
1954 srv_put_dos_date2(p
,8,mdate
);
1955 SIVAL(p
,12,(uint32_t)file_size
);
1956 SIVAL(p
,16,(uint32_t)allocation_size
);
1958 p
+= 22; /* p now points to the EA area. */
1960 status
= get_ea_list_from_fsp(ctx
,
1962 &ea_len
, &file_list
);
1963 if (!NT_STATUS_IS_OK(status
)) {
1966 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1968 /* We need to determine if this entry will fit in the space available. */
1969 /* Max string size is 255 bytes. */
1970 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1971 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1972 "(wanted %u, had %d)\n",
1973 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1975 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1978 /* Push the ea_data followed by the name. */
1979 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1981 status
= srvstr_push(base_data
, flags2
,
1982 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1983 STR_TERMINATE
| STR_NOALIGN
, &len
);
1984 if (!NT_STATUS_IS_OK(status
)) {
1987 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
2000 SCVAL(nameptr
,0,len
);
2002 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
2006 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2008 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2010 SIVAL(p
,0,reskey
); p
+= 4;
2011 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2012 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2013 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2014 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2015 SOFF_T(p
,0,file_size
); p
+= 8;
2016 SOFF_T(p
,0,allocation_size
); p
+= 8;
2017 SIVAL(p
,0,mode
); p
+= 4;
2018 q
= p
; p
+= 4; /* q is placeholder for name length. */
2019 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2020 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2022 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2023 SIVAL(p
,0,ea_size
); /* Extended attributes */
2026 /* Clear the short name buffer. This is
2027 * IMPORTANT as not doing so will trigger
2028 * a Win2k client bug. JRA.
2030 if (!was_8_3
&& check_mangled_names
) {
2031 char mangled_name
[13]; /* mangled 8.3 name. */
2032 if (!name_to_8_3(fname
,mangled_name
,True
,
2034 /* Error - mangle failed ! */
2035 memset(mangled_name
,'\0',12);
2037 mangled_name
[12] = 0;
2038 status
= srvstr_push(base_data
, flags2
,
2039 p
+2, mangled_name
, 24,
2040 STR_UPPER
|STR_UNICODE
, &len
);
2041 if (!NT_STATUS_IS_OK(status
)) {
2045 memset(p
+ 2 + len
,'\0',24 - len
);
2052 status
= srvstr_push(base_data
, flags2
, p
,
2053 fname
, PTR_DIFF(end_data
, p
),
2054 STR_TERMINATE_ASCII
, &len
);
2055 if (!NT_STATUS_IS_OK(status
)) {
2061 len
= PTR_DIFF(p
, pdata
);
2062 pad
= (len
+ (align
-1)) & ~(align
-1);
2064 * offset to the next entry, the caller
2065 * will overwrite it for the last entry
2066 * that's why we always include the padding
2070 * set padding to zero
2073 memset(p
, 0, pad
- len
);
2080 case SMB_FIND_FILE_DIRECTORY_INFO
:
2081 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2083 SIVAL(p
,0,reskey
); p
+= 4;
2084 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2085 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2086 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2087 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2088 SOFF_T(p
,0,file_size
); p
+= 8;
2089 SOFF_T(p
,0,allocation_size
); p
+= 8;
2090 SIVAL(p
,0,mode
); p
+= 4;
2091 status
= srvstr_push(base_data
, flags2
,
2092 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
2093 STR_TERMINATE_ASCII
, &len
);
2094 if (!NT_STATUS_IS_OK(status
)) {
2100 len
= PTR_DIFF(p
, pdata
);
2101 pad
= (len
+ (align
-1)) & ~(align
-1);
2103 * offset to the next entry, the caller
2104 * will overwrite it for the last entry
2105 * that's why we always include the padding
2109 * set padding to zero
2112 memset(p
, 0, pad
- len
);
2119 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2120 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2122 SIVAL(p
,0,reskey
); p
+= 4;
2123 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2124 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2125 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2126 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2127 SOFF_T(p
,0,file_size
); p
+= 8;
2128 SOFF_T(p
,0,allocation_size
); p
+= 8;
2129 SIVAL(p
,0,mode
); p
+= 4;
2130 q
= p
; p
+= 4; /* q is placeholder for name length. */
2131 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2132 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2134 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2135 SIVAL(p
,0,ea_size
); /* Extended attributes */
2138 status
= srvstr_push(base_data
, flags2
, p
,
2139 fname
, PTR_DIFF(end_data
, p
),
2140 STR_TERMINATE_ASCII
, &len
);
2141 if (!NT_STATUS_IS_OK(status
)) {
2147 len
= PTR_DIFF(p
, pdata
);
2148 pad
= (len
+ (align
-1)) & ~(align
-1);
2150 * offset to the next entry, the caller
2151 * will overwrite it for the last entry
2152 * that's why we always include the padding
2156 * set padding to zero
2159 memset(p
, 0, pad
- len
);
2166 case SMB_FIND_FILE_NAMES_INFO
:
2167 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2169 SIVAL(p
,0,reskey
); p
+= 4;
2171 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2172 acl on a dir (tridge) */
2173 status
= srvstr_push(base_data
, flags2
, p
,
2174 fname
, PTR_DIFF(end_data
, p
),
2175 STR_TERMINATE_ASCII
, &len
);
2176 if (!NT_STATUS_IS_OK(status
)) {
2182 len
= PTR_DIFF(p
, pdata
);
2183 pad
= (len
+ (align
-1)) & ~(align
-1);
2185 * offset to the next entry, the caller
2186 * will overwrite it for the last entry
2187 * that's why we always include the padding
2191 * set padding to zero
2194 memset(p
, 0, pad
- len
);
2201 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2202 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2204 SIVAL(p
,0,reskey
); p
+= 4;
2205 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2206 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2207 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2208 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2209 SOFF_T(p
,0,file_size
); p
+= 8;
2210 SOFF_T(p
,0,allocation_size
); p
+= 8;
2211 SIVAL(p
,0,mode
); p
+= 4;
2212 q
= p
; p
+= 4; /* q is placeholder for name length. */
2213 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2214 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2216 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2217 SIVAL(p
,0,ea_size
); /* Extended attributes */
2220 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2221 SBVAL(p
,0,file_id
); p
+= 8;
2222 status
= srvstr_push(base_data
, flags2
, p
,
2223 fname
, PTR_DIFF(end_data
, p
),
2224 STR_TERMINATE_ASCII
, &len
);
2225 if (!NT_STATUS_IS_OK(status
)) {
2231 len
= PTR_DIFF(p
, pdata
);
2232 pad
= (len
+ (align
-1)) & ~(align
-1);
2234 * offset to the next entry, the caller
2235 * will overwrite it for the last entry
2236 * that's why we always include the padding
2240 * set padding to zero
2243 memset(p
, 0, pad
- len
);
2250 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2251 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2252 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2254 SIVAL(p
,0,reskey
); p
+= 4;
2255 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2256 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2257 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2258 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2259 SOFF_T(p
,0,file_size
); p
+= 8;
2260 SOFF_T(p
,0,allocation_size
); p
+= 8;
2261 SIVAL(p
,0,mode
); p
+= 4;
2262 q
= p
; p
+= 4; /* q is placeholder for name length */
2263 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2264 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2265 } else if (readdir_attr_data
&&
2266 readdir_attr_data
->type
== RDATTR_AAPL
) {
2268 * OS X specific SMB2 extension negotiated via
2269 * AAPL create context: return max_access in
2272 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2274 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2275 SIVAL(p
,0,ea_size
); /* Extended attributes */
2279 if (readdir_attr_data
&&
2280 readdir_attr_data
->type
== RDATTR_AAPL
) {
2282 * OS X specific SMB2 extension negotiated via
2283 * AAPL create context: return resource fork
2284 * length and compressed FinderInfo in
2287 * According to documentation short_name_len
2288 * should be 0, but on the wire behaviour
2289 * shows its set to 24 by clients.
2293 /* Resourefork length */
2294 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2296 /* Compressed FinderInfo */
2297 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2298 } else if (!was_8_3
&& check_mangled_names
) {
2299 char mangled_name
[13]; /* mangled 8.3 name. */
2300 if (!name_to_8_3(fname
,mangled_name
,True
,
2302 /* Error - mangle failed ! */
2303 memset(mangled_name
,'\0',12);
2305 mangled_name
[12] = 0;
2306 status
= srvstr_push(base_data
, flags2
,
2307 p
+2, mangled_name
, 24,
2308 STR_UPPER
|STR_UNICODE
, &len
);
2309 if (!NT_STATUS_IS_OK(status
)) {
2314 memset(p
+ 2 + len
,'\0',24 - len
);
2318 /* Clear the short name buffer. This is
2319 * IMPORTANT as not doing so will trigger
2320 * a Win2k client bug. JRA.
2327 if (readdir_attr_data
&&
2328 readdir_attr_data
->type
== RDATTR_AAPL
) {
2330 * OS X specific SMB2 extension negotiated via
2331 * AAPL create context: return UNIX mode in
2334 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2335 SSVAL(p
, 0, aapl_mode
);
2341 SBVAL(p
,0,file_id
); p
+= 8;
2342 status
= srvstr_push(base_data
, flags2
, p
,
2343 fname
, PTR_DIFF(end_data
, p
),
2344 STR_TERMINATE_ASCII
, &len
);
2345 if (!NT_STATUS_IS_OK(status
)) {
2351 len
= PTR_DIFF(p
, pdata
);
2352 pad
= (len
+ (align
-1)) & ~(align
-1);
2354 * offset to the next entry, the caller
2355 * will overwrite it for the last entry
2356 * that's why we always include the padding
2360 * set padding to zero
2363 memset(p
, 0, pad
- len
);
2370 /* CIFS UNIX Extension. */
2372 case SMB_FIND_FILE_UNIX
:
2373 case SMB_FIND_FILE_UNIX_INFO2
:
2375 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2377 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2379 if (info_level
== SMB_FIND_FILE_UNIX
) {
2380 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2381 p
= store_file_unix_basic(conn
, p
,
2382 NULL
, &smb_fname
->st
);
2383 status
= srvstr_push(base_data
, flags2
, p
,
2384 fname
, PTR_DIFF(end_data
, p
),
2385 STR_TERMINATE
, &len
);
2386 if (!NT_STATUS_IS_OK(status
)) {
2390 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2391 p
= store_file_unix_basic_info2(conn
, p
,
2392 NULL
, &smb_fname
->st
);
2395 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2396 PTR_DIFF(end_data
, p
), 0, &len
);
2397 if (!NT_STATUS_IS_OK(status
)) {
2400 SIVAL(nameptr
, 0, len
);
2405 len
= PTR_DIFF(p
, pdata
);
2406 pad
= (len
+ (align
-1)) & ~(align
-1);
2408 * offset to the next entry, the caller
2409 * will overwrite it for the last entry
2410 * that's why we always include the padding
2414 * set padding to zero
2417 memset(p
, 0, pad
- len
);
2422 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2427 return NT_STATUS_INVALID_LEVEL
;
2430 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2431 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2432 "(wanted %u, had %d)\n",
2433 (unsigned int)PTR_DIFF(p
,pdata
),
2435 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2438 /* Setup the last entry pointer, as an offset from base_data */
2439 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2440 /* Advance the data pointer to the next slot */
2443 return NT_STATUS_OK
;
2446 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2447 connection_struct
*conn
,
2448 struct dptr_struct
*dirptr
,
2450 const char *path_mask
,
2453 int requires_resume_key
,
2462 int space_remaining
,
2463 struct smb_filename
**_smb_fname
,
2464 bool *got_exact_match
,
2465 int *_last_entry_off
,
2466 struct ea_list
*name_list
,
2467 struct file_id
*file_id
)
2470 const char *mask
= NULL
;
2471 long prev_dirpos
= 0;
2474 struct smb_filename
*smb_fname
= NULL
;
2475 struct smbd_dirptr_lanman2_state state
;
2477 uint64_t last_entry_off
= 0;
2479 enum mangled_names_options mangled_names
;
2480 bool marshall_with_83_names
;
2482 mangled_names
= lp_mangled_names(conn
->params
);
2486 state
.info_level
= info_level
;
2487 if (mangled_names
!= MANGLED_NAMES_NO
) {
2488 state
.check_mangled_names
= true;
2490 state
.has_wild
= dptr_has_wild(dirptr
);
2491 state
.got_exact_match
= false;
2493 *got_exact_match
= false;
2495 p
= strrchr_m(path_mask
,'/');
2506 ok
= smbd_dirptr_get_entry(ctx
,
2513 smbd_dirptr_lanman2_match_fn
,
2514 smbd_dirptr_lanman2_mode_fn
,
2521 return NT_STATUS_END_OF_FILE
;
2524 *got_exact_match
= state
.got_exact_match
;
2526 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2528 status
= smbd_marshall_dir_entry(ctx
,
2533 marshall_with_83_names
,
2534 requires_resume_key
,
2545 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2546 DEBUG(1,("Conversion error: illegal character: %s\n",
2547 smb_fname_str_dbg(smb_fname
)));
2550 if (file_id
!= NULL
) {
2551 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2554 if (!NT_STATUS_IS_OK(status
) &&
2555 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2557 TALLOC_FREE(smb_fname
);
2562 if (_smb_fname
!= NULL
) {
2563 struct smb_filename
*name
= NULL
;
2565 name
= synthetic_smb_fname(ctx
,
2572 TALLOC_FREE(smb_fname
);
2574 return NT_STATUS_NO_MEMORY
;
2579 TALLOC_FREE(smb_fname
);
2582 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2583 dptr_SeekDir(dirptr
, prev_dirpos
);
2587 *_last_entry_off
= last_entry_off
;
2588 return NT_STATUS_OK
;
2591 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2592 connection_struct
*conn
,
2593 struct dptr_struct
*dirptr
,
2595 const char *path_mask
,
2598 bool requires_resume_key
,
2604 int space_remaining
,
2605 bool *got_exact_match
,
2606 int *last_entry_off
,
2607 struct ea_list
*name_list
)
2610 const bool do_pad
= true;
2612 if (info_level
>= 1 && info_level
<= 3) {
2613 /* No alignment on earlier info levels. */
2617 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2618 path_mask
, dirtype
, info_level
,
2619 requires_resume_key
, dont_descend
, ask_sharemode
,
2620 true, align
, do_pad
,
2621 ppdata
, base_data
, end_data
,
2625 last_entry_off
, name_list
, NULL
);
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDFIRST.
2630 ****************************************************************************/
2632 static void call_trans2findfirst(connection_struct
*conn
,
2633 struct smb_request
*req
,
2634 char **pparams
, int total_params
,
2635 char **ppdata
, int total_data
,
2636 unsigned int max_data_bytes
)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2643 struct smb_filename
*smb_dname
= NULL
;
2644 char *params
= *pparams
;
2645 char *pdata
= *ppdata
;
2649 uint16_t findfirst_flags
;
2650 bool close_after_first
;
2652 bool requires_resume_key
;
2654 char *directory
= NULL
;
2657 int last_entry_off
=0;
2661 bool finished
= False
;
2662 bool dont_descend
= False
;
2663 bool out_of_space
= False
;
2664 int space_remaining
;
2665 struct ea_list
*ea_list
= NULL
;
2666 NTSTATUS ntstatus
= NT_STATUS_OK
;
2667 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
2668 struct smbd_server_connection
*sconn
= req
->sconn
;
2669 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
2670 ucf_flags_from_smb_request(req
);
2671 bool backup_priv
= false;
2672 bool as_root
= false;
2673 files_struct
*fsp
= NULL
;
2674 const struct loadparm_substitution
*lp_sub
=
2675 loadparm_s3_global_substitution();
2678 if (total_params
< 13) {
2679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2683 dirtype
= SVAL(params
,0);
2684 maxentries
= SVAL(params
,2);
2685 findfirst_flags
= SVAL(params
,4);
2686 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2687 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2688 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2689 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2690 security_token_has_privilege(get_current_nttok(conn
),
2693 info_level
= SVAL(params
,6);
2695 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2696 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2697 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2699 info_level
, max_data_bytes
));
2702 /* W2K3 seems to treat zero as 1. */
2706 switch (info_level
) {
2707 case SMB_FIND_INFO_STANDARD
:
2708 case SMB_FIND_EA_SIZE
:
2709 case SMB_FIND_EA_LIST
:
2710 case SMB_FIND_FILE_DIRECTORY_INFO
:
2711 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2712 case SMB_FIND_FILE_NAMES_INFO
:
2713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2714 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2715 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2717 case SMB_FIND_FILE_UNIX
:
2718 case SMB_FIND_FILE_UNIX_INFO2
:
2719 if (!lp_unix_extensions()) {
2720 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2725 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2729 if (req
->posix_pathnames
) {
2730 /* Always use filesystem for UNIX mtime query. */
2731 ask_sharemode
= false;
2734 if (req
->posix_pathnames
) {
2735 srvstr_get_path_posix(talloc_tos(),
2744 srvstr_get_path(talloc_tos(),
2753 if (!NT_STATUS_IS_OK(ntstatus
)) {
2754 reply_nterror(req
, ntstatus
);
2761 ntstatus
= filename_convert_with_privilege(talloc_tos(),
2768 ntstatus
= filename_convert(talloc_tos(), conn
,
2775 if (!NT_STATUS_IS_OK(ntstatus
)) {
2776 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2777 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2778 ERRSRV
, ERRbadpath
);
2781 reply_nterror(req
, ntstatus
);
2786 * The above call to filename_convert() is on the path from the client
2787 * including the search mask. Until the code that chops of the search
2788 * mask from the path below is moved before the call to
2789 * filename_convert(), we close a possible pathref fsp to ensure
2790 * SMB_VFS_CREATE_FILE() below will internally open a pathref fsp on the
2793 if (smb_dname
->fsp
!= NULL
) {
2794 ntstatus
= fd_close(smb_dname
->fsp
);
2795 if (!NT_STATUS_IS_OK(ntstatus
)) {
2796 reply_nterror(req
, ntstatus
);
2800 * The pathref fsp link destructor will set smb_dname->fsp to
2801 * NULL. Turning this into an assert to give a hint at readers
2802 * of the code trying to understand the mechanics.
2804 file_free(req
, smb_dname
->fsp
);
2805 SMB_ASSERT(smb_dname
->fsp
== NULL
);
2808 mask
= get_original_lcomp(talloc_tos(),
2813 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2817 directory
= smb_dname
->base_name
;
2819 p
= strrchr_m(directory
,'/');
2821 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2822 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2823 mask
= talloc_strdup(talloc_tos(),"*");
2825 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2833 if (p
== NULL
|| p
== directory
) {
2834 struct smb_filename
*old_name
= smb_dname
;
2836 /* Ensure we don't have a directory name of "". */
2837 smb_dname
= synthetic_smb_fname(talloc_tos(),
2843 TALLOC_FREE(old_name
);
2844 if (smb_dname
== NULL
) {
2845 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2848 directory
= smb_dname
->base_name
;
2851 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2853 if (info_level
== SMB_FIND_EA_LIST
) {
2856 if (total_data
< 4) {
2857 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2861 ea_size
= IVAL(pdata
,0);
2862 if (ea_size
!= total_data
) {
2863 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2864 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2869 if (!lp_ea_support(SNUM(conn
))) {
2870 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2874 /* Pull out the list of names. */
2875 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
2877 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2882 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2883 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2887 *ppdata
= (char *)SMB_REALLOC(
2888 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2889 if(*ppdata
== NULL
) {
2890 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2894 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2896 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2899 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2900 /* Realloc the params space */
2901 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2902 if (*pparams
== NULL
) {
2903 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2909 * As we've cut off the last component from
2910 * smb_fname we need to re-stat smb_dname
2911 * so FILE_OPEN disposition knows the directory
2914 ret
= vfs_stat(conn
, smb_dname
);
2916 ntstatus
= map_nt_error_from_unix(errno
);
2917 reply_nterror(req
, ntstatus
);
2921 ntstatus
= openat_pathref_fsp(conn
->cwd_fsp
, smb_dname
);
2922 if (!NT_STATUS_IS_OK(ntstatus
)) {
2923 reply_nterror(req
, ntstatus
);
2928 * Open an fsp on this directory for the dptr.
2930 ntstatus
= SMB_VFS_CREATE_FILE(
2933 smb_dname
, /* dname */
2934 FILE_LIST_DIRECTORY
, /* access_mask */
2936 FILE_SHARE_WRITE
, /* share_access */
2937 FILE_OPEN
, /* create_disposition*/
2938 FILE_DIRECTORY_FILE
, /* create_options */
2939 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
2940 NO_OPLOCK
, /* oplock_request */
2942 0, /* allocation_size */
2943 0, /* private_flags */
2948 NULL
, /* in_context */
2949 NULL
);/* out_context */
2951 if (!NT_STATUS_IS_OK(ntstatus
)) {
2952 DBG_ERR("failed to open directory %s\n",
2953 smb_fname_str_dbg(smb_dname
));
2954 reply_nterror(req
, ntstatus
);
2958 /* Save the wildcard match and attribs we are using on this directory -
2959 needed as lanman2 assumes these are being saved between calls */
2961 ntstatus
= dptr_create(conn
,
2971 if (!NT_STATUS_IS_OK(ntstatus
)) {
2973 * Use NULL here for the first parameter (req)
2974 * as this is not a client visible handle so
2975 * can'tbe part of an SMB1 chain.
2977 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2979 reply_nterror(req
, ntstatus
);
2984 /* Remember this in case we have
2985 to do a findnext. */
2986 dptr_set_priv(fsp
->dptr
);
2989 dptr_num
= dptr_dnum(fsp
->dptr
);
2990 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2992 /* We don't need to check for VOL here as this is returned by
2993 a different TRANS2 call. */
2995 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2996 directory
,lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
))));
2997 if (in_list(directory
,
2998 lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
)),
2999 conn
->case_sensitive
)) {
3000 dont_descend
= True
;
3004 space_remaining
= max_data_bytes
;
3005 out_of_space
= False
;
3007 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
3008 bool got_exact_match
= False
;
3010 /* this is a heuristic to avoid seeking the dirptr except when
3011 absolutely necessary. It allows for a filename of about 40 chars */
3012 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3013 out_of_space
= True
;
3016 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
3020 mask
,dirtype
,info_level
,
3021 requires_resume_key
,dont_descend
,
3026 &last_entry_off
, ea_list
);
3027 if (NT_STATUS_EQUAL(ntstatus
,
3028 NT_STATUS_ILLEGAL_CHARACTER
)) {
3030 * Bad character conversion on name. Ignore this
3035 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3036 out_of_space
= true;
3038 finished
= !NT_STATUS_IS_OK(ntstatus
);
3042 if (!finished
&& !out_of_space
)
3046 * As an optimisation if we know we aren't looking
3047 * for a wildcard name (ie. the name matches the wildcard exactly)
3048 * then we can finish on any (first) match.
3049 * This speeds up large directory searches. JRA.
3055 /* Ensure space_remaining never goes -ve. */
3056 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
3057 space_remaining
= 0;
3058 out_of_space
= true;
3060 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3064 /* Check if we can close the dirptr */
3065 if(close_after_first
|| (finished
&& close_if_end
)) {
3066 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
3068 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3073 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3074 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3075 * the protocol level is less than NT1. Tested with smbclient. JRA.
3076 * This should fix the OS/2 client bug #2335.
3079 if(numentries
== 0) {
3082 * We may have already closed the file in the
3083 * close_after_first or finished case above.
3086 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3089 if (get_Protocol() < PROTOCOL_NT1
) {
3090 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
3093 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
3094 ERRDOS
, ERRbadfile
);
3099 /* At this point pdata points to numentries directory entries. */
3101 /* Set up the return parameter block */
3102 SSVAL(params
,0,dptr_num
);
3103 SSVAL(params
,2,numentries
);
3104 SSVAL(params
,4,finished
);
3105 SSVAL(params
,6,0); /* Never an EA error */
3106 SSVAL(params
,8,last_entry_off
);
3108 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
3111 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
3112 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
3114 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3118 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3119 smb_fn_name(req
->cmd
),
3120 mask
, directory
, dirtype
, numentries
) );
3123 * Force a name mangle here to ensure that the
3124 * mask as an 8.3 name is top of the mangled cache.
3125 * The reasons for this are subtle. Don't remove
3126 * this code unless you know what you are doing
3127 * (see PR#13758). JRA.
3130 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
3131 char mangled_name
[13];
3132 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
3140 TALLOC_FREE(smb_dname
);
3144 /****************************************************************************
3145 Reply to a TRANS2_FINDNEXT.
3146 ****************************************************************************/
3148 static void call_trans2findnext(connection_struct
*conn
,
3149 struct smb_request
*req
,
3150 char **pparams
, int total_params
,
3151 char **ppdata
, int total_data
,
3152 unsigned int max_data_bytes
)
3154 /* We must be careful here that we don't return more than the
3155 allowed number of data bytes. If this means returning fewer than
3156 maxentries then so be it. We assume that the redirector has
3157 enough room for the fixed number of parameter bytes it has
3159 char *params
= *pparams
;
3160 char *pdata
= *ppdata
;
3164 uint16_t info_level
;
3165 uint32_t resume_key
;
3166 uint16_t findnext_flags
;
3167 bool close_after_request
;
3169 bool requires_resume_key
;
3171 char *resume_name
= NULL
;
3172 const char *mask
= NULL
;
3173 const char *directory
= NULL
;
3177 int i
, last_entry_off
=0;
3178 bool finished
= False
;
3179 bool dont_descend
= False
;
3180 bool out_of_space
= False
;
3181 int space_remaining
;
3182 struct ea_list
*ea_list
= NULL
;
3183 NTSTATUS ntstatus
= NT_STATUS_OK
;
3184 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
3185 TALLOC_CTX
*ctx
= talloc_tos();
3186 struct smbd_server_connection
*sconn
= req
->sconn
;
3187 bool backup_priv
= false;
3188 bool as_root
= false;
3189 files_struct
*fsp
= NULL
;
3190 const struct loadparm_substitution
*lp_sub
=
3191 loadparm_s3_global_substitution();
3193 if (total_params
< 13) {
3194 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3198 dptr_num
= SVAL(params
,0);
3199 maxentries
= SVAL(params
,2);
3200 info_level
= SVAL(params
,4);
3201 resume_key
= IVAL(params
,6);
3202 findnext_flags
= SVAL(params
,10);
3203 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
3204 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
3205 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
3206 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
3208 if (!continue_bit
) {
3209 /* We only need resume_name if continue_bit is zero. */
3210 if (req
->posix_pathnames
) {
3211 srvstr_get_path_posix(ctx
,
3220 srvstr_get_path(ctx
,
3229 if (!NT_STATUS_IS_OK(ntstatus
)) {
3230 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3231 complain (it thinks we're asking for the directory above the shared
3232 path or an invalid name). Catch this as the resume name is only compared, never used in
3233 a file access. JRA. */
3234 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
3235 &resume_name
, params
+12,
3239 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
3240 reply_nterror(req
, ntstatus
);
3246 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3247 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3248 resume_key = %d resume name = %s continue=%d level = %d\n",
3249 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
3250 requires_resume_key
, resume_key
,
3251 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
3254 /* W2K3 seems to treat zero as 1. */
3258 switch (info_level
) {
3259 case SMB_FIND_INFO_STANDARD
:
3260 case SMB_FIND_EA_SIZE
:
3261 case SMB_FIND_EA_LIST
:
3262 case SMB_FIND_FILE_DIRECTORY_INFO
:
3263 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
3264 case SMB_FIND_FILE_NAMES_INFO
:
3265 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
3266 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
3267 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
3269 case SMB_FIND_FILE_UNIX
:
3270 case SMB_FIND_FILE_UNIX_INFO2
:
3271 /* Always use filesystem for UNIX mtime query. */
3272 ask_sharemode
= false;
3273 if (!lp_unix_extensions()) {
3274 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3279 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3283 if (info_level
== SMB_FIND_EA_LIST
) {
3286 if (total_data
< 4) {
3287 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3291 ea_size
= IVAL(pdata
,0);
3292 if (ea_size
!= total_data
) {
3293 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3294 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3295 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3299 if (!lp_ea_support(SNUM(conn
))) {
3300 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
3304 /* Pull out the list of names. */
3305 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3307 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3312 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3313 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3317 *ppdata
= (char *)SMB_REALLOC(
3318 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3319 if(*ppdata
== NULL
) {
3320 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3325 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3328 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3331 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3332 /* Realloc the params space */
3333 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3334 if(*pparams
== NULL
) {
3335 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3341 /* Check that the dptr is valid */
3342 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
3344 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3348 directory
= dptr_path(sconn
, dptr_num
);
3350 /* Get the wildcard mask from the dptr */
3351 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3352 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3353 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3357 /* Get the attr mask from the dptr */
3358 dirtype
= dptr_attr(sconn
, dptr_num
);
3360 backup_priv
= dptr_get_priv(fsp
->dptr
);
3362 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3363 "backup_priv = %d\n",
3364 dptr_num
, mask
, dirtype
,
3366 dptr_TellDir(fsp
->dptr
),
3369 /* We don't need to check for VOL here as this is returned by
3370 a different TRANS2 call. */
3372 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3373 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
3374 if (in_list(directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),conn
->case_sensitive
))
3375 dont_descend
= True
;
3378 space_remaining
= max_data_bytes
;
3379 out_of_space
= False
;
3387 * Seek to the correct position. We no longer use the resume key but
3388 * depend on the last file name instead.
3391 if(!continue_bit
&& resume_name
&& *resume_name
) {
3394 long current_pos
= 0;
3396 * Remember, name_to_8_3 is called by
3397 * get_lanman2_dir_entry(), so the resume name
3398 * could be mangled. Ensure we check the unmangled name.
3401 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3402 char *new_resume_name
= NULL
;
3403 mangle_lookup_name_from_8_3(ctx
,
3407 if (new_resume_name
) {
3408 resume_name
= new_resume_name
;
3413 * Fix for NT redirector problem triggered by resume key indexes
3414 * changing between directory scans. We now return a resume key of 0
3415 * and instead look for the filename to continue from (also given
3416 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3417 * findfirst/findnext (as is usual) then the directory pointer
3418 * should already be at the correct place.
3421 finished
= !dptr_SearchDir(fsp
->dptr
, resume_name
, ¤t_pos
, &st
);
3422 } /* end if resume_name && !continue_bit */
3424 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3425 bool got_exact_match
= False
;
3427 /* this is a heuristic to avoid seeking the fsp->dptr except when
3428 absolutely necessary. It allows for a filename of about 40 chars */
3429 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3430 out_of_space
= True
;
3433 ntstatus
= get_lanman2_dir_entry(ctx
,
3437 mask
,dirtype
,info_level
,
3438 requires_resume_key
,dont_descend
,
3443 &last_entry_off
, ea_list
);
3444 if (NT_STATUS_EQUAL(ntstatus
,
3445 NT_STATUS_ILLEGAL_CHARACTER
)) {
3447 * Bad character conversion on name. Ignore this
3452 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3453 out_of_space
= true;
3455 finished
= !NT_STATUS_IS_OK(ntstatus
);
3459 if (!finished
&& !out_of_space
)
3463 * As an optimisation if we know we aren't looking
3464 * for a wildcard name (ie. the name matches the wildcard exactly)
3465 * then we can finish on any (first) match.
3466 * This speeds up large directory searches. JRA.
3472 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3475 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3476 smb_fn_name(req
->cmd
),
3477 mask
, directory
, dirtype
, numentries
) );
3479 /* Check if we can close the fsp->dptr */
3480 if(close_after_request
|| (finished
&& close_if_end
)) {
3481 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3483 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3491 /* Set up the return parameter block */
3492 SSVAL(params
,0,numentries
);
3493 SSVAL(params
,2,finished
);
3494 SSVAL(params
,4,0); /* Never an EA error */
3495 SSVAL(params
,6,last_entry_off
);
3497 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3503 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3505 const struct loadparm_substitution
*lp_sub
=
3506 loadparm_s3_global_substitution();
3508 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
3512 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3514 SMB_ASSERT(extended_info
!= NULL
);
3516 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3517 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3518 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3519 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3520 #ifdef SAMBA_VERSION_REVISION
3521 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3523 extended_info
->samba_subversion
= 0;
3524 #ifdef SAMBA_VERSION_RC_RELEASE
3525 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3527 #ifdef SAMBA_VERSION_PRE_RELEASE
3528 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3531 #ifdef SAMBA_VERSION_VENDOR_PATCH
3532 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3534 extended_info
->samba_gitcommitdate
= 0;
3535 #ifdef SAMBA_VERSION_COMMIT_TIME
3536 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3539 memset(extended_info
->samba_version_string
, 0,
3540 sizeof(extended_info
->samba_version_string
));
3542 snprintf (extended_info
->samba_version_string
,
3543 sizeof(extended_info
->samba_version_string
),
3544 "%s", samba_version_string());
3547 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3548 connection_struct
*conn
,
3549 TALLOC_CTX
*mem_ctx
,
3550 uint16_t info_level
,
3552 unsigned int max_data_bytes
,
3553 size_t *fixed_portion
,
3554 struct smb_filename
*fname
,
3558 const struct loadparm_substitution
*lp_sub
=
3559 loadparm_s3_global_substitution();
3560 char *pdata
, *end_data
;
3563 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3564 int snum
= SNUM(conn
);
3565 const char *fstype
= lp_fstype(SNUM(conn
));
3566 const char *filename
= NULL
;
3567 const uint64_t bytes_per_sector
= 512;
3568 uint32_t additional_flags
= 0;
3569 struct smb_filename smb_fname
;
3571 NTSTATUS status
= NT_STATUS_OK
;
3574 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3577 filename
= fname
->base_name
;
3581 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3582 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3583 "info level (0x%x) on IPC$.\n",
3584 (unsigned int)info_level
));
3585 return NT_STATUS_ACCESS_DENIED
;
3589 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3591 smb_fname
= (struct smb_filename
) {
3592 .base_name
= discard_const_p(char, filename
),
3593 .flags
= fname
? fname
->flags
: 0,
3594 .twrp
= fname
? fname
->twrp
: 0,
3597 if(info_level
!= SMB_FS_QUOTA_INFORMATION
3598 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3599 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3600 return map_nt_error_from_unix(errno
);
3605 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3606 return NT_STATUS_INVALID_PARAMETER
;
3609 *ppdata
= (char *)SMB_REALLOC(
3610 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3611 if (*ppdata
== NULL
) {
3612 return NT_STATUS_NO_MEMORY
;
3616 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3617 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3621 switch (info_level
) {
3622 case SMB_INFO_ALLOCATION
:
3624 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3626 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3628 if (df_ret
== (uint64_t)-1) {
3629 return map_nt_error_from_unix(errno
);
3632 block_size
= lp_block_size(snum
);
3633 if (bsize
< block_size
) {
3634 uint64_t factor
= block_size
/bsize
;
3639 if (bsize
> block_size
) {
3640 uint64_t factor
= bsize
/block_size
;
3645 sectors_per_unit
= bsize
/bytes_per_sector
;
3647 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3648 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3649 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3652 * For large drives, return max values and not modulo.
3654 dsize
= MIN(dsize
, UINT32_MAX
);
3655 dfree
= MIN(dfree
, UINT32_MAX
);
3657 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3658 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3659 SIVAL(pdata
,l1_cUnit
,dsize
);
3660 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3661 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3665 case SMB_INFO_VOLUME
:
3666 /* Return volume name */
3668 * Add volume serial number - hash of a combination of
3669 * the called hostname and the service name.
3671 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3673 * Win2k3 and previous mess this up by sending a name length
3674 * one byte short. I believe only older clients (OS/2 Win9x) use
3675 * this call so try fixing this by adding a terminating null to
3676 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3678 status
= srvstr_push(
3680 pdata
+l2_vol_szVolLabel
, vname
,
3681 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3682 STR_NOALIGN
|STR_TERMINATE
, &len
);
3683 if (!NT_STATUS_IS_OK(status
)) {
3686 SCVAL(pdata
,l2_vol_cch
,len
);
3687 data_len
= l2_vol_szVolLabel
+ len
;
3688 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3689 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3690 (unsigned)len
, vname
));
3693 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3694 case SMB_FS_ATTRIBUTE_INFORMATION
:
3696 additional_flags
= 0;
3697 #if defined(HAVE_SYS_QUOTAS)
3698 additional_flags
|= FILE_VOLUME_QUOTAS
;
3701 if(lp_nt_acl_support(SNUM(conn
))) {
3702 additional_flags
|= FILE_PERSISTENT_ACLS
;
3705 /* Capabilities are filled in at connection time through STATVFS call */
3706 additional_flags
|= conn
->fs_capabilities
;
3707 additional_flags
|= lp_parm_int(conn
->params
->service
,
3708 "share", "fake_fscaps",
3711 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3712 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3713 additional_flags
); /* FS ATTRIBUTES */
3715 SIVAL(pdata
,4,255); /* Max filename component length */
3716 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3717 and will think we can't do long filenames */
3718 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3719 PTR_DIFF(end_data
, pdata
+12),
3721 if (!NT_STATUS_IS_OK(status
)) {
3725 data_len
= 12 + len
;
3726 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3727 /* the client only requested a portion of the
3729 data_len
= max_data_bytes
;
3730 status
= STATUS_BUFFER_OVERFLOW
;
3732 *fixed_portion
= 16;
3735 case SMB_QUERY_FS_LABEL_INFO
:
3736 case SMB_FS_LABEL_INFORMATION
:
3737 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3738 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3739 if (!NT_STATUS_IS_OK(status
)) {
3746 case SMB_QUERY_FS_VOLUME_INFO
:
3747 case SMB_FS_VOLUME_INFORMATION
:
3750 * Add volume serial number - hash of a combination of
3751 * the called hostname and the service name.
3753 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
3754 (str_checksum(get_local_machine_name())<<16));
3756 /* Max label len is 32 characters. */
3757 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3758 PTR_DIFF(end_data
, pdata
+18),
3760 if (!NT_STATUS_IS_OK(status
)) {
3763 SIVAL(pdata
,12,len
);
3766 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3767 (int)strlen(vname
),vname
,
3768 lp_servicename(talloc_tos(), lp_sub
, snum
)));
3769 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3770 /* the client only requested a portion of the
3772 data_len
= max_data_bytes
;
3773 status
= STATUS_BUFFER_OVERFLOW
;
3775 *fixed_portion
= 24;
3778 case SMB_QUERY_FS_SIZE_INFO
:
3779 case SMB_FS_SIZE_INFORMATION
:
3781 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3783 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3785 if (df_ret
== (uint64_t)-1) {
3786 return map_nt_error_from_unix(errno
);
3788 block_size
= lp_block_size(snum
);
3789 if (bsize
< block_size
) {
3790 uint64_t factor
= block_size
/bsize
;
3795 if (bsize
> block_size
) {
3796 uint64_t factor
= bsize
/block_size
;
3801 sectors_per_unit
= bsize
/bytes_per_sector
;
3802 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3803 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3804 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3805 SBIG_UINT(pdata
,0,dsize
);
3806 SBIG_UINT(pdata
,8,dfree
);
3807 SIVAL(pdata
,16,sectors_per_unit
);
3808 SIVAL(pdata
,20,bytes_per_sector
);
3809 *fixed_portion
= 24;
3813 case SMB_FS_FULL_SIZE_INFORMATION
:
3815 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3817 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3819 if (df_ret
== (uint64_t)-1) {
3820 return map_nt_error_from_unix(errno
);
3822 block_size
= lp_block_size(snum
);
3823 if (bsize
< block_size
) {
3824 uint64_t factor
= block_size
/bsize
;
3829 if (bsize
> block_size
) {
3830 uint64_t factor
= bsize
/block_size
;
3835 sectors_per_unit
= bsize
/bytes_per_sector
;
3836 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3837 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3838 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3839 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3840 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3841 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3842 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3843 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3844 *fixed_portion
= 32;
3848 case SMB_QUERY_FS_DEVICE_INFO
:
3849 case SMB_FS_DEVICE_INFORMATION
:
3851 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3853 if (!CAN_WRITE(conn
)) {
3854 characteristics
|= FILE_READ_ONLY_DEVICE
;
3857 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3858 SIVAL(pdata
,4,characteristics
);
3863 #ifdef HAVE_SYS_QUOTAS
3864 case SMB_FS_QUOTA_INFORMATION
:
3866 * what we have to send --metze:
3868 * Unknown1: 24 NULL bytes
3869 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3870 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3871 * Quota Flags: 2 byte :
3872 * Unknown3: 6 NULL bytes
3876 * details for Quota Flags:
3878 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3879 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3880 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3881 * 0x0001 Enable Quotas: enable quota for this fs
3885 /* we need to fake up a fsp here,
3886 * because its not send in this call
3889 SMB_NTQUOTA_STRUCT quotas
;
3892 ZERO_STRUCT(quotas
);
3895 fsp
.fnum
= FNUM_FIELD_INVALID
;
3898 if (get_current_uid(conn
) != 0) {
3899 DEBUG(0,("get_user_quota: access_denied "
3900 "service [%s] user [%s]\n",
3901 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
3902 conn
->session_info
->unix_info
->unix_name
));
3903 return NT_STATUS_ACCESS_DENIED
;
3906 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
3908 if (!NT_STATUS_IS_OK(status
)) {
3909 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
3915 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3916 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
3918 /* Unknown1 24 NULL bytes*/
3919 SBIG_UINT(pdata
,0,(uint64_t)0);
3920 SBIG_UINT(pdata
,8,(uint64_t)0);
3921 SBIG_UINT(pdata
,16,(uint64_t)0);
3923 /* Default Soft Quota 8 bytes */
3924 SBIG_UINT(pdata
,24,quotas
.softlim
);
3926 /* Default Hard Quota 8 bytes */
3927 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3929 /* Quota flag 2 bytes */
3930 SSVAL(pdata
,40,quotas
.qflags
);
3932 /* Unknown3 6 NULL bytes */
3938 #endif /* HAVE_SYS_QUOTAS */
3939 case SMB_FS_OBJECTID_INFORMATION
:
3941 unsigned char objid
[16];
3942 struct smb_extended_info extended_info
;
3943 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3944 samba_extended_info_version (&extended_info
);
3945 SIVAL(pdata
,16,extended_info
.samba_magic
);
3946 SIVAL(pdata
,20,extended_info
.samba_version
);
3947 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3948 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3949 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3954 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3958 * These values match a physical Windows Server 2012
3959 * share backed by NTFS atop spinning rust.
3961 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3962 /* logical_bytes_per_sector */
3963 SIVAL(pdata
, 0, bytes_per_sector
);
3964 /* phys_bytes_per_sector_atomic */
3965 SIVAL(pdata
, 4, bytes_per_sector
);
3966 /* phys_bytes_per_sector_perf */
3967 SIVAL(pdata
, 8, bytes_per_sector
);
3968 /* fs_effective_phys_bytes_per_sector_atomic */
3969 SIVAL(pdata
, 12, bytes_per_sector
);
3971 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3972 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3973 /* byte_off_sector_align */
3974 SIVAL(pdata
, 20, 0);
3975 /* byte_off_partition_align */
3976 SIVAL(pdata
, 24, 0);
3977 *fixed_portion
= 28;
3983 * Query the version and capabilities of the CIFS UNIX extensions
3987 case SMB_QUERY_CIFS_UNIX_INFO
:
3989 bool large_write
= lp_min_receive_file_size() &&
3990 !srv_is_signing_active(xconn
);
3991 bool large_read
= !srv_is_signing_active(xconn
);
3992 int encrypt_caps
= 0;
3994 if (!lp_unix_extensions()) {
3995 return NT_STATUS_INVALID_LEVEL
;
3998 switch (conn
->encrypt_level
) {
3999 case SMB_SIGNING_OFF
:
4002 case SMB_SIGNING_DESIRED
:
4003 case SMB_SIGNING_IF_REQUIRED
:
4004 case SMB_SIGNING_DEFAULT
:
4005 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
4007 case SMB_SIGNING_REQUIRED
:
4008 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
4009 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
4010 large_write
= false;
4016 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
4017 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
4019 /* We have POSIX ACLs, pathname, encryption,
4020 * large read/write, and locking capability. */
4022 SBIG_UINT(pdata
,4,((uint64_t)(
4023 CIFS_UNIX_POSIX_ACLS_CAP
|
4024 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
4025 CIFS_UNIX_FCNTL_LOCKS_CAP
|
4026 CIFS_UNIX_EXTATTR_CAP
|
4027 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
4029 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
4031 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
4035 case SMB_QUERY_POSIX_FS_INFO
:
4038 vfs_statvfs_struct svfs
;
4040 if (!lp_unix_extensions()) {
4041 return NT_STATUS_INVALID_LEVEL
;
4044 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
4048 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
4049 SIVAL(pdata
,4,svfs
.BlockSize
);
4050 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
4051 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
4052 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
4053 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
4054 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
4055 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
4056 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4058 } else if (rc
== EOPNOTSUPP
) {
4059 return NT_STATUS_INVALID_LEVEL
;
4060 #endif /* EOPNOTSUPP */
4062 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4063 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
4068 case SMB_QUERY_POSIX_WHOAMI
:
4074 if (!lp_unix_extensions()) {
4075 return NT_STATUS_INVALID_LEVEL
;
4078 if (max_data_bytes
< 40) {
4079 return NT_STATUS_BUFFER_TOO_SMALL
;
4082 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
4083 flags
|= SMB_WHOAMI_GUEST
;
4086 /* NOTE: 8 bytes for UID/GID, irrespective of native
4087 * platform size. This matches
4088 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4090 data_len
= 4 /* flags */
4097 + 4 /* pad/reserved */
4098 + (conn
->session_info
->unix_token
->ngroups
* 8)
4100 + (conn
->session_info
->security_token
->num_sids
*
4104 SIVAL(pdata
, 0, flags
);
4105 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
4107 (uint64_t)conn
->session_info
->unix_token
->uid
);
4108 SBIG_UINT(pdata
, 16,
4109 (uint64_t)conn
->session_info
->unix_token
->gid
);
4112 if (data_len
>= max_data_bytes
) {
4113 /* Potential overflow, skip the GIDs and SIDs. */
4115 SIVAL(pdata
, 24, 0); /* num_groups */
4116 SIVAL(pdata
, 28, 0); /* num_sids */
4117 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
4118 SIVAL(pdata
, 36, 0); /* reserved */
4124 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
4125 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
4127 /* We walk the SID list twice, but this call is fairly
4128 * infrequent, and I don't expect that it's performance
4129 * sensitive -- jpeach
4131 for (i
= 0, sid_bytes
= 0;
4132 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4133 sid_bytes
+= ndr_size_dom_sid(
4134 &conn
->session_info
->security_token
->sids
[i
],
4138 /* SID list byte count */
4139 SIVAL(pdata
, 32, sid_bytes
);
4141 /* 4 bytes pad/reserved - must be zero */
4142 SIVAL(pdata
, 36, 0);
4146 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
4147 SBIG_UINT(pdata
, data_len
,
4148 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
4154 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4155 int sid_len
= ndr_size_dom_sid(
4156 &conn
->session_info
->security_token
->sids
[i
],
4159 sid_linearize((uint8_t *)(pdata
+ data_len
),
4161 &conn
->session_info
->security_token
->sids
[i
]);
4162 data_len
+= sid_len
;
4168 case SMB_MAC_QUERY_FS_INFO
:
4170 * Thursby MAC extension... ONLY on NTFS filesystems
4171 * once we do streams then we don't need this
4173 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
4175 SIVAL(pdata
,84,0x100); /* Don't support mac... */
4181 return NT_STATUS_INVALID_LEVEL
;
4184 *ret_data_len
= data_len
;
4188 static NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
4189 struct smb_request
*req
,
4191 const DATA_BLOB
*qdata
)
4193 const struct loadparm_substitution
*lp_sub
=
4194 loadparm_s3_global_substitution();
4196 SMB_NTQUOTA_STRUCT quotas
;
4198 ZERO_STRUCT(quotas
);
4201 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4202 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4203 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
4204 conn
->session_info
->unix_info
->unix_name
));
4205 return NT_STATUS_ACCESS_DENIED
;
4208 if (!check_fsp_ntquota_handle(conn
, req
,
4210 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4211 return NT_STATUS_INVALID_HANDLE
;
4214 /* note: normally there're 48 bytes,
4215 * but we didn't use the last 6 bytes for now
4218 if (qdata
->length
< 42) {
4219 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4220 (unsigned int)qdata
->length
));
4221 return NT_STATUS_INVALID_PARAMETER
;
4224 /* unknown_1 24 NULL bytes in pdata*/
4226 /* the soft quotas 8 bytes (uint64_t)*/
4227 quotas
.softlim
= BVAL(qdata
->data
,24);
4229 /* the hard quotas 8 bytes (uint64_t)*/
4230 quotas
.hardlim
= BVAL(qdata
->data
,32);
4232 /* quota_flags 2 bytes **/
4233 quotas
.qflags
= SVAL(qdata
->data
,40);
4235 /* unknown_2 6 NULL bytes follow*/
4237 /* now set the quotas */
4238 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4239 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4240 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4241 status
= map_nt_error_from_unix(errno
);
4243 status
= NT_STATUS_OK
;
4248 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
4249 struct smb_request
*req
,
4250 TALLOC_CTX
*mem_ctx
,
4251 uint16_t info_level
,
4253 const DATA_BLOB
*pdata
)
4255 switch (info_level
) {
4256 case SMB_FS_QUOTA_INFORMATION
:
4258 return smb_set_fsquota(conn
,
4267 return NT_STATUS_INVALID_LEVEL
;
4270 /****************************************************************************
4271 Reply to a TRANS2_QFSINFO (query filesystem info).
4272 ****************************************************************************/
4274 static void call_trans2qfsinfo(connection_struct
*conn
,
4275 struct smb_request
*req
,
4276 char **pparams
, int total_params
,
4277 char **ppdata
, int total_data
,
4278 unsigned int max_data_bytes
)
4280 char *params
= *pparams
;
4281 uint16_t info_level
;
4283 size_t fixed_portion
;
4286 if (total_params
< 2) {
4287 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4291 info_level
= SVAL(params
,0);
4293 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4294 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
4295 DEBUG(0,("call_trans2qfsinfo: encryption required "
4296 "and info level 0x%x sent.\n",
4297 (unsigned int)info_level
));
4298 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4303 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
4305 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
4312 if (!NT_STATUS_IS_OK(status
)) {
4313 reply_nterror(req
, status
);
4317 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
4320 DEBUG( 4, ( "%s info_level = %d\n",
4321 smb_fn_name(req
->cmd
), info_level
) );
4326 /****************************************************************************
4327 Reply to a TRANS2_SETFSINFO (set filesystem info).
4328 ****************************************************************************/
4330 static void call_trans2setfsinfo(connection_struct
*conn
,
4331 struct smb_request
*req
,
4332 char **pparams
, int total_params
,
4333 char **ppdata
, int total_data
,
4334 unsigned int max_data_bytes
)
4336 const struct loadparm_substitution
*lp_sub
=
4337 loadparm_s3_global_substitution();
4338 struct smbXsrv_connection
*xconn
= req
->xconn
;
4339 char *pdata
= *ppdata
;
4340 char *params
= *pparams
;
4341 uint16_t info_level
;
4343 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4344 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4347 if (total_params
< 4) {
4348 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4350 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4354 info_level
= SVAL(params
,2);
4357 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
4358 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
4359 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4360 "info level (0x%x) on IPC$.\n",
4361 (unsigned int)info_level
));
4362 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4367 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4368 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
4369 DEBUG(0,("call_trans2setfsinfo: encryption required "
4370 "and info level 0x%x sent.\n",
4371 (unsigned int)info_level
));
4372 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4377 switch(info_level
) {
4378 case SMB_SET_CIFS_UNIX_INFO
:
4379 if (!lp_unix_extensions()) {
4380 DEBUG(2,("call_trans2setfsinfo: "
4381 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4382 "unix extensions off\n"));
4384 NT_STATUS_INVALID_LEVEL
);
4388 /* There should be 12 bytes of capabilities set. */
4389 if (total_data
< 12) {
4392 NT_STATUS_INVALID_PARAMETER
);
4395 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
4396 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
4397 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
4398 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
4399 /* Just print these values for now. */
4400 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4401 "major = %u, minor = %u cap_low = 0x%x, "
4403 (unsigned int)xconn
->
4404 smb1
.unix_info
.client_major
,
4405 (unsigned int)xconn
->
4406 smb1
.unix_info
.client_minor
,
4407 (unsigned int)xconn
->
4408 smb1
.unix_info
.client_cap_low
,
4409 (unsigned int)xconn
->
4410 smb1
.unix_info
.client_cap_high
));
4412 /* Here is where we must switch to posix pathname processing... */
4413 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
4414 lp_set_posix_pathnames();
4415 mangle_change_to_posix();
4418 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
4419 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
4420 /* Client that knows how to do posix locks,
4421 * but not posix open/mkdir operations. Set a
4422 * default type for read/write checks. */
4424 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
4429 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4432 size_t param_len
= 0;
4433 size_t data_len
= total_data
;
4435 if (!lp_unix_extensions()) {
4438 NT_STATUS_INVALID_LEVEL
);
4442 if (lp_server_smb_encrypt(SNUM(conn
)) ==
4443 SMB_ENCRYPTION_OFF
) {
4446 NT_STATUS_NOT_SUPPORTED
);
4450 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4451 DEBUG( 2,("call_trans2setfsinfo: "
4452 "request transport encryption disabled"
4453 "with 'fork echo handler = yes'\n"));
4456 NT_STATUS_NOT_SUPPORTED
);
4460 DEBUG( 4,("call_trans2setfsinfo: "
4461 "request transport encryption.\n"));
4463 status
= srv_request_encryption_setup(conn
,
4464 (unsigned char **)ppdata
,
4466 (unsigned char **)pparams
,
4469 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4470 !NT_STATUS_IS_OK(status
)) {
4471 reply_nterror(req
, status
);
4475 send_trans2_replies(conn
, req
,
4483 if (NT_STATUS_IS_OK(status
)) {
4484 /* Server-side transport
4485 * encryption is now *on*. */
4486 status
= srv_encryption_start(conn
);
4487 if (!NT_STATUS_IS_OK(status
)) {
4488 char *reason
= talloc_asprintf(talloc_tos(),
4489 "Failure in setting "
4490 "up encrypted transport: %s",
4492 exit_server_cleanly(reason
);
4498 case SMB_FS_QUOTA_INFORMATION
:
4502 .data
= (uint8_t *)pdata
,
4503 .length
= total_data
4505 files_struct
*fsp
= NULL
;
4506 fsp
= file_fsp(req
, SVAL(params
,0));
4508 status
= smb_set_fsquota(conn
,
4512 if (!NT_STATUS_IS_OK(status
)) {
4513 reply_nterror(req
, status
);
4519 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4521 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4527 * sending this reply works fine,
4528 * but I'm not sure it's the same
4529 * like windows do...
4532 reply_outbuf(req
, 10, 0);
4535 #if defined(HAVE_POSIX_ACLS)
4536 /****************************************************************************
4537 Utility function to count the number of entries in a POSIX acl.
4538 ****************************************************************************/
4540 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4542 unsigned int ace_count
= 0;
4543 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4544 SMB_ACL_ENTRY_T entry
;
4546 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4548 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4549 entry_id
= SMB_ACL_NEXT_ENTRY
;
4556 /****************************************************************************
4557 Utility function to marshall a POSIX acl into wire format.
4558 ****************************************************************************/
4560 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4562 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4563 SMB_ACL_ENTRY_T entry
;
4565 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4566 SMB_ACL_TAG_T tagtype
;
4567 SMB_ACL_PERMSET_T permset
;
4568 unsigned char perms
= 0;
4569 unsigned int own_grp
;
4572 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4573 entry_id
= SMB_ACL_NEXT_ENTRY
;
4576 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4577 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4581 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4582 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4586 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4587 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4588 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4590 SCVAL(pdata
,1,perms
);
4593 case SMB_ACL_USER_OBJ
:
4594 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4595 own_grp
= (unsigned int)pst
->st_ex_uid
;
4596 SIVAL(pdata
,2,own_grp
);
4601 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4603 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4606 own_grp
= (unsigned int)*puid
;
4607 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4608 SIVAL(pdata
,2,own_grp
);
4612 case SMB_ACL_GROUP_OBJ
:
4613 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4614 own_grp
= (unsigned int)pst
->st_ex_gid
;
4615 SIVAL(pdata
,2,own_grp
);
4620 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4622 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4625 own_grp
= (unsigned int)*pgid
;
4626 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4627 SIVAL(pdata
,2,own_grp
);
4632 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4633 SIVAL(pdata
,2,0xFFFFFFFF);
4634 SIVAL(pdata
,6,0xFFFFFFFF);
4637 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4638 SIVAL(pdata
,2,0xFFFFFFFF);
4639 SIVAL(pdata
,6,0xFFFFFFFF);
4642 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4645 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4652 /****************************************************************************
4653 Store the FILE_UNIX_BASIC info.
4654 ****************************************************************************/
4656 static char *store_file_unix_basic(connection_struct
*conn
,
4659 const SMB_STRUCT_STAT
*psbuf
)
4663 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4664 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4666 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4669 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4672 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4673 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4674 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4677 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4681 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4685 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4688 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4689 devno
= psbuf
->st_ex_rdev
;
4691 devno
= psbuf
->st_ex_dev
;
4694 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4698 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4702 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
4705 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4709 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4716 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4717 * the chflags(2) (or equivalent) flags.
4719 * XXX: this really should be behind the VFS interface. To do this, we would
4720 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4721 * Each VFS module could then implement its own mapping as appropriate for the
4722 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4724 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4728 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4732 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4736 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4740 { UF_HIDDEN
, EXT_HIDDEN
},
4743 /* Do not remove. We need to guarantee that this array has at least one
4744 * entry to build on HP-UX.
4750 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4751 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4755 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4756 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4757 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4758 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4763 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4764 const uint32_t smb_fflags
,
4765 const uint32_t smb_fmask
,
4768 uint32_t max_fmask
= 0;
4771 *stat_fflags
= psbuf
->st_ex_flags
;
4773 /* For each flags requested in smb_fmask, check the state of the
4774 * corresponding flag in smb_fflags and set or clear the matching
4778 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4779 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4780 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4781 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4782 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4784 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4789 /* If smb_fmask is asking to set any bits that are not supported by
4790 * our flag mappings, we should fail.
4792 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4800 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4801 * of file flags and birth (create) time.
4803 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4806 const SMB_STRUCT_STAT
*psbuf
)
4808 uint32_t file_flags
= 0;
4809 uint32_t flags_mask
= 0;
4811 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4813 /* Create (birth) time 64 bit */
4814 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
4817 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4818 SIVAL(pdata
, 0, file_flags
); /* flags */
4819 SIVAL(pdata
, 4, flags_mask
); /* mask */
4825 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4826 const struct stream_struct
*streams
,
4828 unsigned int max_data_bytes
,
4829 unsigned int *data_size
)
4832 unsigned int ofs
= 0;
4834 if (max_data_bytes
< 32) {
4835 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4838 for (i
= 0; i
< num_streams
; i
++) {
4839 unsigned int next_offset
;
4841 smb_ucs2_t
*namebuf
;
4843 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4844 streams
[i
].name
, &namelen
) ||
4847 return NT_STATUS_INVALID_PARAMETER
;
4851 * name_buf is now null-terminated, we need to marshall as not
4858 * We cannot overflow ...
4860 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4861 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4863 TALLOC_FREE(namebuf
);
4864 return STATUS_BUFFER_OVERFLOW
;
4867 SIVAL(data
, ofs
+4, namelen
);
4868 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4869 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4870 memcpy(data
+ofs
+24, namebuf
, namelen
);
4871 TALLOC_FREE(namebuf
);
4873 next_offset
= ofs
+ 24 + namelen
;
4875 if (i
== num_streams
-1) {
4876 SIVAL(data
, ofs
, 0);
4879 unsigned int align
= ndr_align_size(next_offset
, 8);
4881 if ((next_offset
+ align
) > max_data_bytes
) {
4882 DEBUG(10, ("refusing to overflow align "
4883 "reply at stream %u\n",
4885 TALLOC_FREE(namebuf
);
4886 return STATUS_BUFFER_OVERFLOW
;
4889 memset(data
+next_offset
, 0, align
);
4890 next_offset
+= align
;
4892 SIVAL(data
, ofs
, next_offset
- ofs
);
4899 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4903 return NT_STATUS_OK
;
4906 static NTSTATUS
smb_unix_read_symlink(connection_struct
*conn
,
4907 struct smb_request
*req
,
4908 struct smb_filename
*smb_fname
,
4910 unsigned int data_size_in
,
4911 unsigned int *pdata_size_out
)
4916 struct smb_filename
*parent_fname
= NULL
;
4917 struct smb_filename
*base_name
= NULL
;
4919 char *buffer
= talloc_array(talloc_tos(), char, PATH_MAX
+1);
4922 return NT_STATUS_NO_MEMORY
;
4925 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
4926 smb_fname_str_dbg(smb_fname
));
4928 if(!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4929 TALLOC_FREE(buffer
);
4930 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4933 status
= parent_pathref(talloc_tos(),
4938 if (!NT_STATUS_IS_OK(status
)) {
4939 TALLOC_FREE(buffer
);
4943 link_len
= SMB_VFS_READLINKAT(conn
,
4949 TALLOC_FREE(parent_fname
);
4951 if (link_len
== -1) {
4952 TALLOC_FREE(buffer
);
4953 return map_nt_error_from_unix(errno
);
4956 buffer
[link_len
] = 0;
4957 status
= srvstr_push(pdata
,
4964 TALLOC_FREE(buffer
);
4965 if (!NT_STATUS_IS_OK(status
)) {
4968 *pdata_size_out
= len
;
4970 return NT_STATUS_OK
;
4973 #if defined(HAVE_POSIX_ACLS)
4974 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
4975 struct smb_request
*req
,
4977 struct smb_filename
*smb_fname
,
4979 unsigned int data_size_in
,
4980 unsigned int *pdata_size_out
)
4982 SMB_ACL_T file_acl
= NULL
;
4983 SMB_ACL_T def_acl
= NULL
;
4984 uint16_t num_file_acls
= 0;
4985 uint16_t num_def_acls
= 0;
4986 unsigned int size_needed
= 0;
4989 bool close_fsp
= false;
4992 * Ensure we always operate on a file descriptor, not just
4995 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4996 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
4997 FILE_READ_ATTRIBUTES
|
4998 FILE_WRITE_ATTRIBUTES
;
5000 status
= get_posix_fsp(conn
,
5006 if (!NT_STATUS_IS_OK(status
)) {
5012 SMB_ASSERT(fsp
!= NULL
);
5014 status
= refuse_symlink(conn
,
5017 if (!NT_STATUS_IS_OK(status
)) {
5021 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5024 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5025 DBG_INFO("ACLs not implemented on "
5026 "filesystem containing %s\n",
5028 status
= NT_STATUS_NOT_IMPLEMENTED
;
5032 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
5034 * We can only have default POSIX ACLs on
5037 if (!fsp
->fsp_flags
.is_directory
) {
5038 DBG_INFO("Non-directory open %s\n",
5040 status
= NT_STATUS_INVALID_HANDLE
;
5043 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
,
5045 SMB_ACL_TYPE_DEFAULT
,
5047 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5050 num_file_acls
= count_acl_entries(conn
, file_acl
);
5051 num_def_acls
= count_acl_entries(conn
, def_acl
);
5054 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
5055 status
= NT_STATUS_INVALID_PARAMETER
;
5059 size_needed
= num_file_acls
+ num_def_acls
;
5062 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5063 * than UINT_MAX, so check by division.
5065 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
5066 status
= NT_STATUS_INVALID_PARAMETER
;
5070 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
5071 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
5072 status
= NT_STATUS_INVALID_PARAMETER
;
5075 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
5077 if ( data_size_in
< size_needed
) {
5078 DBG_INFO("data_size too small (%u) need %u\n",
5081 status
= NT_STATUS_BUFFER_TOO_SMALL
;
5085 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5086 SSVAL(pdata
,2,num_file_acls
);
5087 SSVAL(pdata
,4,num_def_acls
);
5088 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
5090 ok
= marshall_posix_acl(conn
,
5095 status
= NT_STATUS_INTERNAL_ERROR
;
5098 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
5100 ok
= marshall_posix_acl(conn
,
5105 status
= NT_STATUS_INTERNAL_ERROR
;
5109 *pdata_size_out
= size_needed
;
5110 status
= NT_STATUS_OK
;
5116 * Ensure the stat struct in smb_fname is up to
5117 * date. Structure copy.
5119 smb_fname
->st
= fsp
->fsp_name
->st
;
5120 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
5124 TALLOC_FREE(file_acl
);
5125 TALLOC_FREE(def_acl
);
5130 /****************************************************************************
5131 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5132 ****************************************************************************/
5134 static void call_trans2qpipeinfo(connection_struct
*conn
,
5135 struct smb_request
*req
,
5136 unsigned int tran_call
,
5137 char **pparams
, int total_params
,
5138 char **ppdata
, int total_data
,
5139 unsigned int max_data_bytes
)
5141 char *params
= *pparams
;
5142 char *pdata
= *ppdata
;
5143 unsigned int data_size
= 0;
5144 unsigned int param_size
= 2;
5145 uint16_t info_level
;
5149 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5153 if (total_params
< 4) {
5154 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5158 fsp
= file_fsp(req
, SVAL(params
,0));
5159 if (!fsp_is_np(fsp
)) {
5160 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5164 info_level
= SVAL(params
,2);
5166 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5167 if (*pparams
== NULL
) {
5168 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5173 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5177 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5178 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5179 if (*ppdata
== NULL
) {
5180 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5185 switch (info_level
) {
5186 case SMB_FILE_STANDARD_INFORMATION
:
5188 SOFF_T(pdata
,0,4096LL);
5195 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5199 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5205 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
5206 TALLOC_CTX
*mem_ctx
,
5207 struct smb_request
*req
,
5208 uint16_t info_level
,
5210 struct smb_filename
*smb_fname
,
5211 bool delete_pending
,
5212 struct timespec write_time_ts
,
5213 struct ea_list
*ea_list
,
5214 int lock_data_count
,
5217 unsigned int max_data_bytes
,
5218 size_t *fixed_portion
,
5220 unsigned int *pdata_size
)
5222 char *pdata
= *ppdata
;
5223 char *dstart
, *dend
;
5224 unsigned int data_size
;
5225 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
5226 time_t create_time
, mtime
, atime
, c_time
;
5227 SMB_STRUCT_STAT
*psbuf
= NULL
;
5234 uint64_t file_size
= 0;
5236 uint64_t allocation_size
= 0;
5237 uint64_t file_id
= 0;
5238 uint32_t access_mask
= 0;
5241 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5242 return NT_STATUS_INVALID_LEVEL
;
5245 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5246 smb_fname_str_dbg(smb_fname
),
5248 info_level
, max_data_bytes
));
5251 * In case of querying a symlink in POSIX context,
5252 * fsp will be NULL. fdos_mode() deals with it.
5255 smb_fname
= fsp
->fsp_name
;
5257 mode
= fdos_mode(fsp
);
5258 psbuf
= &smb_fname
->st
;
5260 nlink
= psbuf
->st_ex_nlink
;
5262 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
5266 if ((nlink
> 0) && delete_pending
) {
5270 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5271 return NT_STATUS_INVALID_PARAMETER
;
5274 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5275 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5276 if (*ppdata
== NULL
) {
5277 return NT_STATUS_NO_MEMORY
;
5281 dend
= dstart
+ data_size
- 1;
5283 if (!is_omit_timespec(&write_time_ts
) &&
5284 !INFO_LEVEL_IS_UNIX(info_level
))
5286 update_stat_ex_mtime(psbuf
, write_time_ts
);
5289 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
5290 mtime_ts
= psbuf
->st_ex_mtime
;
5291 atime_ts
= psbuf
->st_ex_atime
;
5292 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
5294 if (lp_dos_filetime_resolution(SNUM(conn
))) {
5295 dos_filetime_timespec(&create_time_ts
);
5296 dos_filetime_timespec(&mtime_ts
);
5297 dos_filetime_timespec(&atime_ts
);
5298 dos_filetime_timespec(&ctime_ts
);
5301 create_time
= convert_timespec_to_time_t(create_time_ts
);
5302 mtime
= convert_timespec_to_time_t(mtime_ts
);
5303 atime
= convert_timespec_to_time_t(atime_ts
);
5304 c_time
= convert_timespec_to_time_t(ctime_ts
);
5306 p
= strrchr_m(smb_fname
->base_name
,'/');
5308 base_name
= smb_fname
->base_name
;
5312 /* NT expects the name to be in an exact form of the *full*
5313 filename. See the trans2 torture test */
5314 if (ISDOT(base_name
)) {
5315 dos_fname
= talloc_strdup(mem_ctx
, "\\");
5317 return NT_STATUS_NO_MEMORY
;
5320 dos_fname
= talloc_asprintf(mem_ctx
,
5322 smb_fname
->base_name
);
5324 return NT_STATUS_NO_MEMORY
;
5326 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5327 dos_fname
= talloc_asprintf(dos_fname
, "%s",
5328 smb_fname
->stream_name
);
5330 return NT_STATUS_NO_MEMORY
;
5334 string_replace(dos_fname
, '/', '\\');
5337 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
5339 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
5340 /* Do we have this path open ? */
5342 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
5343 fsp1
= file_find_di_first(conn
->sconn
, fileid
, true);
5344 if (fsp1
&& fsp1
->initial_allocation_size
) {
5345 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
5349 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
5350 file_size
= get_file_size_stat(psbuf
);
5354 pos
= fh_get_position_information(fsp
->fh
);
5358 access_mask
= fsp
->access_mask
;
5360 /* GENERIC_EXECUTE mapping from Windows */
5361 access_mask
= 0x12019F;
5364 /* This should be an index number - looks like
5367 I think this causes us to fail the IFSKIT
5368 BasicFileInformationTest. -tpot */
5369 file_id
= SMB_VFS_FS_FILE_ID(conn
, psbuf
);
5373 switch (info_level
) {
5374 case SMB_INFO_STANDARD
:
5375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5377 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
5378 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
5379 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
5380 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
5381 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
5382 SSVAL(pdata
,l1_attrFile
,mode
);
5385 case SMB_INFO_QUERY_EA_SIZE
:
5387 unsigned int ea_size
=
5388 estimate_ea_size(smb_fname
->fsp
);
5389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5391 srv_put_dos_date2(pdata
,0,create_time
);
5392 srv_put_dos_date2(pdata
,4,atime
);
5393 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
5394 SIVAL(pdata
,12,(uint32_t)file_size
);
5395 SIVAL(pdata
,16,(uint32_t)allocation_size
);
5396 SSVAL(pdata
,20,mode
);
5397 SIVAL(pdata
,22,ea_size
);
5401 case SMB_INFO_IS_NAME_VALID
:
5402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5404 /* os/2 needs this ? really ?*/
5405 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
5407 /* This is only reached for qpathinfo */
5411 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5413 size_t total_ea_len
= 0;
5414 struct ea_list
*ea_file_list
= NULL
;
5415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5418 get_ea_list_from_fsp(mem_ctx
,
5420 &total_ea_len
, &ea_file_list
);
5421 if (!NT_STATUS_IS_OK(status
)) {
5425 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
5427 if (!ea_list
|| (total_ea_len
> data_size
)) {
5429 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5433 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5437 case SMB_INFO_QUERY_ALL_EAS
:
5439 /* We have data_size bytes to put EA's into. */
5440 size_t total_ea_len
= 0;
5441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5443 status
= get_ea_list_from_fsp(mem_ctx
,
5445 &total_ea_len
, &ea_list
);
5446 if (!NT_STATUS_IS_OK(status
)) {
5450 if (!ea_list
|| (total_ea_len
> data_size
)) {
5452 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5456 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5460 case SMB2_FILE_FULL_EA_INFORMATION
:
5462 /* We have data_size bytes to put EA's into. */
5463 size_t total_ea_len
= 0;
5464 struct ea_list
*ea_file_list
= NULL
;
5466 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5468 /*TODO: add filtering and index handling */
5471 get_ea_list_from_fsp(mem_ctx
,
5473 &total_ea_len
, &ea_file_list
);
5474 if (!NT_STATUS_IS_OK(status
)) {
5477 if (!ea_file_list
) {
5478 return NT_STATUS_NO_EAS_ON_FILE
;
5481 status
= fill_ea_chained_buffer(mem_ctx
,
5485 conn
, ea_file_list
);
5486 if (!NT_STATUS_IS_OK(status
)) {
5492 case SMB_FILE_BASIC_INFORMATION
:
5493 case SMB_QUERY_FILE_BASIC_INFO
:
5495 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
5496 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5497 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5503 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5504 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5505 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5506 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5507 SIVAL(pdata
,32,mode
);
5509 DEBUG(5,("SMB_QFBI - "));
5510 DEBUG(5,("create: %s ", ctime(&create_time
)));
5511 DEBUG(5,("access: %s ", ctime(&atime
)));
5512 DEBUG(5,("write: %s ", ctime(&mtime
)));
5513 DEBUG(5,("change: %s ", ctime(&c_time
)));
5514 DEBUG(5,("mode: %x\n", mode
));
5515 *fixed_portion
= data_size
;
5518 case SMB_FILE_STANDARD_INFORMATION
:
5519 case SMB_QUERY_FILE_STANDARD_INFO
:
5521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5523 SOFF_T(pdata
,0,allocation_size
);
5524 SOFF_T(pdata
,8,file_size
);
5525 SIVAL(pdata
,16,nlink
);
5526 SCVAL(pdata
,20,delete_pending
?1:0);
5527 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5528 SSVAL(pdata
,22,0); /* Padding. */
5529 *fixed_portion
= 24;
5532 case SMB_FILE_EA_INFORMATION
:
5533 case SMB_QUERY_FILE_EA_INFO
:
5535 unsigned int ea_size
=
5536 estimate_ea_size(smb_fname
->fsp
);
5537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5540 SIVAL(pdata
,0,ea_size
);
5544 /* Get the 8.3 name - used if NT SMB was negotiated. */
5545 case SMB_QUERY_FILE_ALT_NAME_INFO
:
5546 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
5548 char mangled_name
[13];
5549 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5550 if (!name_to_8_3(base_name
,mangled_name
,
5551 True
,conn
->params
)) {
5552 return NT_STATUS_NO_MEMORY
;
5554 status
= srvstr_push(dstart
, flags2
,
5555 pdata
+4, mangled_name
,
5556 PTR_DIFF(dend
, pdata
+4),
5558 if (!NT_STATUS_IS_OK(status
)) {
5561 data_size
= 4 + len
;
5567 case SMB_QUERY_FILE_NAME_INFO
:
5570 this must be *exactly* right for ACLs on mapped drives to work
5572 status
= srvstr_push(dstart
, flags2
,
5574 PTR_DIFF(dend
, pdata
+4),
5576 if (!NT_STATUS_IS_OK(status
)) {
5579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5580 data_size
= 4 + len
;
5585 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
5587 char *nfname
= NULL
;
5589 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
5590 return NT_STATUS_INVALID_LEVEL
;
5593 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
5594 if (nfname
== NULL
) {
5595 return NT_STATUS_NO_MEMORY
;
5598 if (ISDOT(nfname
)) {
5601 string_replace(nfname
, '/', '\\');
5603 if (smb_fname
->stream_name
!= NULL
) {
5604 const char *s
= smb_fname
->stream_name
;
5605 const char *e
= NULL
;
5608 SMB_ASSERT(s
[0] != '\0');
5611 * smb_fname->stream_name is in form
5612 * of ':StrEam:$DATA', but we should only
5613 * append ':StrEam' here.
5616 e
= strchr(&s
[1], ':');
5622 nfname
= talloc_strndup_append(nfname
, s
, n
);
5623 if (nfname
== NULL
) {
5624 return NT_STATUS_NO_MEMORY
;
5628 status
= srvstr_push(dstart
, flags2
,
5630 PTR_DIFF(dend
, pdata
+4),
5632 if (!NT_STATUS_IS_OK(status
)) {
5635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5636 data_size
= 4 + len
;
5642 case SMB_FILE_ALLOCATION_INFORMATION
:
5643 case SMB_QUERY_FILE_ALLOCATION_INFO
:
5644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5646 SOFF_T(pdata
,0,allocation_size
);
5649 case SMB_FILE_END_OF_FILE_INFORMATION
:
5650 case SMB_QUERY_FILE_END_OF_FILEINFO
:
5651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5653 SOFF_T(pdata
,0,file_size
);
5656 case SMB_QUERY_FILE_ALL_INFO
:
5657 case SMB_FILE_ALL_INFORMATION
:
5659 unsigned int ea_size
=
5660 estimate_ea_size(smb_fname
->fsp
);
5661 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5662 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5663 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5664 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5665 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5666 SIVAL(pdata
,32,mode
);
5667 SIVAL(pdata
,36,0); /* padding. */
5669 SOFF_T(pdata
,0,allocation_size
);
5670 SOFF_T(pdata
,8,file_size
);
5671 SIVAL(pdata
,16,nlink
);
5672 SCVAL(pdata
,20,delete_pending
);
5673 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5676 SIVAL(pdata
,0,ea_size
);
5677 pdata
+= 4; /* EA info */
5678 status
= srvstr_push(dstart
, flags2
,
5680 PTR_DIFF(dend
, pdata
+4),
5682 if (!NT_STATUS_IS_OK(status
)) {
5687 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5688 *fixed_portion
= 10;
5692 case SMB2_FILE_ALL_INFORMATION
:
5694 unsigned int ea_size
=
5695 estimate_ea_size(smb_fname
->fsp
);
5696 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5697 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
5698 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
5699 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
5700 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
5701 SIVAL(pdata
, 0x20, mode
);
5702 SIVAL(pdata
, 0x24, 0); /* padding. */
5703 SBVAL(pdata
, 0x28, allocation_size
);
5704 SBVAL(pdata
, 0x30, file_size
);
5705 SIVAL(pdata
, 0x38, nlink
);
5706 SCVAL(pdata
, 0x3C, delete_pending
);
5707 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5708 SSVAL(pdata
, 0x3E, 0); /* padding */
5709 SBVAL(pdata
, 0x40, file_id
);
5710 SIVAL(pdata
, 0x48, ea_size
);
5711 SIVAL(pdata
, 0x4C, access_mask
);
5712 SBVAL(pdata
, 0x50, pos
);
5713 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5714 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5718 status
= srvstr_push(dstart
, flags2
,
5720 PTR_DIFF(dend
, pdata
+4),
5722 if (!NT_STATUS_IS_OK(status
)) {
5727 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5728 *fixed_portion
= 104;
5731 case SMB_FILE_INTERNAL_INFORMATION
:
5733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5734 SBVAL(pdata
, 0, file_id
);
5739 case SMB_FILE_ACCESS_INFORMATION
:
5740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5741 SIVAL(pdata
, 0, access_mask
);
5746 case SMB_FILE_NAME_INFORMATION
:
5747 /* Pathname with leading '\'. */
5750 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5752 SIVAL(pdata
,0,byte_len
);
5753 data_size
= 4 + byte_len
;
5757 case SMB_FILE_DISPOSITION_INFORMATION
:
5758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5760 SCVAL(pdata
,0,delete_pending
);
5764 case SMB_FILE_POSITION_INFORMATION
:
5765 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5767 SOFF_T(pdata
,0,pos
);
5771 case SMB_FILE_MODE_INFORMATION
:
5772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5773 SIVAL(pdata
,0,mode
);
5778 case SMB_FILE_ALIGNMENT_INFORMATION
:
5779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5780 SIVAL(pdata
,0,0); /* No alignment needed. */
5786 * NT4 server just returns "invalid query" to this - if we try
5787 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5790 /* The first statement above is false - verified using Thursby
5791 * client against NT4 -- gcolley.
5793 case SMB_QUERY_FILE_STREAM_INFO
:
5794 case SMB_FILE_STREAM_INFORMATION
: {
5795 unsigned int num_streams
= 0;
5796 struct stream_struct
*streams
= NULL
;
5798 DEBUG(10,("smbd_do_qfilepathinfo: "
5799 "SMB_FILE_STREAM_INFORMATION\n"));
5801 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5802 return NT_STATUS_INVALID_PARAMETER
;
5805 status
= vfs_streaminfo(conn
,
5812 if (!NT_STATUS_IS_OK(status
)) {
5813 DEBUG(10, ("could not get stream info: %s\n",
5814 nt_errstr(status
)));
5818 status
= marshall_stream_info(num_streams
, streams
,
5819 pdata
, max_data_bytes
,
5822 if (!NT_STATUS_IS_OK(status
)) {
5823 DEBUG(10, ("marshall_stream_info failed: %s\n",
5824 nt_errstr(status
)));
5825 TALLOC_FREE(streams
);
5829 TALLOC_FREE(streams
);
5831 *fixed_portion
= 32;
5835 case SMB_QUERY_COMPRESSION_INFO
:
5836 case SMB_FILE_COMPRESSION_INFORMATION
:
5837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5838 SOFF_T(pdata
,0,file_size
);
5839 SIVAL(pdata
,8,0); /* ??? */
5840 SIVAL(pdata
,12,0); /* ??? */
5842 *fixed_portion
= 16;
5845 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5847 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5848 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5849 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5850 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5851 SOFF_T(pdata
,32,allocation_size
);
5852 SOFF_T(pdata
,40,file_size
);
5853 SIVAL(pdata
,48,mode
);
5854 SIVAL(pdata
,52,0); /* ??? */
5856 *fixed_portion
= 56;
5859 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5860 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5861 SIVAL(pdata
,0,mode
);
5868 * CIFS UNIX Extensions.
5871 case SMB_QUERY_FILE_UNIX_BASIC
:
5873 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5874 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5876 DEBUG(4,("smbd_do_qfilepathinfo: "
5877 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5878 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5882 case SMB_QUERY_FILE_UNIX_INFO2
:
5884 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5885 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5889 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5891 for (i
=0; i
<100; i
++)
5892 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5898 case SMB_QUERY_FILE_UNIX_LINK
:
5900 status
= smb_unix_read_symlink(conn
,
5906 if (!NT_STATUS_IS_OK(status
)) {
5912 #if defined(HAVE_POSIX_ACLS)
5913 case SMB_QUERY_POSIX_ACL
:
5915 status
= smb_query_posix_acl(conn
,
5922 if (!NT_STATUS_IS_OK(status
)) {
5930 case SMB_QUERY_POSIX_LOCK
:
5935 enum brl_type lock_type
;
5937 /* We need an open file with a real fd for this. */
5939 fsp
->fsp_flags
.is_pathref
||
5940 fsp_get_io_fd(fsp
) == -1)
5942 return NT_STATUS_INVALID_LEVEL
;
5945 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5946 return NT_STATUS_INVALID_PARAMETER
;
5949 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5950 case POSIX_LOCK_TYPE_READ
:
5951 lock_type
= READ_LOCK
;
5953 case POSIX_LOCK_TYPE_WRITE
:
5954 lock_type
= WRITE_LOCK
;
5956 case POSIX_LOCK_TYPE_UNLOCK
:
5958 /* There's no point in asking for an unlock... */
5959 return NT_STATUS_INVALID_PARAMETER
;
5962 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5963 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5964 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5966 status
= query_lock(fsp
,
5973 if (ERROR_WAS_LOCK_DENIED(status
)) {
5974 /* Here we need to report who has it locked... */
5975 data_size
= POSIX_LOCK_DATA_SIZE
;
5977 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5978 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5979 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5980 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5981 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5983 } else if (NT_STATUS_IS_OK(status
)) {
5984 /* For success we just return a copy of what we sent
5985 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5986 data_size
= POSIX_LOCK_DATA_SIZE
;
5987 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5988 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5996 return NT_STATUS_INVALID_LEVEL
;
5999 *pdata_size
= data_size
;
6000 return NT_STATUS_OK
;
6003 /****************************************************************************
6004 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6005 file name or file id).
6006 ****************************************************************************/
6008 static void call_trans2qfilepathinfo(connection_struct
*conn
,
6009 struct smb_request
*req
,
6010 unsigned int tran_call
,
6011 char **pparams
, int total_params
,
6012 char **ppdata
, int total_data
,
6013 unsigned int max_data_bytes
)
6015 char *params
= *pparams
;
6016 char *pdata
= *ppdata
;
6017 uint16_t info_level
;
6018 unsigned int data_size
= 0;
6019 unsigned int param_size
= 2;
6020 struct smb_filename
*smb_fname
= NULL
;
6021 bool delete_pending
= False
;
6022 struct timespec write_time_ts
;
6023 files_struct
*fsp
= NULL
;
6024 struct file_id fileid
;
6025 struct ea_list
*ea_list
= NULL
;
6026 int lock_data_count
= 0;
6027 char *lock_data
= NULL
;
6028 size_t fixed_portion
;
6029 NTSTATUS status
= NT_STATUS_OK
;
6032 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6036 ZERO_STRUCT(write_time_ts
);
6038 if (tran_call
== TRANSACT2_QFILEINFO
) {
6039 if (total_params
< 4) {
6040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6045 call_trans2qpipeinfo(conn
, req
, tran_call
,
6046 pparams
, total_params
,
6052 fsp
= file_fsp(req
, SVAL(params
,0));
6053 info_level
= SVAL(params
,2);
6055 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
6057 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6058 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6062 /* Initial check for valid fsp ptr. */
6063 if (!check_fsp_open(conn
, req
, fsp
)) {
6067 smb_fname
= fsp
->fsp_name
;
6069 if(fsp
->fake_file_handle
) {
6071 * This is actually for the QUOTA_FAKE_FILE --metze
6074 /* We know this name is ok, it's already passed the checks. */
6076 } else if(fsp_get_pathref_fd(fsp
) == -1) {
6078 * This is actually a QFILEINFO on a directory
6079 * handle (returned from an NT SMB). NT5.0 seems
6080 * to do this call. JRA.
6083 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6084 /* Always do lstat for UNIX calls. */
6085 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
6086 DEBUG(3,("call_trans2qfilepathinfo: "
6087 "SMB_VFS_LSTAT of %s failed "
6089 smb_fname_str_dbg(smb_fname
),
6092 map_nt_error_from_unix(errno
));
6095 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
6096 DEBUG(3,("call_trans2qfilepathinfo: "
6097 "SMB_VFS_STAT of %s failed (%s)\n",
6098 smb_fname_str_dbg(smb_fname
),
6101 map_nt_error_from_unix(errno
));
6105 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6106 fileid
= vfs_file_id_from_sbuf(
6107 conn
, &smb_fname
->st
);
6108 get_file_infos(fileid
, fsp
->name_hash
,
6114 * Original code - this is an open file.
6116 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
6117 DEBUG(3, ("fstat of %s failed (%s)\n",
6118 fsp_fnum_dbg(fsp
), strerror(errno
)));
6120 map_nt_error_from_unix(errno
));
6123 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6124 fileid
= vfs_file_id_from_sbuf(
6125 conn
, &smb_fname
->st
);
6126 get_file_infos(fileid
, fsp
->name_hash
,
6135 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6138 if (total_params
< 7) {
6139 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6143 info_level
= SVAL(params
,0);
6145 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
6147 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6148 if (!lp_unix_extensions()) {
6149 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6154 if (req
->posix_pathnames
) {
6155 srvstr_get_path_posix(req
,
6164 srvstr_get_path(req
,
6173 if (!NT_STATUS_IS_OK(status
)) {
6174 reply_nterror(req
, status
);
6178 status
= filename_convert(req
,
6184 if (!NT_STATUS_IS_OK(status
)) {
6185 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6186 reply_botherror(req
,
6187 NT_STATUS_PATH_NOT_COVERED
,
6188 ERRSRV
, ERRbadpath
);
6191 reply_nterror(req
, status
);
6196 * smb_fname->fsp may be NULL if smb_fname points at a symlink
6197 * and we're in POSIX context, so be careful when using fsp
6198 * below, it can still be NULL.
6200 fsp
= smb_fname
->fsp
;
6202 /* If this is a stream, check if there is a delete_pending. */
6203 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
6204 && is_ntfs_stream_smb_fname(smb_fname
)) {
6205 struct smb_filename
*smb_fname_base
;
6207 /* Create an smb_filename with stream_name == NULL. */
6208 smb_fname_base
= synthetic_smb_fname(
6210 smb_fname
->base_name
,
6215 if (smb_fname_base
== NULL
) {
6216 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6220 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6221 /* Always do lstat for UNIX calls. */
6222 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
6223 DEBUG(3,("call_trans2qfilepathinfo: "
6224 "SMB_VFS_LSTAT of %s failed "
6226 smb_fname_str_dbg(smb_fname_base
),
6228 TALLOC_FREE(smb_fname_base
);
6230 map_nt_error_from_unix(errno
));
6234 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
6235 DEBUG(3,("call_trans2qfilepathinfo: "
6236 "fileinfo of %s failed "
6238 smb_fname_str_dbg(smb_fname_base
),
6240 TALLOC_FREE(smb_fname_base
);
6242 map_nt_error_from_unix(errno
));
6247 status
= file_name_hash(conn
,
6248 smb_fname_str_dbg(smb_fname_base
),
6250 if (!NT_STATUS_IS_OK(status
)) {
6251 TALLOC_FREE(smb_fname_base
);
6252 reply_nterror(req
, status
);
6256 fileid
= vfs_file_id_from_sbuf(conn
,
6257 &smb_fname_base
->st
);
6258 TALLOC_FREE(smb_fname_base
);
6259 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
6260 if (delete_pending
) {
6261 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6266 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6267 /* Always do lstat for UNIX calls. */
6268 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
6269 DEBUG(3,("call_trans2qfilepathinfo: "
6270 "SMB_VFS_LSTAT of %s failed (%s)\n",
6271 smb_fname_str_dbg(smb_fname
),
6274 map_nt_error_from_unix(errno
));
6279 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
6280 DEBUG(3,("call_trans2qfilepathinfo: "
6281 "SMB_VFS_STAT of %s failed (%s)\n",
6282 smb_fname_str_dbg(smb_fname
),
6285 map_nt_error_from_unix(errno
));
6290 status
= file_name_hash(conn
,
6291 smb_fname_str_dbg(smb_fname
),
6293 if (!NT_STATUS_IS_OK(status
)) {
6294 reply_nterror(req
, status
);
6298 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6299 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
6300 get_file_infos(fileid
, name_hash
, &delete_pending
,
6304 if (delete_pending
) {
6305 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6310 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6311 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
6313 info_level
,tran_call
,total_data
));
6315 /* Pull out any data sent here before we realloc. */
6316 switch (info_level
) {
6317 case SMB_INFO_QUERY_EAS_FROM_LIST
:
6319 /* Pull any EA list from the data portion. */
6322 if (total_data
< 4) {
6324 req
, NT_STATUS_INVALID_PARAMETER
);
6327 ea_size
= IVAL(pdata
,0);
6329 if (total_data
> 0 && ea_size
!= total_data
) {
6330 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6331 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
6333 req
, NT_STATUS_INVALID_PARAMETER
);
6337 if (!lp_ea_support(SNUM(conn
))) {
6338 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
6342 /* Pull out the list of names. */
6343 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
6346 req
, NT_STATUS_INVALID_PARAMETER
);
6352 case SMB_QUERY_POSIX_LOCK
:
6355 fsp
->fsp_flags
.is_pathref
||
6356 fsp_get_io_fd(fsp
) == -1)
6358 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6362 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6364 req
, NT_STATUS_INVALID_PARAMETER
);
6368 /* Copy the lock range data. */
6369 lock_data
= (char *)talloc_memdup(
6370 req
, pdata
, total_data
);
6372 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6375 lock_data_count
= total_data
;
6382 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6383 if (*pparams
== NULL
) {
6384 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6391 * draft-leach-cifs-v1-spec-02.txt
6392 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6395 * The requested information is placed in the Data portion of the
6396 * transaction response. For the information levels greater than 0x100,
6397 * the transaction response has 1 parameter word which should be
6398 * ignored by the client.
6400 * However Windows only follows this rule for the IS_NAME_VALID call.
6402 switch (info_level
) {
6403 case SMB_INFO_IS_NAME_VALID
:
6408 if ((info_level
& SMB2_INFO_SPECIAL
) == SMB2_INFO_SPECIAL
) {
6410 * We use levels that start with 0xFF00
6411 * internally to represent SMB2 specific levels
6413 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6417 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
6419 delete_pending
, write_time_ts
,
6421 lock_data_count
, lock_data
,
6422 req
->flags2
, max_data_bytes
,
6424 ppdata
, &data_size
);
6425 if (!NT_STATUS_IS_OK(status
)) {
6426 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6427 /* We have re-scheduled this call. */
6430 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6431 bool ok
= defer_smb1_sharing_violation(req
);
6436 reply_nterror(req
, status
);
6439 if (fixed_portion
> max_data_bytes
) {
6440 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
6444 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
6450 /****************************************************************************
6451 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6453 ****************************************************************************/
6455 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
6456 connection_struct
*conn
,
6457 struct smb_request
*req
,
6458 bool overwrite_if_exists
,
6459 const struct smb_filename
*smb_fname_old
,
6460 struct smb_filename
*smb_fname_new
)
6462 NTSTATUS status
= NT_STATUS_OK
;
6465 struct smb_filename
*parent_fname_old
= NULL
;
6466 struct smb_filename
*base_name_old
= NULL
;
6467 struct smb_filename
*parent_fname_new
= NULL
;
6468 struct smb_filename
*base_name_new
= NULL
;
6470 /* source must already exist. */
6471 if (!VALID_STAT(smb_fname_old
->st
)) {
6472 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6476 /* No links from a directory. */
6477 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
6478 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
6482 /* Setting a hardlink to/from a stream isn't currently supported. */
6483 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
6485 DBG_DEBUG("Old name has streams\n");
6486 status
= NT_STATUS_INVALID_PARAMETER
;
6489 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
6491 DBG_DEBUG("New name has streams\n");
6492 status
= NT_STATUS_INVALID_PARAMETER
;
6496 status
= parent_pathref(talloc_tos(),
6501 if (!NT_STATUS_IS_OK(status
)) {
6505 status
= parent_pathref(talloc_tos(),
6510 if (!NT_STATUS_IS_OK(status
)) {
6514 if (VALID_STAT(smb_fname_new
->st
)) {
6515 if (overwrite_if_exists
) {
6516 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
6517 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
6520 status
= unlink_internals(conn
,
6522 FILE_ATTRIBUTE_NORMAL
,
6525 if (!NT_STATUS_IS_OK(status
)) {
6529 /* Disallow if newname already exists. */
6530 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6535 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6536 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
6538 ret
= SMB_VFS_LINKAT(conn
,
6539 parent_fname_old
->fsp
,
6541 parent_fname_new
->fsp
,
6546 status
= map_nt_error_from_unix(errno
);
6547 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6548 nt_errstr(status
), smb_fname_old
->base_name
,
6549 smb_fname_new
->base_name
));
6554 TALLOC_FREE(parent_fname_old
);
6555 TALLOC_FREE(parent_fname_new
);
6559 /****************************************************************************
6560 Deal with setting the time from any of the setfilepathinfo functions.
6561 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6562 calling this function.
6563 ****************************************************************************/
6565 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
6567 struct smb_filename
*smb_fname
,
6568 struct smb_file_time
*ft
,
6569 bool setting_write_time
)
6571 struct files_struct
*set_fsp
= NULL
;
6572 struct timeval_buf tbuf
[4];
6574 FILE_NOTIFY_CHANGE_LAST_ACCESS
6575 |FILE_NOTIFY_CHANGE_LAST_WRITE
6576 |FILE_NOTIFY_CHANGE_CREATION
;
6579 if (!VALID_STAT(smb_fname
->st
)) {
6580 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6585 return NT_STATUS_OK
;
6588 set_fsp
= fsp
->base_fsp
== NULL
? fsp
: fsp
->base_fsp
;
6590 /* get some defaults (no modifications) if any info is zero or -1. */
6591 if (is_omit_timespec(&ft
->create_time
)) {
6592 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
6595 if (is_omit_timespec(&ft
->atime
)) {
6596 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
6599 if (is_omit_timespec(&ft
->mtime
)) {
6600 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6603 if (!setting_write_time
) {
6604 /* ft->mtime comes from change time, not write time. */
6605 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6608 /* Ensure the resolution is the correct for
6609 * what we can store on this filesystem. */
6611 round_timespec(conn
->ts_res
, &ft
->create_time
);
6612 round_timespec(conn
->ts_res
, &ft
->ctime
);
6613 round_timespec(conn
->ts_res
, &ft
->atime
);
6614 round_timespec(conn
->ts_res
, &ft
->mtime
);
6616 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6617 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
6618 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6619 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
6620 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6621 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
6622 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6623 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
6625 if (setting_write_time
) {
6627 * This was a Windows setfileinfo on an open file.
6628 * NT does this a lot. We also need to
6629 * set the time here, as it can be read by
6630 * FindFirst/FindNext and with the patch for bug #2045
6631 * in smbd/fileio.c it ensures that this timestamp is
6632 * kept sticky even after a write. We save the request
6633 * away and will set it on file close and after a write. JRA.
6636 DBG_DEBUG("setting pending modtime to %s\n",
6637 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
6639 if (set_fsp
!= NULL
) {
6640 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
6642 set_sticky_write_time_path(
6643 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
6648 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6650 ret
= file_ntimes(conn
, set_fsp
->fsp_name
, ft
);
6652 return map_nt_error_from_unix(errno
);
6655 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
6656 smb_fname
->base_name
);
6657 return NT_STATUS_OK
;
6660 /****************************************************************************
6661 Deal with setting the dosmode from any of the setfilepathinfo functions.
6662 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6663 done before calling this function.
6664 ****************************************************************************/
6666 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
6667 struct files_struct
*fsp
,
6668 struct smb_filename
*smb_fname
,
6671 struct smb_filename
*smb_fname_base
;
6674 if (!VALID_STAT(smb_fname
->st
)) {
6675 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6678 /* Always operate on the base_name, even if a stream was passed in. */
6679 smb_fname_base
= synthetic_smb_fname(talloc_tos(),
6680 smb_fname
->base_name
,
6685 if (smb_fname_base
== NULL
) {
6686 return NT_STATUS_NO_MEMORY
;
6690 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6691 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6693 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6697 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6699 /* check the mode isn't different, before changing it */
6700 if ((dosmode
!= 0) && (dosmode
!= fdos_mode(fsp
))) {
6701 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6702 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6703 (unsigned int)dosmode
));
6705 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6707 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6709 smb_fname_str_dbg(smb_fname_base
),
6711 status
= map_nt_error_from_unix(errno
);
6715 status
= NT_STATUS_OK
;
6717 TALLOC_FREE(smb_fname_base
);
6721 /****************************************************************************
6722 Deal with setting the size from any of the setfilepathinfo functions.
6723 ****************************************************************************/
6725 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6726 struct smb_request
*req
,
6728 struct smb_filename
*smb_fname
,
6729 const SMB_STRUCT_STAT
*psbuf
,
6731 bool fail_after_createfile
)
6733 NTSTATUS status
= NT_STATUS_OK
;
6734 files_struct
*new_fsp
= NULL
;
6736 if (!VALID_STAT(*psbuf
)) {
6737 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6740 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
6742 get_file_size_stat(psbuf
));
6744 if (size
== get_file_size_stat(psbuf
)) {
6746 return NT_STATUS_OK
;
6748 if (!fsp
->fsp_flags
.modified
) {
6749 return NT_STATUS_OK
;
6751 trigger_write_time_update_immediate(fsp
);
6752 return NT_STATUS_OK
;
6755 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6756 smb_fname_str_dbg(smb_fname
), (double)size
));
6759 !fsp
->fsp_flags
.is_pathref
&&
6760 fsp_get_io_fd(fsp
) != -1)
6762 /* Handle based call. */
6763 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6764 return NT_STATUS_ACCESS_DENIED
;
6767 if (vfs_set_filelen(fsp
, size
) == -1) {
6768 return map_nt_error_from_unix(errno
);
6770 trigger_write_time_update_immediate(fsp
);
6771 return NT_STATUS_OK
;
6774 status
= SMB_VFS_CREATE_FILE(
6777 smb_fname
, /* fname */
6778 FILE_WRITE_DATA
, /* access_mask */
6779 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6781 FILE_OPEN
, /* create_disposition*/
6782 0, /* create_options */
6783 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6784 0, /* oplock_request */
6786 0, /* allocation_size */
6787 0, /* private_flags */
6790 &new_fsp
, /* result */
6792 NULL
, NULL
); /* create context */
6794 if (!NT_STATUS_IS_OK(status
)) {
6795 /* NB. We check for open_was_deferred in the caller. */
6799 /* See RAW-SFILEINFO-END-OF-FILE */
6800 if (fail_after_createfile
) {
6801 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6802 return NT_STATUS_INVALID_LEVEL
;
6805 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6806 status
= map_nt_error_from_unix(errno
);
6807 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6811 trigger_write_time_update_immediate(new_fsp
);
6812 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6813 return NT_STATUS_OK
;
6816 /****************************************************************************
6817 Deal with SMB_INFO_SET_EA.
6818 ****************************************************************************/
6820 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6824 struct smb_filename
*smb_fname
)
6826 struct ea_list
*ea_list
= NULL
;
6827 TALLOC_CTX
*ctx
= NULL
;
6828 NTSTATUS status
= NT_STATUS_OK
;
6830 if (total_data
< 10) {
6832 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6833 length. They seem to have no effect. Bug #3212. JRA */
6835 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6836 /* We're done. We only get EA info in this call. */
6837 return NT_STATUS_OK
;
6840 return NT_STATUS_INVALID_PARAMETER
;
6843 if (IVAL(pdata
,0) > total_data
) {
6844 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6845 IVAL(pdata
,0), (unsigned int)total_data
));
6846 return NT_STATUS_INVALID_PARAMETER
;
6850 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6852 return NT_STATUS_INVALID_PARAMETER
;
6857 * The only way fsp can be NULL here is if
6858 * smb_fname points at a symlink and
6859 * and we're in POSIX context.
6860 * Ensure this is the case.
6862 * There is still a race condition in that
6863 * the symlink could be changed after we
6864 * checked it, so ensure we only operate
6865 * EA setting on a file handle.
6867 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
6868 if (!(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
)) {
6869 return NT_STATUS_ACCESS_DENIED
;
6871 status
= refuse_symlink(conn
, NULL
, smb_fname
);
6872 SMB_ASSERT(NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
));
6873 return NT_STATUS_ACCESS_DENIED
;
6876 status
= set_ea(conn
, fsp
, ea_list
);
6881 /****************************************************************************
6882 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6883 ****************************************************************************/
6885 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6890 struct ea_list
*ea_list
= NULL
;
6894 return NT_STATUS_INVALID_HANDLE
;
6897 if (!lp_ea_support(SNUM(conn
))) {
6898 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6899 "EA's not supported.\n",
6900 (unsigned int)total_data
));
6901 return NT_STATUS_EAS_NOT_SUPPORTED
;
6904 if (total_data
< 10) {
6905 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6907 (unsigned int)total_data
));
6908 return NT_STATUS_INVALID_PARAMETER
;
6911 ea_list
= read_nttrans_ea_list(talloc_tos(),
6916 return NT_STATUS_INVALID_PARAMETER
;
6919 status
= set_ea(conn
, fsp
, ea_list
);
6921 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6922 smb_fname_str_dbg(fsp
->fsp_name
),
6923 nt_errstr(status
) ));
6929 /****************************************************************************
6930 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6931 ****************************************************************************/
6933 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6937 struct smb_filename
*smb_fname
)
6939 NTSTATUS status
= NT_STATUS_OK
;
6940 bool delete_on_close
;
6941 uint32_t dosmode
= 0;
6943 if (total_data
< 1) {
6944 return NT_STATUS_INVALID_PARAMETER
;
6948 return NT_STATUS_INVALID_HANDLE
;
6951 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6952 dosmode
= fdos_mode(fsp
);
6954 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6955 "delete_on_close = %u\n",
6956 smb_fname_str_dbg(smb_fname
),
6957 (unsigned int)dosmode
,
6958 (unsigned int)delete_on_close
));
6960 if (delete_on_close
) {
6961 status
= can_set_delete_on_close(fsp
, dosmode
);
6962 if (!NT_STATUS_IS_OK(status
)) {
6967 /* The set is across all open files on this dev/inode pair. */
6968 if (!set_delete_on_close(fsp
, delete_on_close
,
6969 conn
->session_info
->security_token
,
6970 conn
->session_info
->unix_token
)) {
6971 return NT_STATUS_ACCESS_DENIED
;
6973 return NT_STATUS_OK
;
6976 /****************************************************************************
6977 Deal with SMB_FILE_POSITION_INFORMATION.
6978 ****************************************************************************/
6980 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6985 uint64_t position_information
;
6987 if (total_data
< 8) {
6988 return NT_STATUS_INVALID_PARAMETER
;
6992 /* Ignore on pathname based set. */
6993 return NT_STATUS_OK
;
6996 position_information
= (uint64_t)IVAL(pdata
,0);
6997 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6999 DEBUG(10,("smb_file_position_information: Set file position "
7000 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
7001 (double)position_information
));
7002 fh_set_position_information(fsp
->fh
, position_information
);
7003 return NT_STATUS_OK
;
7006 /****************************************************************************
7007 Deal with SMB_FILE_MODE_INFORMATION.
7008 ****************************************************************************/
7010 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
7016 if (total_data
< 4) {
7017 return NT_STATUS_INVALID_PARAMETER
;
7019 mode
= IVAL(pdata
,0);
7020 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
7021 return NT_STATUS_INVALID_PARAMETER
;
7023 return NT_STATUS_OK
;
7026 /****************************************************************************
7027 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
7028 ****************************************************************************/
7030 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
7031 struct smb_request
*req
,
7034 struct smb_filename
*new_smb_fname
)
7036 char *link_target
= NULL
;
7037 struct smb_filename target_fname
;
7038 TALLOC_CTX
*ctx
= talloc_tos();
7041 struct smb_filename
*parent_fname
= NULL
;
7042 struct smb_filename
*base_name
= NULL
;
7044 /* Set a symbolic link. */
7045 /* Don't allow this if follow links is false. */
7047 if (total_data
== 0) {
7048 return NT_STATUS_INVALID_PARAMETER
;
7051 if (!lp_follow_symlinks(SNUM(conn
))) {
7052 return NT_STATUS_ACCESS_DENIED
;
7055 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
7056 total_data
, STR_TERMINATE
);
7059 return NT_STATUS_INVALID_PARAMETER
;
7062 target_fname
= (struct smb_filename
) {
7063 .base_name
= link_target
,
7066 /* Removes @GMT tokens if any */
7067 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
7068 if (!NT_STATUS_IS_OK(status
)) {
7072 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7073 new_smb_fname
->base_name
, link_target
));
7075 status
= parent_pathref(talloc_tos(),
7080 if (!NT_STATUS_IS_OK(status
)) {
7084 ret
= SMB_VFS_SYMLINKAT(conn
,
7089 TALLOC_FREE(parent_fname
);
7090 return map_nt_error_from_unix(errno
);
7093 TALLOC_FREE(parent_fname
);
7094 return NT_STATUS_OK
;
7097 /****************************************************************************
7098 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7099 ****************************************************************************/
7101 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
7102 struct smb_request
*req
,
7103 const char *pdata
, int total_data
,
7104 struct smb_filename
*smb_fname_new
)
7106 char *oldname
= NULL
;
7107 struct smb_filename
*smb_fname_old
= NULL
;
7108 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7109 TALLOC_CTX
*ctx
= talloc_tos();
7110 NTSTATUS status
= NT_STATUS_OK
;
7112 /* Set a hard link. */
7113 if (total_data
== 0) {
7114 return NT_STATUS_INVALID_PARAMETER
;
7117 if (req
->posix_pathnames
) {
7118 srvstr_get_path_posix(ctx
,
7127 srvstr_get_path(ctx
,
7136 if (!NT_STATUS_IS_OK(status
)) {
7140 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7141 smb_fname_str_dbg(smb_fname_new
), oldname
));
7143 status
= filename_convert(ctx
,
7149 if (!NT_STATUS_IS_OK(status
)) {
7153 return hardlink_internals(ctx
, conn
, req
, false,
7154 smb_fname_old
, smb_fname_new
);
7157 /****************************************************************************
7158 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7159 ****************************************************************************/
7161 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
7162 struct smb_request
*req
,
7166 struct smb_filename
*smb_fname_src
)
7170 char *newname
= NULL
;
7171 struct smb_filename
*smb_fname_dst
= NULL
;
7172 const char *dst_original_lcomp
= NULL
;
7173 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7174 NTSTATUS status
= NT_STATUS_OK
;
7175 TALLOC_CTX
*ctx
= talloc_tos();
7178 return NT_STATUS_INVALID_HANDLE
;
7181 if (total_data
< 20) {
7182 return NT_STATUS_INVALID_PARAMETER
;
7185 overwrite
= (CVAL(pdata
,0) ? True
: False
);
7186 len
= IVAL(pdata
,16);
7188 if (len
> (total_data
- 20) || (len
== 0)) {
7189 return NT_STATUS_INVALID_PARAMETER
;
7192 if (req
->posix_pathnames
) {
7193 srvstr_get_path_posix(ctx
,
7202 srvstr_get_path(ctx
,
7211 if (!NT_STATUS_IS_OK(status
)) {
7215 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7218 status
= filename_convert(ctx
,
7224 if (!NT_STATUS_IS_OK(status
)) {
7228 if (fsp
->base_fsp
) {
7229 /* newname must be a stream name. */
7230 if (newname
[0] != ':') {
7231 return NT_STATUS_NOT_SUPPORTED
;
7234 /* Create an smb_fname to call rename_internals_fsp() with. */
7235 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7236 fsp
->base_fsp
->fsp_name
->base_name
,
7239 fsp
->base_fsp
->fsp_name
->twrp
,
7240 fsp
->base_fsp
->fsp_name
->flags
);
7241 if (smb_fname_dst
== NULL
) {
7242 status
= NT_STATUS_NO_MEMORY
;
7248 * Set the original last component, since
7249 * rename_internals_fsp() requires it.
7251 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7255 if (dst_original_lcomp
== NULL
) {
7256 status
= NT_STATUS_NO_MEMORY
;
7260 DEBUG(10,("smb2_file_rename_information: "
7261 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7262 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7263 smb_fname_str_dbg(smb_fname_dst
)));
7264 status
= rename_internals_fsp(conn
,
7268 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
7272 TALLOC_FREE(smb_fname_dst
);
7276 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
7277 struct smb_request
*req
,
7281 struct smb_filename
*smb_fname_src
)
7285 char *newname
= NULL
;
7286 struct smb_filename
*smb_fname_dst
= NULL
;
7287 NTSTATUS status
= NT_STATUS_OK
;
7288 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7289 TALLOC_CTX
*ctx
= talloc_tos();
7292 return NT_STATUS_INVALID_HANDLE
;
7295 if (total_data
< 20) {
7296 return NT_STATUS_INVALID_PARAMETER
;
7299 overwrite
= (CVAL(pdata
,0) ? true : false);
7300 len
= IVAL(pdata
,16);
7302 if (len
> (total_data
- 20) || (len
== 0)) {
7303 return NT_STATUS_INVALID_PARAMETER
;
7306 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
7307 srvstr_get_path_posix(ctx
,
7315 ucf_flags
|= UCF_POSIX_PATHNAMES
;
7317 srvstr_get_path(ctx
,
7326 if (!NT_STATUS_IS_OK(status
)) {
7330 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7333 status
= filename_convert(ctx
,
7339 if (!NT_STATUS_IS_OK(status
)) {
7343 if (fsp
->base_fsp
) {
7344 /* No stream names. */
7345 return NT_STATUS_NOT_SUPPORTED
;
7348 DEBUG(10,("smb_file_link_information: "
7349 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7350 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7351 smb_fname_str_dbg(smb_fname_dst
)));
7352 status
= hardlink_internals(ctx
,
7359 TALLOC_FREE(smb_fname_dst
);
7363 /****************************************************************************
7364 Deal with SMB_FILE_RENAME_INFORMATION.
7365 ****************************************************************************/
7367 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
7368 struct smb_request
*req
,
7372 struct smb_filename
*smb_fname_src
)
7377 char *newname
= NULL
;
7378 struct smb_filename
*smb_fname_dst
= NULL
;
7379 const char *dst_original_lcomp
= NULL
;
7380 NTSTATUS status
= NT_STATUS_OK
;
7382 TALLOC_CTX
*ctx
= talloc_tos();
7384 if (total_data
< 13) {
7385 return NT_STATUS_INVALID_PARAMETER
;
7388 overwrite
= (CVAL(pdata
,0) ? True
: False
);
7389 root_fid
= IVAL(pdata
,4);
7390 len
= IVAL(pdata
,8);
7392 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
7393 return NT_STATUS_INVALID_PARAMETER
;
7396 if (req
->posix_pathnames
) {
7397 srvstr_get_path_posix(ctx
,
7406 srvstr_get_path(ctx
,
7415 if (!NT_STATUS_IS_OK(status
)) {
7419 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7422 /* Check the new name has no '/' characters. */
7423 if (strchr_m(newname
, '/')) {
7424 return NT_STATUS_NOT_SUPPORTED
;
7427 if (fsp
&& fsp
->base_fsp
) {
7428 /* newname must be a stream name. */
7429 if (newname
[0] != ':') {
7430 return NT_STATUS_NOT_SUPPORTED
;
7433 /* Create an smb_fname to call rename_internals_fsp() with. */
7434 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7435 fsp
->base_fsp
->fsp_name
->base_name
,
7438 fsp
->base_fsp
->fsp_name
->twrp
,
7439 fsp
->base_fsp
->fsp_name
->flags
);
7440 if (smb_fname_dst
== NULL
) {
7441 status
= NT_STATUS_NO_MEMORY
;
7446 * Get the original last component, since
7447 * rename_internals_fsp() requires it.
7449 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7453 if (dst_original_lcomp
== NULL
) {
7454 status
= NT_STATUS_NO_MEMORY
;
7460 * Build up an smb_fname_dst based on the filename passed in.
7461 * We basically just strip off the last component, and put on
7462 * the newname instead.
7464 char *base_name
= NULL
;
7465 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
7466 ucf_flags_from_smb_request(req
);
7468 /* newname must *not* be a stream name. */
7469 if (newname
[0] == ':') {
7470 return NT_STATUS_NOT_SUPPORTED
;
7474 * Strip off the last component (filename) of the path passed
7477 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
7479 return NT_STATUS_NO_MEMORY
;
7481 p
= strrchr_m(base_name
, '/');
7485 base_name
= talloc_strdup(ctx
, "");
7487 return NT_STATUS_NO_MEMORY
;
7490 /* Append the new name. */
7491 base_name
= talloc_asprintf_append(base_name
,
7495 return NT_STATUS_NO_MEMORY
;
7498 status
= filename_convert(ctx
,
7505 /* If an error we expect this to be
7506 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7508 if (!NT_STATUS_IS_OK(status
)) {
7509 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
7513 /* Create an smb_fname to call rename_internals_fsp() */
7514 smb_fname_dst
= synthetic_smb_fname(ctx
,
7518 smb_fname_src
->twrp
,
7519 smb_fname_src
->flags
);
7520 if (smb_fname_dst
== NULL
) {
7521 status
= NT_STATUS_NO_MEMORY
;
7525 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7529 if (dst_original_lcomp
== NULL
) {
7530 status
= NT_STATUS_NO_MEMORY
;
7535 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
7536 DEBUG(10,("smb_file_rename_information: "
7537 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7538 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7539 smb_fname_str_dbg(smb_fname_dst
)));
7540 status
= rename_internals_fsp(conn
,
7547 DEBUG(10,("smb_file_rename_information: "
7548 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7549 smb_fname_str_dbg(smb_fname_src
),
7550 smb_fname_str_dbg(smb_fname_dst
)));
7551 status
= rename_internals(ctx
,
7560 FILE_WRITE_ATTRIBUTES
);
7563 TALLOC_FREE(smb_fname_dst
);
7567 /****************************************************************************
7568 Deal with SMB_SET_POSIX_ACL.
7569 ****************************************************************************/
7571 #if defined(HAVE_POSIX_ACLS)
7572 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
7573 struct smb_request
*req
,
7577 struct smb_filename
*smb_fname
)
7579 uint16_t posix_acl_version
;
7580 uint16_t num_file_acls
;
7581 uint16_t num_def_acls
;
7582 bool valid_file_acls
= true;
7583 bool valid_def_acls
= true;
7585 unsigned int size_needed
;
7586 unsigned int total_data
;
7587 bool close_fsp
= false;
7589 if (total_data_in
< 0) {
7590 status
= NT_STATUS_INVALID_PARAMETER
;
7594 total_data
= total_data_in
;
7596 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
7597 status
= NT_STATUS_INVALID_PARAMETER
;
7600 posix_acl_version
= SVAL(pdata
,0);
7601 num_file_acls
= SVAL(pdata
,2);
7602 num_def_acls
= SVAL(pdata
,4);
7604 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7605 valid_file_acls
= false;
7609 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7610 valid_def_acls
= false;
7614 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
7615 status
= NT_STATUS_INVALID_PARAMETER
;
7620 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
7621 status
= NT_STATUS_INVALID_PARAMETER
;
7625 size_needed
= num_file_acls
+ num_def_acls
;
7628 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7629 * than UINT_MAX, so check by division.
7631 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
7632 status
= NT_STATUS_INVALID_PARAMETER
;
7636 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
7637 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
7638 status
= NT_STATUS_INVALID_PARAMETER
;
7641 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
7643 if (total_data
< size_needed
) {
7644 status
= NT_STATUS_INVALID_PARAMETER
;
7649 * Ensure we always operate on a file descriptor, not just
7652 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
7653 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
7655 SEC_STD_READ_CONTROL
|
7656 FILE_READ_ATTRIBUTES
|
7657 FILE_WRITE_ATTRIBUTES
;
7659 status
= get_posix_fsp(conn
,
7665 if (!NT_STATUS_IS_OK(status
)) {
7671 /* Here we know fsp != NULL */
7672 SMB_ASSERT(fsp
!= NULL
);
7674 status
= refuse_symlink(conn
, fsp
, fsp
->fsp_name
);
7675 if (!NT_STATUS_IS_OK(status
)) {
7679 /* If we have a default acl, this *must* be a directory. */
7680 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
7681 DBG_INFO("Can't set default acls on "
7682 "non-directory %s\n",
7684 return NT_STATUS_INVALID_HANDLE
;
7687 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
7688 "num_def_acls = %"PRIu16
"\n",
7693 /* Move pdata to the start of the file ACL entries. */
7694 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
7696 if (valid_file_acls
) {
7697 status
= set_unix_posix_acl(conn
,
7701 if (!NT_STATUS_IS_OK(status
)) {
7706 /* Move pdata to the start of the default ACL entries. */
7707 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
7709 if (valid_def_acls
) {
7710 status
= set_unix_posix_default_acl(conn
,
7714 if (!NT_STATUS_IS_OK(status
)) {
7719 status
= NT_STATUS_OK
;
7724 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
7731 /****************************************************************************
7732 Deal with SMB_SET_POSIX_LOCK.
7733 ****************************************************************************/
7735 static void smb_set_posix_lock_done(struct tevent_req
*subreq
);
7737 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
7738 struct smb_request
*req
,
7743 struct tevent_req
*subreq
= NULL
;
7744 struct smbd_lock_element
*lck
= NULL
;
7748 bool blocking_lock
= False
;
7749 enum brl_type lock_type
;
7751 NTSTATUS status
= NT_STATUS_OK
;
7754 fsp
->fsp_flags
.is_pathref
||
7755 fsp_get_io_fd(fsp
) == -1)
7757 return NT_STATUS_INVALID_HANDLE
;
7760 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
7761 return NT_STATUS_INVALID_PARAMETER
;
7764 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
7765 case POSIX_LOCK_TYPE_READ
:
7766 lock_type
= READ_LOCK
;
7768 case POSIX_LOCK_TYPE_WRITE
:
7769 /* Return the right POSIX-mappable error code for files opened read-only. */
7770 if (!fsp
->fsp_flags
.can_write
) {
7771 return NT_STATUS_INVALID_HANDLE
;
7773 lock_type
= WRITE_LOCK
;
7775 case POSIX_LOCK_TYPE_UNLOCK
:
7776 lock_type
= UNLOCK_LOCK
;
7779 return NT_STATUS_INVALID_PARAMETER
;
7782 switch (SVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
)) {
7783 case POSIX_LOCK_FLAG_NOWAIT
:
7784 blocking_lock
= false;
7786 case POSIX_LOCK_FLAG_WAIT
:
7787 blocking_lock
= true;
7790 return NT_STATUS_INVALID_PARAMETER
;
7793 if (!lp_blocking_locks(SNUM(conn
))) {
7794 blocking_lock
= False
;
7797 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
7798 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
7799 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
7800 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
7801 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
7803 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64
", "
7804 "count = %"PRIu64
", offset = %"PRIu64
"\n",
7806 (unsigned int)lock_type
,
7811 if (lock_type
== UNLOCK_LOCK
) {
7812 struct smbd_lock_element l
= {
7813 .req_guid
= smbd_request_guid(req
, 0),
7815 .brltype
= UNLOCK_LOCK
,
7819 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, POSIX_LOCK
);
7823 lck
= talloc(req
, struct smbd_lock_element
);
7825 return NT_STATUS_NO_MEMORY
;
7828 *lck
= (struct smbd_lock_element
) {
7829 .req_guid
= smbd_request_guid(req
, 0),
7831 .brltype
= lock_type
,
7836 subreq
= smbd_smb1_do_locks_send(
7841 blocking_lock
? UINT32_MAX
: 0,
7842 true, /* large_offset */
7846 if (subreq
== NULL
) {
7848 return NT_STATUS_NO_MEMORY
;
7850 tevent_req_set_callback(subreq
, smb_set_posix_lock_done
, req
);
7851 return NT_STATUS_EVENT_PENDING
;
7854 static void smb_set_posix_lock_done(struct tevent_req
*subreq
)
7856 struct smb_request
*req
= NULL
;
7860 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
7863 status
= smbd_smb1_do_locks_recv(subreq
);
7864 TALLOC_FREE(subreq
);
7866 if (NT_STATUS_IS_OK(status
)) {
7867 char params
[2] = {0};
7868 /* Fake up max_data_bytes here - we know it fits. */
7869 send_trans2_replies(
7879 reply_nterror(req
, status
);
7882 (char *)req
->outbuf
,
7885 IS_CONN_ENCRYPTED(req
->conn
),
7888 exit_server_cleanly("smb_set_posix_lock_done: "
7889 "srv_send_smb failed.");
7897 /****************************************************************************
7898 Deal with SMB_SET_FILE_BASIC_INFO.
7899 ****************************************************************************/
7901 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
7905 struct smb_filename
*smb_fname
)
7907 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7908 struct smb_file_time ft
;
7909 uint32_t dosmode
= 0;
7910 NTSTATUS status
= NT_STATUS_OK
;
7912 init_smb_file_time(&ft
);
7914 if (total_data
< 36) {
7915 return NT_STATUS_INVALID_PARAMETER
;
7918 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
7919 if (!NT_STATUS_IS_OK(status
)) {
7923 /* Set the attributes */
7924 dosmode
= IVAL(pdata
,32);
7925 status
= smb_set_file_dosmode(conn
, fsp
, smb_fname
, dosmode
);
7926 if (!NT_STATUS_IS_OK(status
)) {
7931 ft
.create_time
= pull_long_date_full_timespec(pdata
);
7934 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
7937 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
7940 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
7942 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7943 smb_fname_str_dbg(smb_fname
)));
7945 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
7946 if (!NT_STATUS_IS_OK(status
)) {
7950 if (fsp
!= NULL
&& fsp
->fsp_flags
.modified
) {
7951 trigger_write_time_update_immediate(fsp
);
7953 return NT_STATUS_OK
;
7956 /****************************************************************************
7957 Deal with SMB_INFO_STANDARD.
7958 ****************************************************************************/
7960 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
7964 struct smb_filename
*smb_fname
)
7967 struct smb_file_time ft
;
7969 init_smb_file_time(&ft
);
7971 if (total_data
< 12) {
7972 return NT_STATUS_INVALID_PARAMETER
;
7976 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
7978 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
7980 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
7982 DEBUG(10,("smb_set_info_standard: file %s\n",
7983 smb_fname_str_dbg(smb_fname
)));
7985 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
7986 if (!NT_STATUS_IS_OK(status
)) {
7990 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
7991 if (!NT_STATUS_IS_OK(status
)) {
7995 if (fsp
!= NULL
&& fsp
->fsp_flags
.modified
) {
7996 trigger_write_time_update_immediate(fsp
);
7998 return NT_STATUS_OK
;
8001 /****************************************************************************
8002 Deal with SMB_SET_FILE_ALLOCATION_INFO.
8003 ****************************************************************************/
8005 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
8006 struct smb_request
*req
,
8010 struct smb_filename
*smb_fname
)
8012 uint64_t allocation_size
= 0;
8013 NTSTATUS status
= NT_STATUS_OK
;
8014 files_struct
*new_fsp
= NULL
;
8016 if (!VALID_STAT(smb_fname
->st
)) {
8017 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8020 if (total_data
< 8) {
8021 return NT_STATUS_INVALID_PARAMETER
;
8024 allocation_size
= (uint64_t)IVAL(pdata
,0);
8025 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
8026 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
8027 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
8028 (double)allocation_size
));
8030 if (allocation_size
) {
8031 allocation_size
= smb_roundup(conn
, allocation_size
);
8034 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
8035 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
8036 (double)allocation_size
));
8039 !fsp
->fsp_flags
.is_pathref
&&
8040 fsp_get_io_fd(fsp
) != -1)
8042 /* Open file handle. */
8043 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
8044 return NT_STATUS_ACCESS_DENIED
;
8047 /* Only change if needed. */
8048 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
8049 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
8050 return map_nt_error_from_unix(errno
);
8053 /* But always update the time. */
8055 * This is equivalent to a write. Ensure it's seen immediately
8056 * if there are no pending writes.
8058 trigger_write_time_update_immediate(fsp
);
8059 return NT_STATUS_OK
;
8062 /* Pathname or stat or directory file. */
8063 status
= SMB_VFS_CREATE_FILE(
8066 smb_fname
, /* fname */
8067 FILE_WRITE_DATA
, /* access_mask */
8068 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8070 FILE_OPEN
, /* create_disposition*/
8071 0, /* create_options */
8072 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
8073 0, /* oplock_request */
8075 0, /* allocation_size */
8076 0, /* private_flags */
8079 &new_fsp
, /* result */
8081 NULL
, NULL
); /* create context */
8083 if (!NT_STATUS_IS_OK(status
)) {
8084 /* NB. We check for open_was_deferred in the caller. */
8088 /* Only change if needed. */
8089 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
8090 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
8091 status
= map_nt_error_from_unix(errno
);
8092 close_file(req
, new_fsp
, NORMAL_CLOSE
);
8097 /* Changing the allocation size should set the last mod time. */
8099 * This is equivalent to a write. Ensure it's seen immediately
8100 * if there are no pending writes.
8102 trigger_write_time_update_immediate(new_fsp
);
8103 close_file(req
, new_fsp
, NORMAL_CLOSE
);
8104 return NT_STATUS_OK
;
8107 /****************************************************************************
8108 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8109 ****************************************************************************/
8111 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
8112 struct smb_request
*req
,
8116 struct smb_filename
*smb_fname
,
8117 bool fail_after_createfile
)
8121 if (total_data
< 8) {
8122 return NT_STATUS_INVALID_PARAMETER
;
8125 size
= IVAL(pdata
,0);
8126 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
8127 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8128 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
8131 return smb_set_file_size(conn
, req
,
8136 fail_after_createfile
);
8139 /****************************************************************************
8140 Allow a UNIX info mknod.
8141 ****************************************************************************/
8143 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
8146 const struct smb_filename
*smb_fname
)
8148 uint32_t file_type
= IVAL(pdata
,56);
8149 #if defined(HAVE_MAKEDEV)
8150 uint32_t dev_major
= IVAL(pdata
,60);
8151 uint32_t dev_minor
= IVAL(pdata
,68);
8153 SMB_DEV_T dev
= (SMB_DEV_T
)0;
8154 uint32_t raw_unixmode
= IVAL(pdata
,84);
8158 struct smb_filename
*parent_fname
= NULL
;
8159 struct smb_filename
*base_name
= NULL
;
8161 if (total_data
< 100) {
8162 return NT_STATUS_INVALID_PARAMETER
;
8165 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8166 PERM_NEW_FILE
, &unixmode
);
8167 if (!NT_STATUS_IS_OK(status
)) {
8171 #if defined(HAVE_MAKEDEV)
8172 dev
= makedev(dev_major
, dev_minor
);
8175 switch (file_type
) {
8176 /* We can't create other objects here. */
8177 case UNIX_TYPE_FILE
:
8179 case UNIX_TYPE_SYMLINK
:
8180 return NT_STATUS_ACCESS_DENIED
;
8181 #if defined(S_IFIFO)
8182 case UNIX_TYPE_FIFO
:
8183 unixmode
|= S_IFIFO
;
8186 #if defined(S_IFSOCK)
8187 case UNIX_TYPE_SOCKET
:
8188 unixmode
|= S_IFSOCK
;
8191 #if defined(S_IFCHR)
8192 case UNIX_TYPE_CHARDEV
:
8193 /* This is only allowed for root. */
8194 if (get_current_uid(conn
) != sec_initial_uid()) {
8195 return NT_STATUS_ACCESS_DENIED
;
8197 unixmode
|= S_IFCHR
;
8200 #if defined(S_IFBLK)
8201 case UNIX_TYPE_BLKDEV
:
8202 if (get_current_uid(conn
) != sec_initial_uid()) {
8203 return NT_STATUS_ACCESS_DENIED
;
8205 unixmode
|= S_IFBLK
;
8209 return NT_STATUS_INVALID_PARAMETER
;
8212 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8213 "%.0f mode 0%o for file %s\n", (double)dev
,
8214 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
8216 status
= parent_pathref(talloc_tos(),
8221 if (!NT_STATUS_IS_OK(status
)) {
8225 /* Ok - do the mknod. */
8226 ret
= SMB_VFS_MKNODAT(conn
,
8233 TALLOC_FREE(parent_fname
);
8234 return map_nt_error_from_unix(errno
);
8237 /* If any of the other "set" calls fail we
8238 * don't want to end up with a half-constructed mknod.
8241 if (lp_inherit_permissions(SNUM(conn
))) {
8242 inherit_access_posix_acl(conn
,
8247 TALLOC_FREE(parent_fname
);
8249 return NT_STATUS_OK
;
8252 /****************************************************************************
8253 Deal with SMB_SET_FILE_UNIX_BASIC.
8254 ****************************************************************************/
8256 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
8257 struct smb_request
*req
,
8261 struct smb_filename
*smb_fname
)
8263 struct smb_file_time ft
;
8264 uint32_t raw_unixmode
;
8267 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
8268 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
8269 NTSTATUS status
= NT_STATUS_OK
;
8270 enum perm_type ptype
;
8271 files_struct
*all_fsps
= NULL
;
8272 bool modify_mtime
= true;
8274 SMB_STRUCT_STAT sbuf
;
8276 init_smb_file_time(&ft
);
8278 if (total_data
< 100) {
8279 return NT_STATUS_INVALID_PARAMETER
;
8282 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
8283 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
8284 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
8285 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
8288 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
8289 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
8290 set_owner
= (uid_t
)IVAL(pdata
,40);
8291 set_grp
= (gid_t
)IVAL(pdata
,48);
8292 raw_unixmode
= IVAL(pdata
,84);
8294 if (VALID_STAT(smb_fname
->st
)) {
8295 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
8296 ptype
= PERM_EXISTING_DIR
;
8298 ptype
= PERM_EXISTING_FILE
;
8301 ptype
= PERM_NEW_FILE
;
8304 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8306 if (!NT_STATUS_IS_OK(status
)) {
8310 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8311 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8312 smb_fname_str_dbg(smb_fname
), (double)size
,
8313 (unsigned int)set_owner
, (unsigned int)set_grp
,
8314 (int)raw_unixmode
));
8316 sbuf
= smb_fname
->st
;
8318 if (!VALID_STAT(sbuf
)) {
8320 * The only valid use of this is to create character and block
8321 * devices, and named pipes. This is deprecated (IMHO) and
8322 * a new info level should be used for mknod. JRA.
8325 return smb_unix_mknod(conn
,
8332 /* Horrible backwards compatibility hack as an old server bug
8333 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8337 size
= get_file_size_stat(&sbuf
);
8342 * Deal with the UNIX specific mode set.
8345 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
8348 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8349 "setting mode 0%o for file %s\n",
8350 (unsigned int)unixmode
,
8351 smb_fname_str_dbg(smb_fname
)));
8353 !fsp
->fsp_flags
.is_pathref
&&
8354 fsp_get_io_fd(fsp
) != -1)
8356 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
8358 ret
= SMB_VFS_CHMOD(conn
, smb_fname
, unixmode
);
8361 return map_nt_error_from_unix(errno
);
8366 * Deal with the UNIX specific uid set.
8369 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
8370 (sbuf
.st_ex_uid
!= set_owner
)) {
8373 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8374 "changing owner %u for path %s\n",
8375 (unsigned int)set_owner
,
8376 smb_fname_str_dbg(smb_fname
)));
8379 !fsp
->fsp_flags
.is_pathref
&&
8380 fsp_get_io_fd(fsp
) != -1)
8382 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
8385 * UNIX extensions calls must always operate
8388 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
8389 set_owner
, (gid_t
)-1);
8393 status
= map_nt_error_from_unix(errno
);
8399 * Deal with the UNIX specific gid set.
8402 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
8403 (sbuf
.st_ex_gid
!= set_grp
)) {
8406 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8407 "changing group %u for file %s\n",
8408 (unsigned int)set_grp
,
8409 smb_fname_str_dbg(smb_fname
)));
8411 !fsp
->fsp_flags
.is_pathref
&&
8412 fsp_get_io_fd(fsp
) != -1)
8414 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
8417 * UNIX extensions calls must always operate
8420 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
8424 status
= map_nt_error_from_unix(errno
);
8429 /* Deal with any size changes. */
8431 if (S_ISREG(sbuf
.st_ex_mode
)) {
8432 status
= smb_set_file_size(conn
, req
,
8438 if (!NT_STATUS_IS_OK(status
)) {
8443 /* Deal with any time changes. */
8444 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
8445 /* No change, don't cancel anything. */
8449 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
8450 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
8451 all_fsps
= file_find_di_next(all_fsps
, true)) {
8453 * We're setting the time explicitly for UNIX.
8454 * Cancel any pending changes over all handles.
8456 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
8457 TALLOC_FREE(all_fsps
->update_write_time_event
);
8461 * Override the "setting_write_time"
8462 * parameter here as it almost does what
8463 * we need. Just remember if we modified
8464 * mtime and send the notify ourselves.
8466 if (is_omit_timespec(&ft
.mtime
)) {
8467 modify_mtime
= false;
8470 status
= smb_set_file_time(conn
,
8476 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
8477 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
8482 /****************************************************************************
8483 Deal with SMB_SET_FILE_UNIX_INFO2.
8484 ****************************************************************************/
8486 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
8487 struct smb_request
*req
,
8491 struct smb_filename
*smb_fname
)
8494 uint32_t smb_fflags
;
8497 if (total_data
< 116) {
8498 return NT_STATUS_INVALID_PARAMETER
;
8501 /* Start by setting all the fields that are common between UNIX_BASIC
8504 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
8506 if (!NT_STATUS_IS_OK(status
)) {
8510 smb_fflags
= IVAL(pdata
, 108);
8511 smb_fmask
= IVAL(pdata
, 112);
8513 /* NB: We should only attempt to alter the file flags if the client
8514 * sends a non-zero mask.
8516 if (smb_fmask
!= 0) {
8517 int stat_fflags
= 0;
8519 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
8520 smb_fmask
, &stat_fflags
)) {
8521 /* Client asked to alter a flag we don't understand. */
8522 return NT_STATUS_INVALID_PARAMETER
;
8526 !fsp
->fsp_flags
.is_pathref
&&
8527 fsp_get_io_fd(fsp
) != -1)
8529 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8530 return NT_STATUS_NOT_SUPPORTED
;
8532 if (SMB_VFS_CHFLAGS(conn
, smb_fname
,
8533 stat_fflags
) != 0) {
8534 return map_nt_error_from_unix(errno
);
8539 /* XXX: need to add support for changing the create_time here. You
8540 * can do this for paths on Darwin with setattrlist(2). The right way
8541 * to hook this up is probably by extending the VFS utimes interface.
8544 return NT_STATUS_OK
;
8547 /****************************************************************************
8548 Create a directory with POSIX semantics.
8549 ****************************************************************************/
8551 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
8552 struct smb_request
*req
,
8555 struct smb_filename
*smb_fname
,
8556 int *pdata_return_size
)
8558 NTSTATUS status
= NT_STATUS_OK
;
8559 uint32_t raw_unixmode
= 0;
8560 mode_t unixmode
= (mode_t
)0;
8561 files_struct
*fsp
= NULL
;
8562 uint16_t info_level_return
= 0;
8564 char *pdata
= *ppdata
;
8565 struct smb2_create_blobs
*posx
= NULL
;
8567 if (total_data
< 18) {
8568 return NT_STATUS_INVALID_PARAMETER
;
8571 raw_unixmode
= IVAL(pdata
,8);
8572 /* Next 4 bytes are not yet defined. */
8574 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8575 PERM_NEW_DIR
, &unixmode
);
8576 if (!NT_STATUS_IS_OK(status
)) {
8580 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
8581 if (!NT_STATUS_IS_OK(status
)) {
8582 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8587 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8588 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
8590 status
= SMB_VFS_CREATE_FILE(
8593 smb_fname
, /* fname */
8594 FILE_READ_ATTRIBUTES
, /* access_mask */
8595 FILE_SHARE_NONE
, /* share_access */
8596 FILE_CREATE
, /* create_disposition*/
8597 FILE_DIRECTORY_FILE
, /* create_options */
8598 0, /* file_attributes */
8599 0, /* oplock_request */
8601 0, /* allocation_size */
8602 0, /* private_flags */
8607 posx
, /* in_context_blobs */
8608 NULL
); /* out_context_blobs */
8612 if (NT_STATUS_IS_OK(status
)) {
8613 close_file(req
, fsp
, NORMAL_CLOSE
);
8616 info_level_return
= SVAL(pdata
,16);
8618 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8619 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8620 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8621 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8623 *pdata_return_size
= 12;
8626 /* Realloc the data size */
8627 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8628 if (*ppdata
== NULL
) {
8629 *pdata_return_size
= 0;
8630 return NT_STATUS_NO_MEMORY
;
8634 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8635 SSVAL(pdata
,2,0); /* No fnum. */
8636 SIVAL(pdata
,4,info
); /* Was directory created. */
8638 switch (info_level_return
) {
8639 case SMB_QUERY_FILE_UNIX_BASIC
:
8640 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8641 SSVAL(pdata
,10,0); /* Padding. */
8642 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8645 case SMB_QUERY_FILE_UNIX_INFO2
:
8646 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8647 SSVAL(pdata
,10,0); /* Padding. */
8648 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8652 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8653 SSVAL(pdata
,10,0); /* Padding. */
8660 /****************************************************************************
8661 Open/Create a file with POSIX semantics.
8662 ****************************************************************************/
8664 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8665 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8667 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
8668 struct smb_request
*req
,
8671 struct smb_filename
*smb_fname
,
8672 int *pdata_return_size
)
8674 bool extended_oplock_granted
= False
;
8675 char *pdata
= *ppdata
;
8677 uint32_t wire_open_mode
= 0;
8678 uint32_t raw_unixmode
= 0;
8679 uint32_t attributes
= 0;
8680 uint32_t create_disp
= 0;
8681 uint32_t access_mask
= 0;
8682 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
8683 NTSTATUS status
= NT_STATUS_OK
;
8684 mode_t unixmode
= (mode_t
)0;
8685 files_struct
*fsp
= NULL
;
8686 int oplock_request
= 0;
8688 uint16_t info_level_return
= 0;
8689 struct smb2_create_blobs
*posx
= NULL
;
8691 if (total_data
< 18) {
8692 return NT_STATUS_INVALID_PARAMETER
;
8695 flags
= IVAL(pdata
,0);
8696 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
8697 if (oplock_request
) {
8698 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
8701 wire_open_mode
= IVAL(pdata
,4);
8703 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
8704 return smb_posix_mkdir(conn
, req
,
8711 switch (wire_open_mode
& SMB_ACCMODE
) {
8713 access_mask
= SMB_O_RDONLY_MAPPING
;
8716 access_mask
= SMB_O_WRONLY_MAPPING
;
8719 access_mask
= (SMB_O_RDONLY_MAPPING
|
8720 SMB_O_WRONLY_MAPPING
);
8723 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8724 (unsigned int)wire_open_mode
));
8725 return NT_STATUS_INVALID_PARAMETER
;
8728 wire_open_mode
&= ~SMB_ACCMODE
;
8730 /* First take care of O_CREAT|O_EXCL interactions. */
8731 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
8732 case (SMB_O_CREAT
| SMB_O_EXCL
):
8733 /* File exists fail. File not exist create. */
8734 create_disp
= FILE_CREATE
;
8737 /* File exists open. File not exist create. */
8738 create_disp
= FILE_OPEN_IF
;
8741 /* O_EXCL on its own without O_CREAT is undefined.
8742 We deliberately ignore it as some versions of
8743 Linux CIFSFS can send a bare O_EXCL on the
8744 wire which other filesystems in the kernel
8745 ignore. See bug 9519 for details. */
8750 /* File exists open. File not exist fail. */
8751 create_disp
= FILE_OPEN
;
8754 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8755 (unsigned int)wire_open_mode
));
8756 return NT_STATUS_INVALID_PARAMETER
;
8759 /* Next factor in the effects of O_TRUNC. */
8760 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
8762 if (wire_open_mode
& SMB_O_TRUNC
) {
8763 switch (create_disp
) {
8765 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8766 /* Leave create_disp alone as
8767 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8769 /* File exists fail. File not exist create. */
8772 /* SMB_O_CREAT | SMB_O_TRUNC */
8773 /* File exists overwrite. File not exist create. */
8774 create_disp
= FILE_OVERWRITE_IF
;
8778 /* File exists overwrite. File not exist fail. */
8779 create_disp
= FILE_OVERWRITE
;
8782 /* Cannot get here. */
8783 smb_panic("smb_posix_open: logic error");
8784 return NT_STATUS_INVALID_PARAMETER
;
8788 raw_unixmode
= IVAL(pdata
,8);
8789 /* Next 4 bytes are not yet defined. */
8791 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8792 (VALID_STAT(smb_fname
->st
) ?
8793 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
8796 if (!NT_STATUS_IS_OK(status
)) {
8800 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
8801 if (!NT_STATUS_IS_OK(status
)) {
8802 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8807 if (wire_open_mode
& SMB_O_SYNC
) {
8808 create_options
|= FILE_WRITE_THROUGH
;
8810 if (wire_open_mode
& SMB_O_APPEND
) {
8811 access_mask
|= FILE_APPEND_DATA
;
8813 if (wire_open_mode
& SMB_O_DIRECT
) {
8814 attributes
|= FILE_FLAG_NO_BUFFERING
;
8817 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
8818 VALID_STAT_OF_DIR(smb_fname
->st
)) {
8819 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
8820 return NT_STATUS_FILE_IS_A_DIRECTORY
;
8822 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
8823 create_options
|= FILE_DIRECTORY_FILE
;
8826 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8827 smb_fname_str_dbg(smb_fname
),
8828 (unsigned int)wire_open_mode
,
8829 (unsigned int)unixmode
));
8831 status
= SMB_VFS_CREATE_FILE(
8834 smb_fname
, /* fname */
8835 access_mask
, /* access_mask */
8836 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8838 create_disp
, /* create_disposition*/
8839 create_options
, /* create_options */
8840 attributes
, /* file_attributes */
8841 oplock_request
, /* oplock_request */
8843 0, /* allocation_size */
8844 0, /* private_flags */
8849 posx
, /* in_context_blobs */
8850 NULL
); /* out_context_blobs */
8854 if (!NT_STATUS_IS_OK(status
)) {
8858 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
8859 extended_oplock_granted
= True
;
8862 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
8863 extended_oplock_granted
= True
;
8866 info_level_return
= SVAL(pdata
,16);
8868 /* Allocate the correct return size. */
8870 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8871 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8872 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8873 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8875 *pdata_return_size
= 12;
8878 /* Realloc the data size */
8879 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8880 if (*ppdata
== NULL
) {
8881 close_file(req
, fsp
, ERROR_CLOSE
);
8882 *pdata_return_size
= 0;
8883 return NT_STATUS_NO_MEMORY
;
8887 if (extended_oplock_granted
) {
8888 if (flags
& REQUEST_BATCH_OPLOCK
) {
8889 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
8891 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
8893 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
8894 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
8896 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8899 SSVAL(pdata
,2,fsp
->fnum
);
8900 SIVAL(pdata
,4,info
); /* Was file created etc. */
8902 switch (info_level_return
) {
8903 case SMB_QUERY_FILE_UNIX_BASIC
:
8904 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8905 SSVAL(pdata
,10,0); /* padding. */
8906 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8909 case SMB_QUERY_FILE_UNIX_INFO2
:
8910 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8911 SSVAL(pdata
,10,0); /* padding. */
8912 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8916 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8917 SSVAL(pdata
,10,0); /* padding. */
8920 return NT_STATUS_OK
;
8923 /****************************************************************************
8924 Delete a file with POSIX semantics.
8925 ****************************************************************************/
8927 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
8928 struct smb_request
*req
,
8931 struct smb_filename
*smb_fname
)
8933 NTSTATUS status
= NT_STATUS_OK
;
8934 files_struct
*fsp
= NULL
;
8938 int create_options
= 0;
8939 struct share_mode_lock
*lck
= NULL
;
8940 bool other_nonposix_opens
;
8941 struct smb2_create_blobs
*posx
= NULL
;
8943 if (total_data
< 2) {
8944 return NT_STATUS_INVALID_PARAMETER
;
8947 flags
= SVAL(pdata
,0);
8949 if (!VALID_STAT(smb_fname
->st
)) {
8950 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8953 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
8954 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
8955 return NT_STATUS_NOT_A_DIRECTORY
;
8958 DEBUG(10,("smb_posix_unlink: %s %s\n",
8959 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
8960 smb_fname_str_dbg(smb_fname
)));
8962 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
8963 create_options
|= FILE_DIRECTORY_FILE
;
8966 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
8967 if (!NT_STATUS_IS_OK(status
)) {
8968 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8973 status
= SMB_VFS_CREATE_FILE(
8976 smb_fname
, /* fname */
8977 DELETE_ACCESS
, /* access_mask */
8978 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8980 FILE_OPEN
, /* create_disposition*/
8981 create_options
, /* create_options */
8982 0, /* file_attributes */
8983 0, /* oplock_request */
8985 0, /* allocation_size */
8986 0, /* private_flags */
8991 posx
, /* in_context_blobs */
8992 NULL
); /* out_context_blobs */
8996 if (!NT_STATUS_IS_OK(status
)) {
9001 * Don't lie to client. If we can't really delete due to
9002 * non-POSIX opens return SHARING_VIOLATION.
9005 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
9007 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
9008 "lock for file %s\n", fsp_str_dbg(fsp
)));
9009 close_file(req
, fsp
, NORMAL_CLOSE
);
9010 return NT_STATUS_INVALID_PARAMETER
;
9013 other_nonposix_opens
= has_other_nonposix_opens(lck
, fsp
);
9014 if (other_nonposix_opens
) {
9015 /* Fail with sharing violation. */
9017 close_file(req
, fsp
, NORMAL_CLOSE
);
9018 return NT_STATUS_SHARING_VIOLATION
;
9022 * Set the delete on close.
9024 status
= smb_set_file_disposition_info(conn
,
9032 if (!NT_STATUS_IS_OK(status
)) {
9033 close_file(req
, fsp
, NORMAL_CLOSE
);
9036 return close_file(req
, fsp
, NORMAL_CLOSE
);
9039 static NTSTATUS
smbd_do_posix_setfilepathinfo(struct connection_struct
*conn
,
9040 struct smb_request
*req
,
9041 TALLOC_CTX
*mem_ctx
,
9042 uint16_t info_level
,
9043 struct smb_filename
*smb_fname
,
9049 char *pdata
= *ppdata
;
9050 NTSTATUS status
= NT_STATUS_OK
;
9051 int data_return_size
= 0;
9055 if (!CAN_WRITE(conn
)) {
9056 /* Allow POSIX opens. The open path will deny
9057 * any non-readonly opens. */
9058 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
9059 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
9063 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
9064 smb_fname_str_dbg(smb_fname
),
9069 switch (info_level
) {
9070 case SMB_SET_FILE_UNIX_BASIC
:
9072 status
= smb_set_file_unix_basic(conn
, req
,
9080 case SMB_SET_FILE_UNIX_INFO2
:
9082 status
= smb_set_file_unix_info2(conn
, req
,
9090 case SMB_SET_FILE_UNIX_LINK
:
9092 if (smb_fname
== NULL
) {
9093 /* We must have a pathname for this. */
9094 return NT_STATUS_INVALID_LEVEL
;
9096 status
= smb_set_file_unix_link(conn
, req
, pdata
,
9097 total_data
, smb_fname
);
9101 case SMB_SET_FILE_UNIX_HLINK
:
9103 if (smb_fname
== NULL
) {
9104 /* We must have a pathname for this. */
9105 return NT_STATUS_INVALID_LEVEL
;
9107 status
= smb_set_file_unix_hlink(conn
, req
,
9113 #if defined(HAVE_POSIX_ACLS)
9114 case SMB_SET_POSIX_ACL
:
9116 status
= smb_set_posix_acl(conn
,
9126 case SMB_SET_POSIX_LOCK
:
9129 return NT_STATUS_INVALID_LEVEL
;
9131 status
= smb_set_posix_lock(conn
, req
,
9132 pdata
, total_data
, fsp
);
9136 case SMB_POSIX_PATH_OPEN
:
9138 if (smb_fname
== NULL
) {
9139 /* We must have a pathname for this. */
9140 return NT_STATUS_INVALID_LEVEL
;
9143 status
= smb_posix_open(conn
, req
,
9151 case SMB_POSIX_PATH_UNLINK
:
9153 if (smb_fname
== NULL
) {
9154 /* We must have a pathname for this. */
9155 return NT_STATUS_INVALID_LEVEL
;
9158 status
= smb_posix_unlink(conn
, req
,
9166 return NT_STATUS_INVALID_LEVEL
;
9169 if (!NT_STATUS_IS_OK(status
)) {
9173 *ret_data_size
= data_return_size
;
9174 return NT_STATUS_OK
;
9177 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
9178 struct smb_request
*req
,
9179 TALLOC_CTX
*mem_ctx
,
9180 uint16_t info_level
,
9182 struct smb_filename
*smb_fname
,
9183 char **ppdata
, int total_data
,
9186 char *pdata
= *ppdata
;
9187 NTSTATUS status
= NT_STATUS_OK
;
9188 int data_return_size
= 0;
9190 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9191 if (!lp_unix_extensions()) {
9192 return NT_STATUS_INVALID_LEVEL
;
9195 status
= smbd_do_posix_setfilepathinfo(conn
,
9204 if (!NT_STATUS_IS_OK(status
)) {
9207 *ret_data_size
= data_return_size
;
9208 return NT_STATUS_OK
;
9213 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9214 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
9216 info_level
, total_data
));
9218 switch (info_level
) {
9220 case SMB_INFO_STANDARD
:
9222 status
= smb_set_info_standard(conn
,
9230 case SMB_INFO_SET_EA
:
9232 status
= smb_info_set_ea(conn
,
9240 case SMB_SET_FILE_BASIC_INFO
:
9241 case SMB_FILE_BASIC_INFORMATION
:
9243 status
= smb_set_file_basic_info(conn
,
9251 case SMB_FILE_ALLOCATION_INFORMATION
:
9252 case SMB_SET_FILE_ALLOCATION_INFO
:
9254 status
= smb_set_file_allocation_info(conn
, req
,
9262 case SMB_FILE_END_OF_FILE_INFORMATION
:
9263 case SMB_SET_FILE_END_OF_FILE_INFO
:
9266 * XP/Win7 both fail after the createfile with
9267 * SMB_SET_FILE_END_OF_FILE_INFO but not
9268 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9269 * The level is known here, so pass it down
9273 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
9275 status
= smb_set_file_end_of_file_info(conn
, req
,
9284 case SMB_FILE_DISPOSITION_INFORMATION
:
9285 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
9288 /* JRA - We used to just ignore this on a path ?
9289 * Shouldn't this be invalid level on a pathname
9292 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
9293 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
9296 status
= smb_set_file_disposition_info(conn
,
9304 case SMB_FILE_POSITION_INFORMATION
:
9306 status
= smb_file_position_information(conn
,
9313 case SMB_FILE_FULL_EA_INFORMATION
:
9315 status
= smb_set_file_full_ea_info(conn
,
9322 /* From tridge Samba4 :
9323 * MODE_INFORMATION in setfileinfo (I have no
9324 * idea what "mode information" on a file is - it takes a value of 0,
9325 * 2, 4 or 6. What could it be?).
9328 case SMB_FILE_MODE_INFORMATION
:
9330 status
= smb_file_mode_information(conn
,
9336 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9337 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
9338 case SMB_FILE_SHORT_NAME_INFORMATION
:
9339 return NT_STATUS_NOT_SUPPORTED
;
9341 case SMB_FILE_RENAME_INFORMATION
:
9343 status
= smb_file_rename_information(conn
, req
,
9349 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
9351 /* SMB2 rename information. */
9352 status
= smb2_file_rename_information(conn
, req
,
9358 case SMB_FILE_LINK_INFORMATION
:
9360 status
= smb_file_link_information(conn
, req
,
9367 return NT_STATUS_INVALID_LEVEL
;
9370 if (!NT_STATUS_IS_OK(status
)) {
9374 *ret_data_size
= data_return_size
;
9375 return NT_STATUS_OK
;
9378 /****************************************************************************
9379 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9380 ****************************************************************************/
9382 static void call_trans2setfilepathinfo(connection_struct
*conn
,
9383 struct smb_request
*req
,
9384 unsigned int tran_call
,
9385 char **pparams
, int total_params
,
9386 char **ppdata
, int total_data
,
9387 unsigned int max_data_bytes
)
9389 char *params
= *pparams
;
9390 char *pdata
= *ppdata
;
9391 uint16_t info_level
;
9392 struct smb_filename
*smb_fname
= NULL
;
9393 files_struct
*fsp
= NULL
;
9394 NTSTATUS status
= NT_STATUS_OK
;
9395 int data_return_size
= 0;
9398 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9402 if (tran_call
== TRANSACT2_SETFILEINFO
) {
9403 if (total_params
< 4) {
9404 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9408 fsp
= file_fsp(req
, SVAL(params
,0));
9409 /* Basic check for non-null fsp. */
9410 if (!check_fsp_open(conn
, req
, fsp
)) {
9413 info_level
= SVAL(params
,2);
9415 smb_fname
= fsp
->fsp_name
;
9417 if (fsp_get_pathref_fd(fsp
) == -1) {
9419 * This is actually a SETFILEINFO on a directory
9420 * handle (returned from an NT SMB). NT5.0 seems
9421 * to do this call. JRA.
9423 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9424 /* Always do lstat for UNIX calls. */
9425 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
9426 DEBUG(3,("call_trans2setfilepathinfo: "
9427 "SMB_VFS_LSTAT of %s failed "
9429 smb_fname_str_dbg(smb_fname
),
9431 reply_nterror(req
, map_nt_error_from_unix(errno
));
9435 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
9436 DEBUG(3,("call_trans2setfilepathinfo: "
9437 "fileinfo of %s failed (%s)\n",
9438 smb_fname_str_dbg(smb_fname
),
9440 reply_nterror(req
, map_nt_error_from_unix(errno
));
9444 } else if (fsp
->print_file
) {
9446 * Doing a DELETE_ON_CLOSE should cancel a print job.
9448 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
9449 uint32_t new_private_options
=
9450 fh_get_private_options(fsp
->fh
);
9451 new_private_options
|=
9452 NTCREATEX_FLAG_DELETE_ON_CLOSE
;
9453 fh_set_private_options(fsp
->fh
,
9454 new_private_options
);
9456 DEBUG(3,("call_trans2setfilepathinfo: "
9457 "Cancelling print job (%s)\n",
9461 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
9467 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
9472 * Original code - this is an open file.
9474 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
9475 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9476 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
9478 reply_nterror(req
, map_nt_error_from_unix(errno
));
9484 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9487 if (total_params
< 7) {
9488 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9492 info_level
= SVAL(params
,0);
9493 if (req
->posix_pathnames
) {
9494 srvstr_get_path_posix(req
,
9503 srvstr_get_path(req
,
9512 if (!NT_STATUS_IS_OK(status
)) {
9513 reply_nterror(req
, status
);
9517 status
= filename_convert(req
, conn
,
9522 if (!NT_STATUS_IS_OK(status
)) {
9523 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9524 reply_botherror(req
,
9525 NT_STATUS_PATH_NOT_COVERED
,
9526 ERRSRV
, ERRbadpath
);
9529 reply_nterror(req
, status
);
9534 * smb_fname->fsp may be NULL if smb_fname points at a symlink
9535 * and we're in POSIX context, so be careful when using fsp
9536 * below, it can still be NULL.
9538 fsp
= smb_fname
->fsp
;
9540 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9542 * For CIFS UNIX extensions the target name may not exist.
9545 /* Always do lstat for UNIX calls. */
9546 SMB_VFS_LSTAT(conn
, smb_fname
);
9548 } else if (!VALID_STAT(smb_fname
->st
) &&
9549 SMB_VFS_STAT(conn
, smb_fname
)) {
9550 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9552 smb_fname_str_dbg(smb_fname
),
9554 reply_nterror(req
, map_nt_error_from_unix(errno
));
9559 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9560 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
9562 info_level
,total_data
));
9564 /* Realloc the parameter size */
9565 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9566 if (*pparams
== NULL
) {
9567 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9574 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
9580 if (!NT_STATUS_IS_OK(status
)) {
9581 if (open_was_deferred(req
->xconn
, req
->mid
)) {
9582 /* We have re-scheduled this call. */
9585 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
9586 bool ok
= defer_smb1_sharing_violation(req
);
9591 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
9592 /* We have re-scheduled this call. */
9595 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9596 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
9597 ERRSRV
, ERRbadpath
);
9600 if (info_level
== SMB_POSIX_PATH_OPEN
) {
9601 reply_openerror(req
, status
);
9606 * Invalid EA name needs to return 2 param bytes,
9607 * not a zero-length error packet.
9609 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
9610 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
9613 reply_nterror(req
, status
);
9618 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
9624 /****************************************************************************
9625 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9626 ****************************************************************************/
9628 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
9629 char **pparams
, int total_params
,
9630 char **ppdata
, int total_data
,
9631 unsigned int max_data_bytes
)
9633 struct files_struct
*fsp
= NULL
;
9634 struct smb_filename
*smb_dname
= NULL
;
9635 char *params
= *pparams
;
9636 char *pdata
= *ppdata
;
9637 char *directory
= NULL
;
9638 NTSTATUS status
= NT_STATUS_OK
;
9639 struct ea_list
*ea_list
= NULL
;
9640 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9641 TALLOC_CTX
*ctx
= talloc_tos();
9643 if (!CAN_WRITE(conn
)) {
9644 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9648 if (total_params
< 5) {
9649 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9653 if (req
->posix_pathnames
) {
9654 srvstr_get_path_posix(ctx
,
9663 srvstr_get_path(ctx
,
9672 if (!NT_STATUS_IS_OK(status
)) {
9673 reply_nterror(req
, status
);
9677 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
9679 status
= filename_convert(ctx
,
9686 if (!NT_STATUS_IS_OK(status
)) {
9687 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9688 reply_botherror(req
,
9689 NT_STATUS_PATH_NOT_COVERED
,
9690 ERRSRV
, ERRbadpath
);
9693 reply_nterror(req
, status
);
9698 * OS/2 workplace shell seems to send SET_EA requests of "null"
9699 * length (4 bytes containing IVAL 4).
9700 * They seem to have no effect. Bug #3212. JRA.
9703 if (total_data
&& (total_data
!= 4)) {
9704 /* Any data in this call is an EA list. */
9705 if (total_data
< 10) {
9706 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9710 if (IVAL(pdata
,0) > total_data
) {
9711 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9712 IVAL(pdata
,0), (unsigned int)total_data
));
9713 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9717 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
9720 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9724 if (!lp_ea_support(SNUM(conn
))) {
9725 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
9729 /* If total_data == 4 Windows doesn't care what values
9730 * are placed in that field, it just ignores them.
9731 * The System i QNTC IBM SMB client puts bad values here,
9732 * so ignore them. */
9734 status
= SMB_VFS_CREATE_FILE(
9737 smb_dname
, /* fname */
9738 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
9739 FILE_SHARE_NONE
, /* share_access */
9740 FILE_CREATE
, /* create_disposition*/
9741 FILE_DIRECTORY_FILE
, /* create_options */
9742 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
9743 0, /* oplock_request */
9745 0, /* allocation_size */
9746 0, /* private_flags */
9751 NULL
, NULL
); /* create context */
9752 if (!NT_STATUS_IS_OK(status
)) {
9753 reply_nterror(req
, status
);
9757 /* Try and set any given EA. */
9759 status
= set_ea(conn
, fsp
, ea_list
);
9760 if (!NT_STATUS_IS_OK(status
)) {
9761 reply_nterror(req
, status
);
9766 /* Realloc the parameter and data sizes */
9767 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9768 if(*pparams
== NULL
) {
9769 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9776 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
9780 close_file(NULL
, fsp
, NORMAL_CLOSE
);
9783 TALLOC_FREE(smb_dname
);
9787 /****************************************************************************
9788 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9789 We don't actually do this - we just send a null response.
9790 ****************************************************************************/
9792 static void call_trans2findnotifyfirst(connection_struct
*conn
,
9793 struct smb_request
*req
,
9794 char **pparams
, int total_params
,
9795 char **ppdata
, int total_data
,
9796 unsigned int max_data_bytes
)
9798 char *params
= *pparams
;
9799 uint16_t info_level
;
9801 if (total_params
< 6) {
9802 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9806 info_level
= SVAL(params
,4);
9807 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
9809 switch (info_level
) {
9814 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
9818 /* Realloc the parameter and data sizes */
9819 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
9820 if (*pparams
== NULL
) {
9821 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9826 SSVAL(params
,0,fnf_handle
);
9827 SSVAL(params
,2,0); /* No changes */
9828 SSVAL(params
,4,0); /* No EA errors */
9835 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
9840 /****************************************************************************
9841 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9842 changes). Currently this does nothing.
9843 ****************************************************************************/
9845 static void call_trans2findnotifynext(connection_struct
*conn
,
9846 struct smb_request
*req
,
9847 char **pparams
, int total_params
,
9848 char **ppdata
, int total_data
,
9849 unsigned int max_data_bytes
)
9851 char *params
= *pparams
;
9853 DEBUG(3,("call_trans2findnotifynext\n"));
9855 /* Realloc the parameter and data sizes */
9856 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
9857 if (*pparams
== NULL
) {
9858 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9863 SSVAL(params
,0,0); /* No changes */
9864 SSVAL(params
,2,0); /* No EA errors */
9866 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
9871 /****************************************************************************
9872 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9873 ****************************************************************************/
9875 static void call_trans2getdfsreferral(connection_struct
*conn
,
9876 struct smb_request
*req
,
9877 char **pparams
, int total_params
,
9878 char **ppdata
, int total_data
,
9879 unsigned int max_data_bytes
)
9881 char *params
= *pparams
;
9882 char *pathname
= NULL
;
9884 int max_referral_level
;
9885 NTSTATUS status
= NT_STATUS_OK
;
9886 TALLOC_CTX
*ctx
= talloc_tos();
9888 DEBUG(10,("call_trans2getdfsreferral\n"));
9890 if (total_params
< 3) {
9891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9895 max_referral_level
= SVAL(params
,0);
9897 if(!lp_host_msdfs()) {
9898 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9902 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
9903 total_params
- 2, STR_TERMINATE
);
9905 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
9908 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
9909 ppdata
,&status
)) < 0) {
9910 reply_nterror(req
, status
);
9914 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
9915 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
9916 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
9921 #define LMCAT_SPL 0x53
9922 #define LMFUNC_GETJOBID 0x60
9924 /****************************************************************************
9925 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9926 ****************************************************************************/
9928 static void call_trans2ioctl(connection_struct
*conn
,
9929 struct smb_request
*req
,
9930 char **pparams
, int total_params
,
9931 char **ppdata
, int total_data
,
9932 unsigned int max_data_bytes
)
9934 const struct loadparm_substitution
*lp_sub
=
9935 loadparm_s3_global_substitution();
9936 char *pdata
= *ppdata
;
9937 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
9941 /* check for an invalid fid before proceeding */
9944 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9948 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9949 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9950 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
9951 if (*ppdata
== NULL
) {
9952 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9957 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9958 CAN ACCEPT THIS IN UNICODE. JRA. */
9961 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
9963 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
9964 lp_netbios_name(), 15,
9965 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
9966 if (!NT_STATUS_IS_OK(status
)) {
9967 reply_nterror(req
, status
);
9970 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
9971 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
9972 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
9973 if (!NT_STATUS_IS_OK(status
)) {
9974 reply_nterror(req
, status
);
9977 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
9982 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9983 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9986 /****************************************************************************
9987 Reply to a SMBfindclose (stop trans2 directory search).
9988 ****************************************************************************/
9990 void reply_findclose(struct smb_request
*req
)
9993 struct smbd_server_connection
*sconn
= req
->sconn
;
9994 files_struct
*fsp
= NULL
;
9996 START_PROFILE(SMBfindclose
);
9999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10000 END_PROFILE(SMBfindclose
);
10004 dptr_num
= SVALS(req
->vwv
+0, 0);
10006 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
10009 * OS/2 seems to use -1 to indicate "close all directories"
10010 * This has to mean on this specific connection struct.
10012 if (dptr_num
== -1) {
10013 dptr_closecnum(req
->conn
);
10015 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
10018 close_file(NULL
, fsp
, NORMAL_CLOSE
);
10023 reply_outbuf(req
, 0, 0);
10025 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
10027 END_PROFILE(SMBfindclose
);
10031 /****************************************************************************
10032 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
10033 ****************************************************************************/
10035 void reply_findnclose(struct smb_request
*req
)
10039 START_PROFILE(SMBfindnclose
);
10041 if (req
->wct
< 1) {
10042 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10043 END_PROFILE(SMBfindnclose
);
10047 dptr_num
= SVAL(req
->vwv
+0, 0);
10049 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
10051 /* We never give out valid handles for a
10052 findnotifyfirst - so any dptr_num is ok here.
10055 reply_outbuf(req
, 0, 0);
10057 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
10059 END_PROFILE(SMBfindnclose
);
10063 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
10064 struct trans_state
*state
)
10066 if (get_Protocol() >= PROTOCOL_NT1
) {
10067 req
->flags2
|= 0x40; /* IS_LONG_NAME */
10068 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
10071 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
10072 if (state
->call
!= TRANSACT2_QFSINFO
&&
10073 state
->call
!= TRANSACT2_SETFSINFO
) {
10074 DEBUG(0,("handle_trans2: encryption required "
10075 "with call 0x%x\n",
10076 (unsigned int)state
->call
));
10077 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
10082 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
10084 /* Now we must call the relevant TRANS2 function */
10085 switch(state
->call
) {
10086 case TRANSACT2_OPEN
:
10088 START_PROFILE(Trans2_open
);
10089 call_trans2open(conn
, req
,
10090 &state
->param
, state
->total_param
,
10091 &state
->data
, state
->total_data
,
10092 state
->max_data_return
);
10093 END_PROFILE(Trans2_open
);
10097 case TRANSACT2_FINDFIRST
:
10099 START_PROFILE(Trans2_findfirst
);
10100 call_trans2findfirst(conn
, req
,
10101 &state
->param
, state
->total_param
,
10102 &state
->data
, state
->total_data
,
10103 state
->max_data_return
);
10104 END_PROFILE(Trans2_findfirst
);
10108 case TRANSACT2_FINDNEXT
:
10110 START_PROFILE(Trans2_findnext
);
10111 call_trans2findnext(conn
, req
,
10112 &state
->param
, state
->total_param
,
10113 &state
->data
, state
->total_data
,
10114 state
->max_data_return
);
10115 END_PROFILE(Trans2_findnext
);
10119 case TRANSACT2_QFSINFO
:
10121 START_PROFILE(Trans2_qfsinfo
);
10122 call_trans2qfsinfo(conn
, req
,
10123 &state
->param
, state
->total_param
,
10124 &state
->data
, state
->total_data
,
10125 state
->max_data_return
);
10126 END_PROFILE(Trans2_qfsinfo
);
10130 case TRANSACT2_SETFSINFO
:
10132 START_PROFILE(Trans2_setfsinfo
);
10133 call_trans2setfsinfo(conn
, req
,
10134 &state
->param
, state
->total_param
,
10135 &state
->data
, state
->total_data
,
10136 state
->max_data_return
);
10137 END_PROFILE(Trans2_setfsinfo
);
10141 case TRANSACT2_QPATHINFO
:
10142 case TRANSACT2_QFILEINFO
:
10144 START_PROFILE(Trans2_qpathinfo
);
10145 call_trans2qfilepathinfo(conn
, req
, state
->call
,
10146 &state
->param
, state
->total_param
,
10147 &state
->data
, state
->total_data
,
10148 state
->max_data_return
);
10149 END_PROFILE(Trans2_qpathinfo
);
10153 case TRANSACT2_SETPATHINFO
:
10154 case TRANSACT2_SETFILEINFO
:
10156 START_PROFILE(Trans2_setpathinfo
);
10157 call_trans2setfilepathinfo(conn
, req
, state
->call
,
10158 &state
->param
, state
->total_param
,
10159 &state
->data
, state
->total_data
,
10160 state
->max_data_return
);
10161 END_PROFILE(Trans2_setpathinfo
);
10165 case TRANSACT2_FINDNOTIFYFIRST
:
10167 START_PROFILE(Trans2_findnotifyfirst
);
10168 call_trans2findnotifyfirst(conn
, req
,
10169 &state
->param
, state
->total_param
,
10170 &state
->data
, state
->total_data
,
10171 state
->max_data_return
);
10172 END_PROFILE(Trans2_findnotifyfirst
);
10176 case TRANSACT2_FINDNOTIFYNEXT
:
10178 START_PROFILE(Trans2_findnotifynext
);
10179 call_trans2findnotifynext(conn
, req
,
10180 &state
->param
, state
->total_param
,
10181 &state
->data
, state
->total_data
,
10182 state
->max_data_return
);
10183 END_PROFILE(Trans2_findnotifynext
);
10187 case TRANSACT2_MKDIR
:
10189 START_PROFILE(Trans2_mkdir
);
10190 call_trans2mkdir(conn
, req
,
10191 &state
->param
, state
->total_param
,
10192 &state
->data
, state
->total_data
,
10193 state
->max_data_return
);
10194 END_PROFILE(Trans2_mkdir
);
10198 case TRANSACT2_GET_DFS_REFERRAL
:
10200 START_PROFILE(Trans2_get_dfs_referral
);
10201 call_trans2getdfsreferral(conn
, req
,
10202 &state
->param
, state
->total_param
,
10203 &state
->data
, state
->total_data
,
10204 state
->max_data_return
);
10205 END_PROFILE(Trans2_get_dfs_referral
);
10209 case TRANSACT2_IOCTL
:
10211 START_PROFILE(Trans2_ioctl
);
10212 call_trans2ioctl(conn
, req
,
10213 &state
->param
, state
->total_param
,
10214 &state
->data
, state
->total_data
,
10215 state
->max_data_return
);
10216 END_PROFILE(Trans2_ioctl
);
10221 /* Error in request */
10222 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
10223 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
10227 /****************************************************************************
10228 Reply to a SMBtrans2.
10229 ****************************************************************************/
10231 void reply_trans2(struct smb_request
*req
)
10233 connection_struct
*conn
= req
->conn
;
10234 unsigned int dsoff
;
10235 unsigned int dscnt
;
10236 unsigned int psoff
;
10237 unsigned int pscnt
;
10238 unsigned int tran_call
;
10239 struct trans_state
*state
;
10242 START_PROFILE(SMBtrans2
);
10244 if (req
->wct
< 14) {
10245 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10246 END_PROFILE(SMBtrans2
);
10250 dsoff
= SVAL(req
->vwv
+12, 0);
10251 dscnt
= SVAL(req
->vwv
+11, 0);
10252 psoff
= SVAL(req
->vwv
+10, 0);
10253 pscnt
= SVAL(req
->vwv
+9, 0);
10254 tran_call
= SVAL(req
->vwv
+14, 0);
10256 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
10257 if (!NT_STATUS_IS_OK(result
)) {
10258 DEBUG(2, ("Got invalid trans2 request: %s\n",
10259 nt_errstr(result
)));
10260 reply_nterror(req
, result
);
10261 END_PROFILE(SMBtrans2
);
10265 if (IS_IPC(conn
)) {
10266 switch (tran_call
) {
10267 /* List the allowed trans2 calls on IPC$ */
10268 case TRANSACT2_OPEN
:
10269 case TRANSACT2_GET_DFS_REFERRAL
:
10270 case TRANSACT2_QFILEINFO
:
10271 case TRANSACT2_QFSINFO
:
10272 case TRANSACT2_SETFSINFO
:
10275 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
10276 END_PROFILE(SMBtrans2
);
10281 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
10282 DEBUG(0, ("talloc failed\n"));
10283 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10284 END_PROFILE(SMBtrans2
);
10288 state
->cmd
= SMBtrans2
;
10290 state
->mid
= req
->mid
;
10291 state
->vuid
= req
->vuid
;
10292 state
->setup_count
= SVAL(req
->vwv
+13, 0);
10293 state
->setup
= NULL
;
10294 state
->total_param
= SVAL(req
->vwv
+0, 0);
10295 state
->param
= NULL
;
10296 state
->total_data
= SVAL(req
->vwv
+1, 0);
10297 state
->data
= NULL
;
10298 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
10299 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
10300 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
10301 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
10302 state
->one_way
= BITSETW(req
->vwv
+5, 1);
10304 state
->call
= tran_call
;
10306 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10307 is so as a sanity check */
10308 if (state
->setup_count
!= 1) {
10310 * Need to have rc=0 for ioctl to get job id for OS/2.
10311 * Network printing will fail if function is not successful.
10312 * Similar function in reply.c will be used if protocol
10313 * is LANMAN1.0 instead of LM1.2X002.
10314 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10315 * outbuf doesn't have to be set(only job id is used).
10317 if ( (state
->setup_count
== 4)
10318 && (tran_call
== TRANSACT2_IOCTL
)
10319 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
10320 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
10321 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10323 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
10324 DEBUG(2,("Transaction is %d\n",tran_call
));
10325 TALLOC_FREE(state
);
10326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10327 END_PROFILE(SMBtrans2
);
10332 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
10335 if (state
->total_data
) {
10337 if (trans_oob(state
->total_data
, 0, dscnt
)
10338 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
10342 /* Can't use talloc here, the core routines do realloc on the
10343 * params and data. */
10344 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
10345 if (state
->data
== NULL
) {
10346 DEBUG(0,("reply_trans2: data malloc fail for %u "
10347 "bytes !\n", (unsigned int)state
->total_data
));
10348 TALLOC_FREE(state
);
10349 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10350 END_PROFILE(SMBtrans2
);
10354 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
10357 if (state
->total_param
) {
10359 if (trans_oob(state
->total_param
, 0, pscnt
)
10360 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
10364 /* Can't use talloc here, the core routines do realloc on the
10365 * params and data. */
10366 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
10367 if (state
->param
== NULL
) {
10368 DEBUG(0,("reply_trans: param malloc fail for %u "
10369 "bytes !\n", (unsigned int)state
->total_param
));
10370 SAFE_FREE(state
->data
);
10371 TALLOC_FREE(state
);
10372 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10373 END_PROFILE(SMBtrans2
);
10377 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
10380 state
->received_data
= dscnt
;
10381 state
->received_param
= pscnt
;
10383 if ((state
->received_param
== state
->total_param
) &&
10384 (state
->received_data
== state
->total_data
)) {
10386 handle_trans2(conn
, req
, state
);
10388 SAFE_FREE(state
->data
);
10389 SAFE_FREE(state
->param
);
10390 TALLOC_FREE(state
);
10391 END_PROFILE(SMBtrans2
);
10395 DLIST_ADD(conn
->pending_trans
, state
);
10397 /* We need to send an interim response then receive the rest
10398 of the parameter/data bytes */
10399 reply_outbuf(req
, 0, 0);
10400 show_msg((char *)req
->outbuf
);
10401 END_PROFILE(SMBtrans2
);
10406 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10407 SAFE_FREE(state
->data
);
10408 SAFE_FREE(state
->param
);
10409 TALLOC_FREE(state
);
10410 END_PROFILE(SMBtrans2
);
10411 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10415 /****************************************************************************
10416 Reply to a SMBtranss2
10417 ****************************************************************************/
10419 void reply_transs2(struct smb_request
*req
)
10421 connection_struct
*conn
= req
->conn
;
10422 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
10423 struct trans_state
*state
;
10425 START_PROFILE(SMBtranss2
);
10427 show_msg((const char *)req
->inbuf
);
10429 /* Windows clients expect all replies to
10430 a transact secondary (SMBtranss2 0x33)
10431 to have a command code of transact
10432 (SMBtrans2 0x32). See bug #8989
10433 and also [MS-CIFS] section 2.2.4.47.2
10436 req
->cmd
= SMBtrans2
;
10438 if (req
->wct
< 8) {
10439 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10440 END_PROFILE(SMBtranss2
);
10444 for (state
= conn
->pending_trans
; state
!= NULL
;
10445 state
= state
->next
) {
10446 if (state
->mid
== req
->mid
) {
10451 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
10452 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10453 END_PROFILE(SMBtranss2
);
10457 /* Revise state->total_param and state->total_data in case they have
10458 changed downwards */
10460 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
10461 state
->total_param
= SVAL(req
->vwv
+0, 0);
10462 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
10463 state
->total_data
= SVAL(req
->vwv
+1, 0);
10465 pcnt
= SVAL(req
->vwv
+2, 0);
10466 poff
= SVAL(req
->vwv
+3, 0);
10467 pdisp
= SVAL(req
->vwv
+4, 0);
10469 dcnt
= SVAL(req
->vwv
+5, 0);
10470 doff
= SVAL(req
->vwv
+6, 0);
10471 ddisp
= SVAL(req
->vwv
+7, 0);
10473 state
->received_param
+= pcnt
;
10474 state
->received_data
+= dcnt
;
10476 if ((state
->received_data
> state
->total_data
) ||
10477 (state
->received_param
> state
->total_param
))
10481 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
10482 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
10485 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
10489 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
10490 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
10493 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
10496 if ((state
->received_param
< state
->total_param
) ||
10497 (state
->received_data
< state
->total_data
)) {
10498 END_PROFILE(SMBtranss2
);
10502 handle_trans2(conn
, req
, state
);
10504 DLIST_REMOVE(conn
->pending_trans
, state
);
10505 SAFE_FREE(state
->data
);
10506 SAFE_FREE(state
->param
);
10507 TALLOC_FREE(state
);
10509 END_PROFILE(SMBtranss2
);
10514 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10515 DLIST_REMOVE(conn
->pending_trans
, state
);
10516 SAFE_FREE(state
->data
);
10517 SAFE_FREE(state
->param
);
10518 TALLOC_FREE(state
);
10519 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10520 END_PROFILE(SMBtranss2
);