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"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
44 #include "smb1_utils.h"
46 #define DIR_ENTRY_SAFETY_MARGIN 4096
48 static char *store_file_unix_basic(connection_struct
*conn
,
51 const SMB_STRUCT_STAT
*psbuf
);
53 static char *store_file_unix_basic_info2(connection_struct
*conn
,
56 const SMB_STRUCT_STAT
*psbuf
);
58 /****************************************************************************
59 Check if an open file handle or smb_fname is a symlink.
60 ****************************************************************************/
62 static NTSTATUS
refuse_symlink(connection_struct
*conn
,
63 const files_struct
*fsp
,
64 const struct smb_filename
*smb_fname
)
67 const SMB_STRUCT_STAT
*pst
= NULL
;
70 pst
= &fsp
->fsp_name
->st
;
75 if (!VALID_STAT(*pst
)) {
76 int ret
= vfs_stat_smb_basename(conn
,
79 if (ret
== -1 && errno
!= ENOENT
) {
80 return map_nt_error_from_unix(errno
);
81 } else if (ret
== -1) {
82 /* it's not a symlink.. */
88 if (S_ISLNK(pst
->st_ex_mode
)) {
89 return NT_STATUS_ACCESS_DENIED
;
94 NTSTATUS
check_access_fsp(const struct files_struct
*fsp
,
97 if (!(fsp
->access_mask
& access_mask
)) {
98 return NT_STATUS_ACCESS_DENIED
;
103 #if defined(HAVE_POSIX_ACLS)
104 /****************************************************************************
105 Utility function to open a fsp for a POSIX handle operation.
106 ****************************************************************************/
108 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
109 struct smb_request
*req
,
110 const struct smb_filename
*smb_fname
,
111 uint32_t access_mask
,
112 files_struct
**ret_fsp
)
115 struct smb_filename
*smb_fname_tmp
= NULL
;
116 uint32_t create_disposition
= FILE_OPEN
;
117 uint32_t share_access
= FILE_SHARE_READ
|
121 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
122 * but set reasonable defaults.
124 uint32_t file_attributes
= 0664|FILE_FLAG_POSIX_SEMANTICS
;
125 uint32_t oplock
= NO_OPLOCK
;
126 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
128 /* File or directory must exist. */
129 if (!VALID_STAT(smb_fname
->st
)) {
130 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
132 /* Cannot be a symlink. */
133 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
134 return NT_STATUS_ACCESS_DENIED
;
136 /* Set options correctly for directory open. */
137 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
139 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
140 * directories, but set reasonable defaults.
142 file_attributes
= 0775|FILE_FLAG_POSIX_SEMANTICS
;
143 create_options
= FILE_DIRECTORY_FILE
;
146 /* Createfile uses a non-const smb_fname. */
147 smb_fname_tmp
= cp_smb_filename(talloc_tos(),
149 if (smb_fname_tmp
== NULL
) {
150 return NT_STATUS_NO_MEMORY
;
153 status
= SMB_VFS_CREATE_FILE(
156 0, /* root_dir_fid */
157 smb_fname_tmp
, /* fname */
158 access_mask
, /* access_mask */
159 share_access
, /* share_access */
160 create_disposition
,/* create_disposition*/
161 create_options
, /* create_options */
162 file_attributes
,/* file_attributes */
163 oplock
, /* oplock_request */
165 0, /* allocation_size */
166 0, /* private_flags */
169 ret_fsp
, /* result */
171 NULL
, /* in_context */
172 NULL
); /* out_context */
174 TALLOC_FREE(smb_fname_tmp
);
179 /********************************************************************
180 The canonical "check access" based on object handle or path function.
181 ********************************************************************/
183 static NTSTATUS
check_access(connection_struct
*conn
,
185 const struct smb_filename
*smb_fname
,
186 uint32_t access_mask
)
191 status
= check_access_fsp(fsp
, access_mask
);
193 status
= smbd_check_access_rights(conn
, smb_fname
,
200 /********************************************************************
201 Roundup a value to the nearest allocation roundup size boundary.
202 Only do this for Windows clients.
203 ********************************************************************/
205 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
207 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
209 /* Only roundup for Windows clients. */
210 enum remote_arch_types ra_type
= get_remote_arch();
211 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
212 val
= SMB_ROUNDUP(val
,rval
);
217 /****************************************************************************
218 Utility functions for dealing with extended attributes.
219 ****************************************************************************/
221 /****************************************************************************
222 Refuse to allow clients to overwrite our private xattrs.
223 ****************************************************************************/
225 bool samba_private_attr_name(const char *unix_ea_name
)
227 static const char * const prohibited_ea_names
[] = {
228 SAMBA_POSIX_INHERITANCE_EA_NAME
,
229 SAMBA_XATTR_DOS_ATTRIB
,
237 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
238 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
241 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
242 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
248 /****************************************************************************
249 Get one EA value. Fill in a struct ea_struct.
250 ****************************************************************************/
252 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
,
253 connection_struct
*conn
,
255 const struct smb_filename
*smb_fname
,
257 struct ea_struct
*pea
)
259 /* Get the value of this xattr. Max size is 64k. */
260 size_t attr_size
= 256;
266 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
268 return NT_STATUS_NO_MEMORY
;
271 if (fsp
&& fsp
->fh
->fd
!= -1) {
272 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
274 sizeret
= SMB_VFS_GETXATTR(conn
, smb_fname
,
275 ea_name
, val
, attr_size
);
278 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
284 return map_nt_error_from_unix(errno
);
287 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
288 dump_data(10, (uint8_t *)val
, sizeret
);
291 if (strnequal(ea_name
, "user.", 5)) {
292 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
294 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
296 if (pea
->name
== NULL
) {
298 return NT_STATUS_NO_MEMORY
;
300 pea
->value
.data
= (unsigned char *)val
;
301 pea
->value
.length
= (size_t)sizeret
;
305 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
,
306 connection_struct
*conn
,
308 const struct smb_filename
*smb_fname
,
313 /* Get a list of all xattrs. Max namesize is 64k. */
314 size_t ea_namelist_size
= 1024;
315 char *ea_namelist
= smallbuf
;
316 char *to_free
= NULL
;
321 ssize_t sizeret
= -1;
329 status
= refuse_symlink(conn
, fsp
, smb_fname
);
330 if (!NT_STATUS_IS_OK(status
)) {
332 * Just return no EA's on a symlink.
337 if (fsp
&& fsp
->fh
->fd
!= -1) {
338 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
341 sizeret
= SMB_VFS_LISTXATTR(conn
,
347 if ((sizeret
== -1) && (errno
== ERANGE
)) {
348 ea_namelist_size
= 65536;
349 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
350 if (ea_namelist
== NULL
) {
351 return NT_STATUS_NO_MEMORY
;
353 to_free
= ea_namelist
;
355 if (fsp
&& fsp
->fh
->fd
!= -1) {
356 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
359 sizeret
= SMB_VFS_LISTXATTR(conn
,
367 status
= map_nt_error_from_unix(errno
);
368 TALLOC_FREE(to_free
);
372 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
375 TALLOC_FREE(to_free
);
380 * Ensure the result is 0-terminated
383 if (ea_namelist
[sizeret
-1] != '\0') {
384 TALLOC_FREE(to_free
);
385 return NT_STATUS_INTERNAL_ERROR
;
393 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
397 *pnum_names
= num_names
;
399 if (pnames
== NULL
) {
400 TALLOC_FREE(to_free
);
404 names
= talloc_array(mem_ctx
, char *, num_names
);
406 DEBUG(0, ("talloc failed\n"));
407 TALLOC_FREE(to_free
);
408 return NT_STATUS_NO_MEMORY
;
411 if (ea_namelist
== smallbuf
) {
412 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
413 if (ea_namelist
== NULL
) {
415 return NT_STATUS_NO_MEMORY
;
418 talloc_steal(names
, ea_namelist
);
420 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
422 if (ea_namelist
== NULL
) {
424 return NT_STATUS_NO_MEMORY
;
430 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
431 names
[num_names
++] = p
;
439 /****************************************************************************
440 Return a linked list of the total EA's. Plus the total size
441 ****************************************************************************/
443 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
,
444 connection_struct
*conn
,
446 const struct smb_filename
*smb_fname
,
447 size_t *pea_total_len
,
448 struct ea_list
**ea_list
)
450 /* Get a list of all xattrs. Max namesize is 64k. */
453 struct ea_list
*ea_list_head
= NULL
;
454 bool posix_pathnames
= false;
460 if (!lp_ea_support(SNUM(conn
))) {
466 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
468 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
471 status
= get_ea_names_from_file(talloc_tos(),
478 if (!NT_STATUS_IS_OK(status
)) {
482 if (num_names
== 0) {
486 for (i
=0; i
<num_names
; i
++) {
487 struct ea_list
*listp
;
490 if (strnequal(names
[i
], "system.", 7)
491 || samba_private_attr_name(names
[i
]))
495 * Filter out any underlying POSIX EA names
496 * that a Windows client can't handle.
498 if (!posix_pathnames
&&
499 is_invalid_windows_ea_name(names
[i
])) {
503 listp
= talloc(mem_ctx
, struct ea_list
);
505 return NT_STATUS_NO_MEMORY
;
508 status
= get_ea_value(listp
,
515 if (!NT_STATUS_IS_OK(status
)) {
520 if (listp
->ea
.value
.length
== 0) {
522 * We can never return a zero length EA.
523 * Windows reports the EA's as corrupted.
529 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
532 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
534 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
535 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
536 (unsigned int)listp
->ea
.value
.length
));
538 DLIST_ADD_END(ea_list_head
, listp
);
542 /* Add on 4 for total length. */
543 if (*pea_total_len
) {
547 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
548 (unsigned int)*pea_total_len
));
550 *ea_list
= ea_list_head
;
554 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
555 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
560 if (!lp_ea_support(SNUM(conn
))) {
564 if (is_ntfs_stream_smb_fname(smb_fname
)) {
565 return NT_STATUS_INVALID_PARAMETER
;
568 return get_ea_list_from_file_path(mem_ctx
,
576 /****************************************************************************
577 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
579 ****************************************************************************/
581 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
582 connection_struct
*conn
, struct ea_list
*ea_list
)
584 unsigned int ret_data_size
= 4;
587 SMB_ASSERT(total_data_size
>= 4);
589 if (!lp_ea_support(SNUM(conn
))) {
594 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
597 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
598 dos_namelen
= strlen(dos_ea_name
);
599 if (dos_namelen
> 255 || dos_namelen
== 0) {
602 if (ea_list
->ea
.value
.length
> 65535) {
605 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
609 /* We know we have room. */
610 SCVAL(p
,0,ea_list
->ea
.flags
);
611 SCVAL(p
,1,dos_namelen
);
612 SSVAL(p
,2,ea_list
->ea
.value
.length
);
613 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
614 if (ea_list
->ea
.value
.length
> 0) {
615 memcpy(p
+ 4 + dos_namelen
+ 1,
616 ea_list
->ea
.value
.data
,
617 ea_list
->ea
.value
.length
);
620 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
621 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
624 ret_data_size
= PTR_DIFF(p
, pdata
);
625 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
626 SIVAL(pdata
,0,ret_data_size
);
627 return ret_data_size
;
630 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
632 unsigned int total_data_size
,
633 unsigned int *ret_data_size
,
634 connection_struct
*conn
,
635 struct ea_list
*ea_list
)
637 uint8_t *p
= (uint8_t *)pdata
;
638 uint8_t *last_start
= NULL
;
639 bool do_store_data
= (pdata
!= NULL
);
643 if (!lp_ea_support(SNUM(conn
))) {
644 return NT_STATUS_NO_EAS_ON_FILE
;
647 for (; ea_list
; ea_list
= ea_list
->next
) {
653 if (last_start
!= NULL
&& do_store_data
) {
654 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
658 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
659 dos_namelen
= strlen(dos_ea_name
);
660 if (dos_namelen
> 255 || dos_namelen
== 0) {
661 return NT_STATUS_INTERNAL_ERROR
;
663 if (ea_list
->ea
.value
.length
> 65535) {
664 return NT_STATUS_INTERNAL_ERROR
;
667 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
670 pad
= (4 - (this_size
% 4)) % 4;
675 if (this_size
> total_data_size
) {
676 return NT_STATUS_INFO_LENGTH_MISMATCH
;
679 /* We know we have room. */
680 SIVAL(p
, 0x00, 0); /* next offset */
681 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
682 SCVAL(p
, 0x05, dos_namelen
);
683 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
684 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
685 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
687 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
691 total_data_size
-= this_size
;
697 *ret_data_size
= PTR_DIFF(p
, pdata
);
698 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
702 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
704 size_t total_ea_len
= 0;
706 struct ea_list
*ea_list
= NULL
;
708 if (!lp_ea_support(SNUM(conn
))) {
711 mem_ctx
= talloc_stackframe();
713 /* If this is a stream fsp, then we need to instead find the
714 * estimated ea len from the main file, not the stream
715 * (streams cannot have EAs), but the estimate isn't just 0 in
717 if (is_ntfs_stream_smb_fname(smb_fname
)) {
720 (void)get_ea_list_from_file_path(mem_ctx
,
726 if(conn
->sconn
->using_smb2
) {
728 unsigned int ret_data_size
;
730 * We're going to be using fill_ea_chained_buffer() to
731 * marshall EA's - this size is significantly larger
732 * than the SMB1 buffer. Re-calculate the size without
735 status
= fill_ea_chained_buffer(mem_ctx
,
741 if (!NT_STATUS_IS_OK(status
)) {
744 total_ea_len
= ret_data_size
;
746 TALLOC_FREE(mem_ctx
);
750 /****************************************************************************
751 Ensure the EA name is case insensitive by matching any existing EA name.
752 ****************************************************************************/
754 static void canonicalize_ea_name(connection_struct
*conn
,
756 const struct smb_filename
*smb_fname
,
757 fstring unix_ea_name
)
760 TALLOC_CTX
*mem_ctx
= talloc_tos();
761 struct ea_list
*ea_list
;
762 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
,
768 if (!NT_STATUS_IS_OK(status
)) {
772 for (; ea_list
; ea_list
= ea_list
->next
) {
773 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
774 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
775 &unix_ea_name
[5], ea_list
->ea
.name
));
776 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
782 /****************************************************************************
783 Set or delete an extended attribute.
784 ****************************************************************************/
786 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
787 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
790 bool posix_pathnames
= false;
792 if (!lp_ea_support(SNUM(conn
))) {
793 return NT_STATUS_EAS_NOT_SUPPORTED
;
798 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
800 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
803 status
= refuse_symlink(conn
, fsp
, smb_fname
);
804 if (!NT_STATUS_IS_OK(status
)) {
808 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
809 if (!NT_STATUS_IS_OK(status
)) {
813 /* Setting EAs on streams isn't supported. */
814 if (is_ntfs_stream_smb_fname(smb_fname
)) {
815 return NT_STATUS_INVALID_PARAMETER
;
819 * Filter out invalid Windows EA names - before
820 * we set *any* of them.
823 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
824 return STATUS_INVALID_EA_NAME
;
827 for (;ea_list
; ea_list
= ea_list
->next
) {
829 fstring unix_ea_name
;
831 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
832 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
834 canonicalize_ea_name(conn
,
839 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
841 if (samba_private_attr_name(unix_ea_name
)) {
842 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
843 return NT_STATUS_ACCESS_DENIED
;
846 if (ea_list
->ea
.value
.length
== 0) {
847 /* Remove the attribute. */
848 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
849 DEBUG(10,("set_ea: deleting ea name %s on "
850 "file %s by file descriptor.\n",
851 unix_ea_name
, fsp_str_dbg(fsp
)));
852 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
854 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
855 unix_ea_name
, smb_fname
->base_name
));
856 ret
= SMB_VFS_REMOVEXATTR(conn
,
861 /* Removing a non existent attribute always succeeds. */
862 if (ret
== -1 && errno
== ENOATTR
) {
863 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
869 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
870 DEBUG(10,("set_ea: setting ea name %s on file "
871 "%s by file descriptor.\n",
872 unix_ea_name
, fsp_str_dbg(fsp
)));
873 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
874 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
876 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
877 unix_ea_name
, smb_fname
->base_name
));
878 ret
= SMB_VFS_SETXATTR(conn
,
881 ea_list
->ea
.value
.data
,
882 ea_list
->ea
.value
.length
,
889 if (errno
== ENOTSUP
) {
890 return NT_STATUS_EAS_NOT_SUPPORTED
;
893 return map_nt_error_from_unix(errno
);
899 /****************************************************************************
900 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
901 ****************************************************************************/
903 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
905 struct ea_list
*ea_list_head
= NULL
;
906 size_t converted_size
, offset
= 0;
908 while (offset
+ 2 < data_size
) {
909 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
910 unsigned int namelen
= CVAL(pdata
,offset
);
912 offset
++; /* Go past the namelen byte. */
914 /* integer wrap paranioa. */
915 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
916 (offset
> data_size
) || (namelen
> data_size
) ||
917 (offset
+ namelen
>= data_size
)) {
920 /* Ensure the name is null terminated. */
921 if (pdata
[offset
+ namelen
] != '\0') {
924 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
926 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
927 "failed: %s", strerror(errno
)));
933 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
934 DLIST_ADD_END(ea_list_head
, eal
);
935 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
941 /****************************************************************************
942 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
943 ****************************************************************************/
945 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
947 struct ea_list
*ea_list_head
= NULL
;
949 size_t bytes_used
= 0;
951 while (offset
< data_size
) {
952 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
958 DLIST_ADD_END(ea_list_head
, eal
);
959 offset
+= bytes_used
;
965 /****************************************************************************
966 Count the total EA size needed.
967 ****************************************************************************/
969 static size_t ea_list_size(struct ea_list
*ealist
)
972 struct ea_list
*listp
;
975 for (listp
= ealist
; listp
; listp
= listp
->next
) {
976 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
977 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
979 /* Add on 4 for total length. */
987 /****************************************************************************
988 Return a union of EA's from a file list and a list of names.
989 The TALLOC context for the two lists *MUST* be identical as we steal
990 memory from one list to add to another. JRA.
991 ****************************************************************************/
993 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
995 struct ea_list
*nlistp
, *flistp
;
997 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
998 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
999 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
1005 /* Copy the data from this entry. */
1006 nlistp
->ea
.flags
= flistp
->ea
.flags
;
1007 nlistp
->ea
.value
= flistp
->ea
.value
;
1010 nlistp
->ea
.flags
= 0;
1011 ZERO_STRUCT(nlistp
->ea
.value
);
1015 *total_ea_len
= ea_list_size(name_list
);
1019 /****************************************************************************
1020 Send the required number of replies back.
1021 We assume all fields other than the data fields are
1022 set correctly for the type of call.
1023 HACK ! Always assumes smb_setup field is zero.
1024 ****************************************************************************/
1026 void send_trans2_replies(connection_struct
*conn
,
1027 struct smb_request
*req
,
1035 /* As we are using a protocol > LANMAN1 then the max_send
1036 variable must have been set in the sessetupX call.
1037 This takes precedence over the max_xmit field in the
1038 global struct. These different max_xmit variables should
1039 be merged as this is now too confusing */
1041 int data_to_send
= datasize
;
1042 int params_to_send
= paramsize
;
1044 const char *pp
= params
;
1045 const char *pd
= pdata
;
1046 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
1047 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1048 int data_alignment_offset
= 0;
1049 bool overflow
= False
;
1050 struct smbXsrv_connection
*xconn
= req
->xconn
;
1051 int max_send
= xconn
->smb1
.sessions
.max_send
;
1053 /* Modify the data_to_send and datasize and set the error if
1054 we're trying to send more than max_data_bytes. We still send
1055 the part of the packet(s) that fit. Strange, but needed
1058 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
1059 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1060 max_data_bytes
, datasize
));
1061 datasize
= data_to_send
= max_data_bytes
;
1065 /* If there genuinely are no parameters or data to send just send the empty packet */
1067 if(params_to_send
== 0 && data_to_send
== 0) {
1068 reply_outbuf(req
, 10, 0);
1069 if (NT_STATUS_V(status
)) {
1072 ntstatus_to_dos(status
, &eclass
, &ecode
);
1073 error_packet_set((char *)req
->outbuf
,
1074 eclass
, ecode
, status
,
1077 show_msg((char *)req
->outbuf
);
1078 if (!srv_send_smb(xconn
,
1079 (char *)req
->outbuf
,
1080 true, req
->seqnum
+1,
1081 IS_CONN_ENCRYPTED(conn
),
1083 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1085 TALLOC_FREE(req
->outbuf
);
1089 /* When sending params and data ensure that both are nicely aligned */
1090 /* Only do this alignment when there is also data to send - else
1091 can cause NT redirector problems. */
1093 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
1094 data_alignment_offset
= 4 - (params_to_send
% 4);
1096 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1097 /* The alignment_offset is to align the param bytes on an even byte
1098 boundary. NT 4.0 Beta needs this to work correctly. */
1100 useable_space
= max_send
- (smb_size
1103 + data_alignment_offset
);
1105 if (useable_space
< 0) {
1106 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1107 "= %d!!!", useable_space
));
1108 exit_server_cleanly("send_trans2_replies: Not enough space");
1111 while (params_to_send
|| data_to_send
) {
1112 /* Calculate whether we will totally or partially fill this packet */
1114 total_sent_thistime
= params_to_send
+ data_to_send
;
1116 /* We can never send more than useable_space */
1118 * Note that 'useable_space' does not include the alignment offsets,
1119 * but we must include the alignment offsets in the calculation of
1120 * the length of the data we send over the wire, as the alignment offsets
1121 * are sent here. Fix from Marc_Jacobsen@hp.com.
1124 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
1126 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
1127 + data_alignment_offset
);
1129 /* Set total params and data to be sent */
1130 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1131 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1133 /* Calculate how many parameters and data we can fit into
1134 * this packet. Parameters get precedence
1137 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1138 data_sent_thistime
= useable_space
- params_sent_thistime
;
1139 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1141 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1143 /* smb_proff is the offset from the start of the SMB header to the
1144 parameter bytes, however the first 4 bytes of outbuf are
1145 the Netbios over TCP header. Thus use smb_base() to subtract
1146 them from the calculation */
1148 SSVAL(req
->outbuf
,smb_proff
,
1149 ((smb_buf(req
->outbuf
)+alignment_offset
)
1150 - smb_base(req
->outbuf
)));
1152 if(params_sent_thistime
== 0)
1153 SSVAL(req
->outbuf
,smb_prdisp
,0);
1155 /* Absolute displacement of param bytes sent in this packet */
1156 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1158 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1159 if(data_sent_thistime
== 0) {
1160 SSVAL(req
->outbuf
,smb_droff
,0);
1161 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1163 /* The offset of the data bytes is the offset of the
1164 parameter bytes plus the number of parameters being sent this time */
1165 SSVAL(req
->outbuf
, smb_droff
,
1166 ((smb_buf(req
->outbuf
)+alignment_offset
)
1167 - smb_base(req
->outbuf
))
1168 + params_sent_thistime
+ data_alignment_offset
);
1169 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1172 /* Initialize the padding for alignment */
1174 if (alignment_offset
!= 0) {
1175 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1178 /* Copy the param bytes into the packet */
1180 if(params_sent_thistime
) {
1181 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1182 params_sent_thistime
);
1185 /* Copy in the data bytes */
1186 if(data_sent_thistime
) {
1187 if (data_alignment_offset
!= 0) {
1188 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1189 params_sent_thistime
), 0,
1190 data_alignment_offset
);
1192 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1193 +params_sent_thistime
+data_alignment_offset
,
1194 pd
,data_sent_thistime
);
1197 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1198 params_sent_thistime
, data_sent_thistime
, useable_space
));
1199 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1200 params_to_send
, data_to_send
, paramsize
, datasize
));
1203 error_packet_set((char *)req
->outbuf
,
1204 ERRDOS
,ERRbufferoverflow
,
1205 STATUS_BUFFER_OVERFLOW
,
1207 } else if (NT_STATUS_V(status
)) {
1210 ntstatus_to_dos(status
, &eclass
, &ecode
);
1211 error_packet_set((char *)req
->outbuf
,
1212 eclass
, ecode
, status
,
1216 /* Send the packet */
1217 show_msg((char *)req
->outbuf
);
1218 if (!srv_send_smb(xconn
,
1219 (char *)req
->outbuf
,
1220 true, req
->seqnum
+1,
1221 IS_CONN_ENCRYPTED(conn
),
1223 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1225 TALLOC_FREE(req
->outbuf
);
1227 pp
+= params_sent_thistime
;
1228 pd
+= data_sent_thistime
;
1230 params_to_send
-= params_sent_thistime
;
1231 data_to_send
-= data_sent_thistime
;
1234 if(params_to_send
< 0 || data_to_send
< 0) {
1235 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1236 params_to_send
, data_to_send
));
1244 /****************************************************************************
1245 Reply to a TRANSACT2_OPEN.
1246 ****************************************************************************/
1248 static void call_trans2open(connection_struct
*conn
,
1249 struct smb_request
*req
,
1250 char **pparams
, int total_params
,
1251 char **ppdata
, int total_data
,
1252 unsigned int max_data_bytes
)
1254 struct smb_filename
*smb_fname
= NULL
;
1255 char *params
= *pparams
;
1256 char *pdata
= *ppdata
;
1259 bool oplock_request
;
1261 bool return_additional_info
;
1270 int fattr
=0,mtime
=0;
1271 SMB_INO_T inode
= 0;
1274 struct ea_list
*ea_list
= NULL
;
1277 uint32_t access_mask
;
1278 uint32_t share_mode
;
1279 uint32_t create_disposition
;
1280 uint32_t create_options
= 0;
1281 uint32_t private_flags
= 0;
1282 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1283 TALLOC_CTX
*ctx
= talloc_tos();
1286 * Ensure we have enough parameters to perform the operation.
1289 if (total_params
< 29) {
1290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1294 flags
= SVAL(params
, 0);
1295 deny_mode
= SVAL(params
, 2);
1296 open_attr
= SVAL(params
,6);
1297 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1298 if (oplock_request
) {
1299 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1303 return_additional_info
= BITSETW(params
,0);
1304 open_sattr
= SVAL(params
, 4);
1305 open_time
= make_unix_date3(params
+8);
1307 open_ofun
= SVAL(params
,12);
1308 open_size
= IVAL(params
,14);
1309 pname
= ¶ms
[28];
1312 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1316 if (req
->posix_pathnames
) {
1317 srvstr_get_path_posix(ctx
,
1326 srvstr_get_path(ctx
,
1335 if (!NT_STATUS_IS_OK(status
)) {
1336 reply_nterror(req
, status
);
1340 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1341 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1342 (unsigned int)open_ofun
, open_size
));
1344 status
= filename_convert(ctx
,
1351 if (!NT_STATUS_IS_OK(status
)) {
1352 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1353 reply_botherror(req
,
1354 NT_STATUS_PATH_NOT_COVERED
,
1355 ERRSRV
, ERRbadpath
);
1358 reply_nterror(req
, status
);
1362 if (open_ofun
== 0) {
1363 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1367 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1369 &access_mask
, &share_mode
,
1370 &create_disposition
,
1373 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1377 /* Any data in this call is an EA list. */
1378 if (total_data
&& (total_data
!= 4)) {
1379 if (total_data
< 10) {
1380 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1384 if (IVAL(pdata
,0) > total_data
) {
1385 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1386 IVAL(pdata
,0), (unsigned int)total_data
));
1387 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1391 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1394 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1398 if (!lp_ea_support(SNUM(conn
))) {
1399 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1403 if (!req
->posix_pathnames
&&
1404 ea_list_has_invalid_name(ea_list
)) {
1406 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1407 if(*pparams
== NULL
) {
1408 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1412 memset(params
, '\0', param_len
);
1413 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1414 params
, param_len
, NULL
, 0, max_data_bytes
);
1419 status
= SMB_VFS_CREATE_FILE(
1422 0, /* root_dir_fid */
1423 smb_fname
, /* fname */
1424 access_mask
, /* access_mask */
1425 share_mode
, /* share_access */
1426 create_disposition
, /* create_disposition*/
1427 create_options
, /* create_options */
1428 open_attr
, /* file_attributes */
1429 oplock_request
, /* oplock_request */
1431 open_size
, /* allocation_size */
1434 ea_list
, /* ea_list */
1436 &smb_action
, /* psbuf */
1437 NULL
, NULL
); /* create context */
1439 if (!NT_STATUS_IS_OK(status
)) {
1440 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1441 /* We have re-scheduled this call. */
1445 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1446 reply_openerror(req
, status
);
1450 fsp
= fcb_or_dos_open(
1458 reply_openerror(req
, status
);
1461 smb_action
= FILE_WAS_OPENED
;
1464 size
= get_file_size_stat(&smb_fname
->st
);
1465 fattr
= dos_mode(conn
, smb_fname
);
1466 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1467 inode
= smb_fname
->st
.st_ex_ino
;
1468 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1469 close_file(req
, fsp
, ERROR_CLOSE
);
1470 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1474 /* Realloc the size of parameters and data we will return */
1475 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1476 if(*pparams
== NULL
) {
1477 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1482 SSVAL(params
,0,fsp
->fnum
);
1483 SSVAL(params
,2,fattr
);
1484 srv_put_dos_date2(params
,4, mtime
);
1485 SIVAL(params
,8, (uint32_t)size
);
1486 SSVAL(params
,12,deny_mode
);
1487 SSVAL(params
,14,0); /* open_type - file or directory. */
1488 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1490 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1491 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1494 SSVAL(params
,18,smb_action
);
1497 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1499 SIVAL(params
,20,inode
);
1500 SSVAL(params
,24,0); /* Padding. */
1502 uint32_t ea_size
= estimate_ea_size(conn
, fsp
,
1504 SIVAL(params
, 26, ea_size
);
1506 SIVAL(params
, 26, 0);
1509 /* Send the required number of replies */
1510 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1512 TALLOC_FREE(smb_fname
);
1515 /*********************************************************
1516 Routine to check if a given string matches exactly.
1517 as a special case a mask of "." does NOT match. That
1518 is required for correct wildcard semantics
1519 Case can be significant or not.
1520 **********************************************************/
1522 static bool exact_match(bool has_wild
,
1523 bool case_sensitive
,
1527 if (mask
[0] == '.' && mask
[1] == 0) {
1535 if (case_sensitive
) {
1536 return strcmp(str
,mask
)==0;
1538 return strcasecmp_m(str
,mask
) == 0;
1542 /****************************************************************************
1543 Return the filetype for UNIX extensions.
1544 ****************************************************************************/
1546 static uint32_t unix_filetype(mode_t mode
)
1549 return UNIX_TYPE_FILE
;
1550 else if(S_ISDIR(mode
))
1551 return UNIX_TYPE_DIR
;
1553 else if(S_ISLNK(mode
))
1554 return UNIX_TYPE_SYMLINK
;
1557 else if(S_ISCHR(mode
))
1558 return UNIX_TYPE_CHARDEV
;
1561 else if(S_ISBLK(mode
))
1562 return UNIX_TYPE_BLKDEV
;
1565 else if(S_ISFIFO(mode
))
1566 return UNIX_TYPE_FIFO
;
1569 else if(S_ISSOCK(mode
))
1570 return UNIX_TYPE_SOCKET
;
1573 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1574 return UNIX_TYPE_UNKNOWN
;
1577 /****************************************************************************
1578 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1579 ****************************************************************************/
1581 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1583 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1584 const SMB_STRUCT_STAT
*psbuf
,
1586 enum perm_type ptype
,
1591 if (perms
== SMB_MODE_NO_CHANGE
) {
1592 if (!VALID_STAT(*psbuf
)) {
1593 return NT_STATUS_INVALID_PARAMETER
;
1595 *ret_perms
= psbuf
->st_ex_mode
;
1596 return NT_STATUS_OK
;
1600 ret
= wire_perms_to_unix(perms
);
1602 if (ptype
== PERM_NEW_FILE
) {
1604 * "create mask"/"force create mode" are
1605 * only applied to new files, not existing ones.
1607 ret
&= lp_create_mask(SNUM(conn
));
1608 /* Add in force bits */
1609 ret
|= lp_force_create_mode(SNUM(conn
));
1610 } else if (ptype
== PERM_NEW_DIR
) {
1612 * "directory mask"/"force directory mode" are
1613 * only applied to new directories, not existing ones.
1615 ret
&= lp_directory_mask(SNUM(conn
));
1616 /* Add in force bits */
1617 ret
|= lp_force_directory_mode(SNUM(conn
));
1621 return NT_STATUS_OK
;
1624 /****************************************************************************
1625 Needed to show the msdfs symlinks as directories. Modifies psbuf
1626 to be a directory if it's a msdfs link.
1627 ****************************************************************************/
1629 static bool check_msdfs_link(connection_struct
*conn
,
1630 struct smb_filename
*smb_fname
)
1632 int saved_errno
= errno
;
1633 if(lp_host_msdfs() &&
1634 lp_msdfs_root(SNUM(conn
)) &&
1635 is_msdfs_link(conn
, smb_fname
)) {
1637 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1639 smb_fname
->base_name
));
1640 smb_fname
->st
.st_ex_mode
=
1641 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1642 errno
= saved_errno
;
1645 errno
= saved_errno
;
1650 /****************************************************************************
1651 Get a level dependent lanman2 dir entry.
1652 ****************************************************************************/
1654 struct smbd_dirptr_lanman2_state
{
1655 connection_struct
*conn
;
1656 uint32_t info_level
;
1657 bool check_mangled_names
;
1659 bool got_exact_match
;
1662 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1668 struct smbd_dirptr_lanman2_state
*state
=
1669 (struct smbd_dirptr_lanman2_state
*)private_data
;
1671 char mangled_name
[13]; /* mangled 8.3 name. */
1675 /* Mangle fname if it's an illegal name. */
1676 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1678 * Slow path - ensure we can push the original name as UCS2. If
1679 * not, then just don't return this name.
1683 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1684 uint8_t *tmp
= talloc_array(talloc_tos(),
1688 status
= srvstr_push(NULL
,
1689 FLAGS2_UNICODE_STRINGS
,
1698 if (!NT_STATUS_IS_OK(status
)) {
1702 ok
= name_to_8_3(dname
, mangled_name
,
1703 true, state
->conn
->params
);
1707 fname
= mangled_name
;
1712 got_match
= exact_match(state
->has_wild
,
1713 state
->conn
->case_sensitive
,
1715 state
->got_exact_match
= got_match
;
1717 got_match
= mask_match(fname
, mask
,
1718 state
->conn
->case_sensitive
);
1721 if(!got_match
&& state
->check_mangled_names
&&
1722 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1724 * It turns out that NT matches wildcards against
1725 * both long *and* short names. This may explain some
1726 * of the wildcard wierdness from old DOS clients
1727 * that some people have been seeing.... JRA.
1729 /* Force the mangling into 8.3. */
1730 ok
= name_to_8_3(fname
, mangled_name
,
1731 false, state
->conn
->params
);
1736 got_match
= exact_match(state
->has_wild
,
1737 state
->conn
->case_sensitive
,
1738 mangled_name
, mask
);
1739 state
->got_exact_match
= got_match
;
1741 got_match
= mask_match(mangled_name
, mask
,
1742 state
->conn
->case_sensitive
);
1750 *_fname
= talloc_strdup(ctx
, fname
);
1751 if (*_fname
== NULL
) {
1758 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1760 struct smb_filename
*smb_fname
,
1764 struct smbd_dirptr_lanman2_state
*state
=
1765 (struct smbd_dirptr_lanman2_state
*)private_data
;
1766 bool ms_dfs_link
= false;
1769 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1770 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1771 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1772 "Couldn't lstat [%s] (%s)\n",
1773 smb_fname_str_dbg(smb_fname
),
1777 } else if (!VALID_STAT(smb_fname
->st
) &&
1778 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1779 /* Needed to show the msdfs symlinks as
1782 ms_dfs_link
= check_msdfs_link(state
->conn
,
1785 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1786 "Couldn't stat [%s] (%s)\n",
1787 smb_fname_str_dbg(smb_fname
),
1794 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1795 } else if (get_dosmode
) {
1796 mode
= dos_mode(state
->conn
, smb_fname
);
1803 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1804 connection_struct
*conn
,
1806 uint32_t info_level
,
1807 struct ea_list
*name_list
,
1808 bool check_mangled_names
,
1809 bool requires_resume_key
,
1812 const struct smb_filename
*smb_fname
,
1813 int space_remaining
,
1819 uint64_t *last_entry_off
)
1821 char *p
, *q
, *pdata
= *ppdata
;
1823 uint64_t file_size
= 0;
1824 uint64_t allocation_size
= 0;
1825 uint64_t file_id
= 0;
1827 struct timespec mdate_ts
= {0};
1828 struct timespec adate_ts
= {0};
1829 struct timespec cdate_ts
= {0};
1830 struct timespec create_date_ts
= {0};
1831 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1833 char *last_entry_ptr
;
1838 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1840 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1841 file_size
= get_file_size_stat(&smb_fname
->st
);
1843 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1845 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1846 if (!NT_STATUS_IS_OK(status
)) {
1847 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1852 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1854 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1855 adate_ts
= smb_fname
->st
.st_ex_atime
;
1856 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1857 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1859 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1860 dos_filetime_timespec(&create_date_ts
);
1861 dos_filetime_timespec(&mdate_ts
);
1862 dos_filetime_timespec(&adate_ts
);
1863 dos_filetime_timespec(&cdate_ts
);
1866 create_date
= convert_timespec_to_time_t(create_date_ts
);
1867 mdate
= convert_timespec_to_time_t(mdate_ts
);
1868 adate
= convert_timespec_to_time_t(adate_ts
);
1870 /* align the record */
1871 SMB_ASSERT(align
>= 1);
1873 off
= (int)PTR_DIFF(pdata
, base_data
);
1874 pad
= (off
+ (align
-1)) & ~(align
-1);
1877 if (pad
&& pad
> space_remaining
) {
1878 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1879 "for padding (wanted %u, had %d)\n",
1882 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1886 /* initialize padding to 0 */
1888 memset(pdata
, 0, pad
);
1890 space_remaining
-= pad
;
1892 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1902 switch (info_level
) {
1903 case SMB_FIND_INFO_STANDARD
:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1905 if(requires_resume_key
) {
1909 srv_put_dos_date2(p
,0,create_date
);
1910 srv_put_dos_date2(p
,4,adate
);
1911 srv_put_dos_date2(p
,8,mdate
);
1912 SIVAL(p
,12,(uint32_t)file_size
);
1913 SIVAL(p
,16,(uint32_t)allocation_size
);
1917 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1918 p
+= ucs2_align(base_data
, p
, 0);
1920 status
= srvstr_push(base_data
, flags2
, p
,
1921 fname
, PTR_DIFF(end_data
, p
),
1922 STR_TERMINATE
, &len
);
1923 if (!NT_STATUS_IS_OK(status
)) {
1926 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1928 SCVAL(nameptr
, -1, len
- 2);
1930 SCVAL(nameptr
, -1, 0);
1934 SCVAL(nameptr
, -1, len
- 1);
1936 SCVAL(nameptr
, -1, 0);
1942 case SMB_FIND_EA_SIZE
:
1943 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1944 if (requires_resume_key
) {
1948 srv_put_dos_date2(p
,0,create_date
);
1949 srv_put_dos_date2(p
,4,adate
);
1950 srv_put_dos_date2(p
,8,mdate
);
1951 SIVAL(p
,12,(uint32_t)file_size
);
1952 SIVAL(p
,16,(uint32_t)allocation_size
);
1955 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1957 SIVAL(p
,22,ea_size
); /* Extended attributes */
1961 status
= srvstr_push(base_data
, flags2
,
1962 p
, fname
, PTR_DIFF(end_data
, p
),
1963 STR_TERMINATE
| STR_NOALIGN
, &len
);
1964 if (!NT_STATUS_IS_OK(status
)) {
1967 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1980 SCVAL(nameptr
,0,len
);
1982 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1985 case SMB_FIND_EA_LIST
:
1987 struct ea_list
*file_list
= NULL
;
1990 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1992 return NT_STATUS_INVALID_PARAMETER
;
1994 if (requires_resume_key
) {
1998 srv_put_dos_date2(p
,0,create_date
);
1999 srv_put_dos_date2(p
,4,adate
);
2000 srv_put_dos_date2(p
,8,mdate
);
2001 SIVAL(p
,12,(uint32_t)file_size
);
2002 SIVAL(p
,16,(uint32_t)allocation_size
);
2004 p
+= 22; /* p now points to the EA area. */
2006 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
2008 &ea_len
, &file_list
);
2009 if (!NT_STATUS_IS_OK(status
)) {
2012 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
2014 /* We need to determine if this entry will fit in the space available. */
2015 /* Max string size is 255 bytes. */
2016 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
2017 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2018 "(wanted %u, had %d)\n",
2019 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
2021 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2024 /* Push the ea_data followed by the name. */
2025 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
2027 status
= srvstr_push(base_data
, flags2
,
2028 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
2029 STR_TERMINATE
| STR_NOALIGN
, &len
);
2030 if (!NT_STATUS_IS_OK(status
)) {
2033 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
2046 SCVAL(nameptr
,0,len
);
2048 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
2052 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2054 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2056 SIVAL(p
,0,reskey
); p
+= 4;
2057 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2058 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2059 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2060 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2061 SOFF_T(p
,0,file_size
); p
+= 8;
2062 SOFF_T(p
,0,allocation_size
); p
+= 8;
2063 SIVAL(p
,0,mode
); p
+= 4;
2064 q
= p
; p
+= 4; /* q is placeholder for name length. */
2065 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2066 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2068 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2070 SIVAL(p
,0,ea_size
); /* Extended attributes */
2073 /* Clear the short name buffer. This is
2074 * IMPORTANT as not doing so will trigger
2075 * a Win2k client bug. JRA.
2077 if (!was_8_3
&& check_mangled_names
) {
2078 char mangled_name
[13]; /* mangled 8.3 name. */
2079 if (!name_to_8_3(fname
,mangled_name
,True
,
2081 /* Error - mangle failed ! */
2082 memset(mangled_name
,'\0',12);
2084 mangled_name
[12] = 0;
2085 status
= srvstr_push(base_data
, flags2
,
2086 p
+2, mangled_name
, 24,
2087 STR_UPPER
|STR_UNICODE
, &len
);
2088 if (!NT_STATUS_IS_OK(status
)) {
2092 memset(p
+ 2 + len
,'\0',24 - len
);
2099 status
= srvstr_push(base_data
, flags2
, p
,
2100 fname
, PTR_DIFF(end_data
, p
),
2101 STR_TERMINATE_ASCII
, &len
);
2102 if (!NT_STATUS_IS_OK(status
)) {
2108 len
= PTR_DIFF(p
, pdata
);
2109 pad
= (len
+ (align
-1)) & ~(align
-1);
2111 * offset to the next entry, the caller
2112 * will overwrite it for the last entry
2113 * that's why we always include the padding
2117 * set padding to zero
2120 memset(p
, 0, pad
- len
);
2127 case SMB_FIND_FILE_DIRECTORY_INFO
:
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2130 SIVAL(p
,0,reskey
); p
+= 4;
2131 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2132 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2133 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2134 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2135 SOFF_T(p
,0,file_size
); p
+= 8;
2136 SOFF_T(p
,0,allocation_size
); p
+= 8;
2137 SIVAL(p
,0,mode
); p
+= 4;
2138 status
= srvstr_push(base_data
, flags2
,
2139 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
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_FULL_DIRECTORY_INFO
:
2167 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2169 SIVAL(p
,0,reskey
); p
+= 4;
2170 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2171 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2172 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2173 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2174 SOFF_T(p
,0,file_size
); p
+= 8;
2175 SOFF_T(p
,0,allocation_size
); p
+= 8;
2176 SIVAL(p
,0,mode
); p
+= 4;
2177 q
= p
; p
+= 4; /* q is placeholder for name length. */
2178 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2179 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2181 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2183 SIVAL(p
,0,ea_size
); /* Extended attributes */
2186 status
= srvstr_push(base_data
, flags2
, p
,
2187 fname
, PTR_DIFF(end_data
, p
),
2188 STR_TERMINATE_ASCII
, &len
);
2189 if (!NT_STATUS_IS_OK(status
)) {
2195 len
= PTR_DIFF(p
, pdata
);
2196 pad
= (len
+ (align
-1)) & ~(align
-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2204 * set padding to zero
2207 memset(p
, 0, pad
- len
);
2214 case SMB_FIND_FILE_NAMES_INFO
:
2215 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2217 SIVAL(p
,0,reskey
); p
+= 4;
2219 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2220 acl on a dir (tridge) */
2221 status
= srvstr_push(base_data
, flags2
, p
,
2222 fname
, PTR_DIFF(end_data
, p
),
2223 STR_TERMINATE_ASCII
, &len
);
2224 if (!NT_STATUS_IS_OK(status
)) {
2230 len
= PTR_DIFF(p
, pdata
);
2231 pad
= (len
+ (align
-1)) & ~(align
-1);
2233 * offset to the next entry, the caller
2234 * will overwrite it for the last entry
2235 * that's why we always include the padding
2239 * set padding to zero
2242 memset(p
, 0, pad
- len
);
2249 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2250 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2252 SIVAL(p
,0,reskey
); p
+= 4;
2253 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2254 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2255 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2256 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2257 SOFF_T(p
,0,file_size
); p
+= 8;
2258 SOFF_T(p
,0,allocation_size
); p
+= 8;
2259 SIVAL(p
,0,mode
); p
+= 4;
2260 q
= p
; p
+= 4; /* q is placeholder for name length. */
2261 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2262 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2264 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2266 SIVAL(p
,0,ea_size
); /* Extended attributes */
2269 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2270 SBVAL(p
,0,file_id
); p
+= 8;
2271 status
= srvstr_push(base_data
, flags2
, p
,
2272 fname
, PTR_DIFF(end_data
, p
),
2273 STR_TERMINATE_ASCII
, &len
);
2274 if (!NT_STATUS_IS_OK(status
)) {
2280 len
= PTR_DIFF(p
, pdata
);
2281 pad
= (len
+ (align
-1)) & ~(align
-1);
2283 * offset to the next entry, the caller
2284 * will overwrite it for the last entry
2285 * that's why we always include the padding
2289 * set padding to zero
2292 memset(p
, 0, pad
- len
);
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2300 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2301 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2303 SIVAL(p
,0,reskey
); p
+= 4;
2304 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2305 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2306 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2307 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2308 SOFF_T(p
,0,file_size
); p
+= 8;
2309 SOFF_T(p
,0,allocation_size
); p
+= 8;
2310 SIVAL(p
,0,mode
); p
+= 4;
2311 q
= p
; p
+= 4; /* q is placeholder for name length */
2312 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2313 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2314 } else if (readdir_attr_data
&&
2315 readdir_attr_data
->type
== RDATTR_AAPL
) {
2317 * OS X specific SMB2 extension negotiated via
2318 * AAPL create context: return max_access in
2321 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2323 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2325 SIVAL(p
,0,ea_size
); /* Extended attributes */
2329 if (readdir_attr_data
&&
2330 readdir_attr_data
->type
== RDATTR_AAPL
) {
2332 * OS X specific SMB2 extension negotiated via
2333 * AAPL create context: return resource fork
2334 * length and compressed FinderInfo in
2337 * According to documentation short_name_len
2338 * should be 0, but on the wire behaviour
2339 * shows its set to 24 by clients.
2343 /* Resourefork length */
2344 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2346 /* Compressed FinderInfo */
2347 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2348 } else if (!was_8_3
&& check_mangled_names
) {
2349 char mangled_name
[13]; /* mangled 8.3 name. */
2350 if (!name_to_8_3(fname
,mangled_name
,True
,
2352 /* Error - mangle failed ! */
2353 memset(mangled_name
,'\0',12);
2355 mangled_name
[12] = 0;
2356 status
= srvstr_push(base_data
, flags2
,
2357 p
+2, mangled_name
, 24,
2358 STR_UPPER
|STR_UNICODE
, &len
);
2359 if (!NT_STATUS_IS_OK(status
)) {
2364 memset(p
+ 2 + len
,'\0',24 - len
);
2368 /* Clear the short name buffer. This is
2369 * IMPORTANT as not doing so will trigger
2370 * a Win2k client bug. JRA.
2377 if (readdir_attr_data
&&
2378 readdir_attr_data
->type
== RDATTR_AAPL
) {
2380 * OS X specific SMB2 extension negotiated via
2381 * AAPL create context: return UNIX mode in
2384 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2385 SSVAL(p
, 0, aapl_mode
);
2391 SBVAL(p
,0,file_id
); p
+= 8;
2392 status
= srvstr_push(base_data
, flags2
, p
,
2393 fname
, PTR_DIFF(end_data
, p
),
2394 STR_TERMINATE_ASCII
, &len
);
2395 if (!NT_STATUS_IS_OK(status
)) {
2401 len
= PTR_DIFF(p
, pdata
);
2402 pad
= (len
+ (align
-1)) & ~(align
-1);
2404 * offset to the next entry, the caller
2405 * will overwrite it for the last entry
2406 * that's why we always include the padding
2410 * set padding to zero
2413 memset(p
, 0, pad
- len
);
2420 /* CIFS UNIX Extension. */
2422 case SMB_FIND_FILE_UNIX
:
2423 case SMB_FIND_FILE_UNIX_INFO2
:
2425 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2427 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2429 if (info_level
== SMB_FIND_FILE_UNIX
) {
2430 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2431 p
= store_file_unix_basic(conn
, p
,
2432 NULL
, &smb_fname
->st
);
2433 status
= srvstr_push(base_data
, flags2
, p
,
2434 fname
, PTR_DIFF(end_data
, p
),
2435 STR_TERMINATE
, &len
);
2436 if (!NT_STATUS_IS_OK(status
)) {
2440 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2441 p
= store_file_unix_basic_info2(conn
, p
,
2442 NULL
, &smb_fname
->st
);
2445 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2446 PTR_DIFF(end_data
, p
), 0, &len
);
2447 if (!NT_STATUS_IS_OK(status
)) {
2450 SIVAL(nameptr
, 0, len
);
2455 len
= PTR_DIFF(p
, pdata
);
2456 pad
= (len
+ (align
-1)) & ~(align
-1);
2458 * offset to the next entry, the caller
2459 * will overwrite it for the last entry
2460 * that's why we always include the padding
2464 * set padding to zero
2467 memset(p
, 0, pad
- len
);
2472 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2477 return NT_STATUS_INVALID_LEVEL
;
2480 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2481 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2482 "(wanted %u, had %d)\n",
2483 (unsigned int)PTR_DIFF(p
,pdata
),
2485 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2488 /* Setup the last entry pointer, as an offset from base_data */
2489 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2490 /* Advance the data pointer to the next slot */
2493 return NT_STATUS_OK
;
2496 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2497 connection_struct
*conn
,
2498 struct dptr_struct
*dirptr
,
2500 const char *path_mask
,
2503 int requires_resume_key
,
2512 int space_remaining
,
2513 struct smb_filename
**_smb_fname
,
2514 bool *got_exact_match
,
2515 int *_last_entry_off
,
2516 struct ea_list
*name_list
,
2517 struct file_id
*file_id
)
2520 const char *mask
= NULL
;
2521 long prev_dirpos
= 0;
2524 struct smb_filename
*smb_fname
= NULL
;
2525 struct smbd_dirptr_lanman2_state state
;
2527 uint64_t last_entry_off
= 0;
2529 enum mangled_names_options mangled_names
;
2530 bool marshall_with_83_names
;
2532 mangled_names
= lp_mangled_names(conn
->params
);
2536 state
.info_level
= info_level
;
2537 if (mangled_names
!= MANGLED_NAMES_NO
) {
2538 state
.check_mangled_names
= true;
2540 state
.has_wild
= dptr_has_wild(dirptr
);
2541 state
.got_exact_match
= false;
2543 *got_exact_match
= false;
2545 p
= strrchr_m(path_mask
,'/');
2556 ok
= smbd_dirptr_get_entry(ctx
,
2563 smbd_dirptr_lanman2_match_fn
,
2564 smbd_dirptr_lanman2_mode_fn
,
2571 return NT_STATUS_END_OF_FILE
;
2574 *got_exact_match
= state
.got_exact_match
;
2576 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2578 status
= smbd_marshall_dir_entry(ctx
,
2583 marshall_with_83_names
,
2584 requires_resume_key
,
2595 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2596 DEBUG(1,("Conversion error: illegal character: %s\n",
2597 smb_fname_str_dbg(smb_fname
)));
2600 if (file_id
!= NULL
) {
2601 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2604 if (!NT_STATUS_IS_OK(status
) &&
2605 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2607 TALLOC_FREE(smb_fname
);
2612 if (_smb_fname
!= NULL
) {
2613 struct smb_filename
*name
= NULL
;
2615 name
= synthetic_smb_fname(ctx
, fname
, NULL
, &smb_fname
->st
, 0);
2617 TALLOC_FREE(smb_fname
);
2619 return NT_STATUS_NO_MEMORY
;
2624 TALLOC_FREE(smb_fname
);
2627 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2628 dptr_SeekDir(dirptr
, prev_dirpos
);
2632 *_last_entry_off
= last_entry_off
;
2633 return NT_STATUS_OK
;
2636 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2637 connection_struct
*conn
,
2638 struct dptr_struct
*dirptr
,
2640 const char *path_mask
,
2643 bool requires_resume_key
,
2649 int space_remaining
,
2650 bool *got_exact_match
,
2651 int *last_entry_off
,
2652 struct ea_list
*name_list
)
2655 const bool do_pad
= true;
2657 if (info_level
>= 1 && info_level
<= 3) {
2658 /* No alignment on earlier info levels. */
2662 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2663 path_mask
, dirtype
, info_level
,
2664 requires_resume_key
, dont_descend
, ask_sharemode
,
2665 true, align
, do_pad
,
2666 ppdata
, base_data
, end_data
,
2670 last_entry_off
, name_list
, NULL
);
2673 /****************************************************************************
2674 Reply to a TRANS2_FINDFIRST.
2675 ****************************************************************************/
2677 static void call_trans2findfirst(connection_struct
*conn
,
2678 struct smb_request
*req
,
2679 char **pparams
, int total_params
,
2680 char **ppdata
, int total_data
,
2681 unsigned int max_data_bytes
)
2683 /* We must be careful here that we don't return more than the
2684 allowed number of data bytes. If this means returning fewer than
2685 maxentries then so be it. We assume that the redirector has
2686 enough room for the fixed number of parameter bytes it has
2688 struct smb_filename
*smb_dname
= NULL
;
2689 char *params
= *pparams
;
2690 char *pdata
= *ppdata
;
2694 uint16_t findfirst_flags
;
2695 bool close_after_first
;
2697 bool requires_resume_key
;
2699 char *directory
= NULL
;
2702 int last_entry_off
=0;
2706 bool finished
= False
;
2707 bool dont_descend
= False
;
2708 bool out_of_space
= False
;
2709 int space_remaining
;
2710 bool mask_contains_wcard
= False
;
2711 struct ea_list
*ea_list
= NULL
;
2712 NTSTATUS ntstatus
= NT_STATUS_OK
;
2713 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2714 struct dptr_struct
*dirptr
= NULL
;
2715 struct smbd_server_connection
*sconn
= req
->sconn
;
2716 uint32_t ucf_flags
= UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
2717 ucf_flags_from_smb_request(req
);
2718 bool backup_priv
= false;
2719 bool as_root
= false;
2721 if (total_params
< 13) {
2722 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2726 dirtype
= SVAL(params
,0);
2727 maxentries
= SVAL(params
,2);
2728 findfirst_flags
= SVAL(params
,4);
2729 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2730 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2731 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2732 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2733 security_token_has_privilege(get_current_nttok(conn
),
2736 info_level
= SVAL(params
,6);
2738 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2739 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2740 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2742 info_level
, max_data_bytes
));
2745 /* W2K3 seems to treat zero as 1. */
2749 switch (info_level
) {
2750 case SMB_FIND_INFO_STANDARD
:
2751 case SMB_FIND_EA_SIZE
:
2752 case SMB_FIND_EA_LIST
:
2753 case SMB_FIND_FILE_DIRECTORY_INFO
:
2754 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2755 case SMB_FIND_FILE_NAMES_INFO
:
2756 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2757 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2758 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2760 case SMB_FIND_FILE_UNIX
:
2761 case SMB_FIND_FILE_UNIX_INFO2
:
2762 /* Always use filesystem for UNIX mtime query. */
2763 ask_sharemode
= false;
2764 if (!lp_unix_extensions()) {
2765 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2768 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2771 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2775 if (req
->posix_pathnames
) {
2776 srvstr_get_path_wcard_posix(talloc_tos(),
2784 &mask_contains_wcard
);
2786 srvstr_get_path_wcard(talloc_tos(),
2794 &mask_contains_wcard
);
2796 if (!NT_STATUS_IS_OK(ntstatus
)) {
2797 reply_nterror(req
, ntstatus
);
2804 ntstatus
= filename_convert_with_privilege(talloc_tos(),
2809 &mask_contains_wcard
,
2812 ntstatus
= filename_convert(talloc_tos(), conn
,
2816 &mask_contains_wcard
,
2820 if (!NT_STATUS_IS_OK(ntstatus
)) {
2821 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2822 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2823 ERRSRV
, ERRbadpath
);
2826 reply_nterror(req
, ntstatus
);
2830 mask
= smb_dname
->original_lcomp
;
2832 directory
= smb_dname
->base_name
;
2834 p
= strrchr_m(directory
,'/');
2836 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2837 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2838 mask
= talloc_strdup(talloc_tos(),"*");
2840 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2843 mask_contains_wcard
= True
;
2849 if (p
== NULL
|| p
== directory
) {
2850 /* Ensure we don't have a directory name of "". */
2851 directory
= talloc_strdup(talloc_tos(), ".");
2853 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2856 /* Ensure smb_dname->base_name matches. */
2857 smb_dname
->base_name
= directory
;
2860 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2862 if (info_level
== SMB_FIND_EA_LIST
) {
2865 if (total_data
< 4) {
2866 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2870 ea_size
= IVAL(pdata
,0);
2871 if (ea_size
!= total_data
) {
2872 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2873 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2874 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2878 if (!lp_ea_support(SNUM(conn
))) {
2879 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2883 /* Pull out the list of names. */
2884 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
2886 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2891 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2892 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2896 *ppdata
= (char *)SMB_REALLOC(
2897 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2898 if(*ppdata
== NULL
) {
2899 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2903 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2905 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2908 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2909 /* Realloc the params space */
2910 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2911 if (*pparams
== NULL
) {
2912 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2917 /* Save the wildcard match and attribs we are using on this directory -
2918 needed as lanman2 assumes these are being saved between calls */
2920 ntstatus
= dptr_create(conn
,
2928 mask_contains_wcard
,
2932 if (!NT_STATUS_IS_OK(ntstatus
)) {
2933 reply_nterror(req
, ntstatus
);
2938 /* Remember this in case we have
2939 to do a findnext. */
2940 dptr_set_priv(dirptr
);
2943 dptr_num
= dptr_dnum(dirptr
);
2944 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2946 /* We don't need to check for VOL here as this is returned by
2947 a different TRANS2 call. */
2949 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2950 directory
,lp_dont_descend(talloc_tos(), SNUM(conn
))));
2951 if (in_list(directory
,
2952 lp_dont_descend(talloc_tos(), SNUM(conn
)),
2953 conn
->case_sensitive
)) {
2954 dont_descend
= True
;
2958 space_remaining
= max_data_bytes
;
2959 out_of_space
= False
;
2961 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2962 bool got_exact_match
= False
;
2964 /* this is a heuristic to avoid seeking the dirptr except when
2965 absolutely necessary. It allows for a filename of about 40 chars */
2966 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2967 out_of_space
= True
;
2970 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
2974 mask
,dirtype
,info_level
,
2975 requires_resume_key
,dont_descend
,
2980 &last_entry_off
, ea_list
);
2981 if (NT_STATUS_EQUAL(ntstatus
,
2982 NT_STATUS_ILLEGAL_CHARACTER
)) {
2984 * Bad character conversion on name. Ignore this
2989 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2990 out_of_space
= true;
2992 finished
= !NT_STATUS_IS_OK(ntstatus
);
2996 if (!finished
&& !out_of_space
)
3000 * As an optimisation if we know we aren't looking
3001 * for a wildcard name (ie. the name matches the wildcard exactly)
3002 * then we can finish on any (first) match.
3003 * This speeds up large directory searches. JRA.
3009 /* Ensure space_remaining never goes -ve. */
3010 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
3011 space_remaining
= 0;
3012 out_of_space
= true;
3014 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3018 /* Check if we can close the dirptr */
3019 if(close_after_first
|| (finished
&& close_if_end
)) {
3020 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
3021 dptr_close(sconn
, &dptr_num
);
3025 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3026 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3027 * the protocol level is less than NT1. Tested with smbclient. JRA.
3028 * This should fix the OS/2 client bug #2335.
3031 if(numentries
== 0) {
3032 dptr_close(sconn
, &dptr_num
);
3033 if (get_Protocol() < PROTOCOL_NT1
) {
3034 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
3037 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
3038 ERRDOS
, ERRbadfile
);
3043 /* At this point pdata points to numentries directory entries. */
3045 /* Set up the return parameter block */
3046 SSVAL(params
,0,dptr_num
);
3047 SSVAL(params
,2,numentries
);
3048 SSVAL(params
,4,finished
);
3049 SSVAL(params
,6,0); /* Never an EA error */
3050 SSVAL(params
,8,last_entry_off
);
3052 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
3055 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
3056 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
3058 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3062 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3063 smb_fn_name(req
->cmd
),
3064 mask
, directory
, dirtype
, numentries
) );
3067 * Force a name mangle here to ensure that the
3068 * mask as an 8.3 name is top of the mangled cache.
3069 * The reasons for this are subtle. Don't remove
3070 * this code unless you know what you are doing
3071 * (see PR#13758). JRA.
3074 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
3075 char mangled_name
[13];
3076 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
3084 TALLOC_FREE(smb_dname
);
3088 /****************************************************************************
3089 Reply to a TRANS2_FINDNEXT.
3090 ****************************************************************************/
3092 static void call_trans2findnext(connection_struct
*conn
,
3093 struct smb_request
*req
,
3094 char **pparams
, int total_params
,
3095 char **ppdata
, int total_data
,
3096 unsigned int max_data_bytes
)
3098 /* We must be careful here that we don't return more than the
3099 allowed number of data bytes. If this means returning fewer than
3100 maxentries then so be it. We assume that the redirector has
3101 enough room for the fixed number of parameter bytes it has
3103 char *params
= *pparams
;
3104 char *pdata
= *ppdata
;
3108 uint16_t info_level
;
3109 uint32_t resume_key
;
3110 uint16_t findnext_flags
;
3111 bool close_after_request
;
3113 bool requires_resume_key
;
3115 bool mask_contains_wcard
= False
;
3116 char *resume_name
= NULL
;
3117 const char *mask
= NULL
;
3118 const char *directory
= NULL
;
3122 int i
, last_entry_off
=0;
3123 bool finished
= False
;
3124 bool dont_descend
= False
;
3125 bool out_of_space
= False
;
3126 int space_remaining
;
3127 struct ea_list
*ea_list
= NULL
;
3128 NTSTATUS ntstatus
= NT_STATUS_OK
;
3129 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
3130 TALLOC_CTX
*ctx
= talloc_tos();
3131 struct dptr_struct
*dirptr
;
3132 struct smbd_server_connection
*sconn
= req
->sconn
;
3133 bool backup_priv
= false;
3134 bool as_root
= false;
3136 if (total_params
< 13) {
3137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3141 dptr_num
= SVAL(params
,0);
3142 maxentries
= SVAL(params
,2);
3143 info_level
= SVAL(params
,4);
3144 resume_key
= IVAL(params
,6);
3145 findnext_flags
= SVAL(params
,10);
3146 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
3147 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
3148 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
3149 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
3151 if (!continue_bit
) {
3152 /* We only need resume_name if continue_bit is zero. */
3153 if (req
->posix_pathnames
) {
3154 srvstr_get_path_wcard_posix(ctx
,
3162 &mask_contains_wcard
);
3164 srvstr_get_path_wcard(ctx
,
3172 &mask_contains_wcard
);
3174 if (!NT_STATUS_IS_OK(ntstatus
)) {
3175 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3176 complain (it thinks we're asking for the directory above the shared
3177 path or an invalid name). Catch this as the resume name is only compared, never used in
3178 a file access. JRA. */
3179 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
3180 &resume_name
, params
+12,
3184 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
3185 reply_nterror(req
, ntstatus
);
3191 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3192 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3193 resume_key = %d resume name = %s continue=%d level = %d\n",
3194 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
3195 requires_resume_key
, resume_key
,
3196 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
3199 /* W2K3 seems to treat zero as 1. */
3203 switch (info_level
) {
3204 case SMB_FIND_INFO_STANDARD
:
3205 case SMB_FIND_EA_SIZE
:
3206 case SMB_FIND_EA_LIST
:
3207 case SMB_FIND_FILE_DIRECTORY_INFO
:
3208 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
3209 case SMB_FIND_FILE_NAMES_INFO
:
3210 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
3211 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
3212 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
3214 case SMB_FIND_FILE_UNIX
:
3215 case SMB_FIND_FILE_UNIX_INFO2
:
3216 /* Always use filesystem for UNIX mtime query. */
3217 ask_sharemode
= false;
3218 if (!lp_unix_extensions()) {
3219 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3224 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3228 if (info_level
== SMB_FIND_EA_LIST
) {
3231 if (total_data
< 4) {
3232 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3236 ea_size
= IVAL(pdata
,0);
3237 if (ea_size
!= total_data
) {
3238 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3239 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3240 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3244 if (!lp_ea_support(SNUM(conn
))) {
3245 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
3249 /* Pull out the list of names. */
3250 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3252 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3257 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3262 *ppdata
= (char *)SMB_REALLOC(
3263 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3264 if(*ppdata
== NULL
) {
3265 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3270 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3273 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3276 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3277 /* Realloc the params space */
3278 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3279 if(*pparams
== NULL
) {
3280 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3286 /* Check that the dptr is valid */
3287 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
3288 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3292 directory
= dptr_path(sconn
, dptr_num
);
3294 /* Get the wildcard mask from the dptr */
3295 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3296 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3297 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3301 /* Get the attr mask from the dptr */
3302 dirtype
= dptr_attr(sconn
, dptr_num
);
3304 backup_priv
= dptr_get_priv(dirptr
);
3306 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3307 "backup_priv = %d\n",
3308 dptr_num
, mask
, dirtype
,
3310 dptr_TellDir(dirptr
),
3313 /* We don't need to check for VOL here as this is returned by
3314 a different TRANS2 call. */
3316 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3317 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3318 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3319 dont_descend
= True
;
3322 space_remaining
= max_data_bytes
;
3323 out_of_space
= False
;
3331 * Seek to the correct position. We no longer use the resume key but
3332 * depend on the last file name instead.
3335 if(!continue_bit
&& resume_name
&& *resume_name
) {
3338 long current_pos
= 0;
3340 * Remember, name_to_8_3 is called by
3341 * get_lanman2_dir_entry(), so the resume name
3342 * could be mangled. Ensure we check the unmangled name.
3345 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3346 char *new_resume_name
= NULL
;
3347 mangle_lookup_name_from_8_3(ctx
,
3351 if (new_resume_name
) {
3352 resume_name
= new_resume_name
;
3357 * Fix for NT redirector problem triggered by resume key indexes
3358 * changing between directory scans. We now return a resume key of 0
3359 * and instead look for the filename to continue from (also given
3360 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3361 * findfirst/findnext (as is usual) then the directory pointer
3362 * should already be at the correct place.
3365 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3366 } /* end if resume_name && !continue_bit */
3368 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3369 bool got_exact_match
= False
;
3371 /* this is a heuristic to avoid seeking the dirptr except when
3372 absolutely necessary. It allows for a filename of about 40 chars */
3373 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3374 out_of_space
= True
;
3377 ntstatus
= get_lanman2_dir_entry(ctx
,
3381 mask
,dirtype
,info_level
,
3382 requires_resume_key
,dont_descend
,
3387 &last_entry_off
, ea_list
);
3388 if (NT_STATUS_EQUAL(ntstatus
,
3389 NT_STATUS_ILLEGAL_CHARACTER
)) {
3391 * Bad character conversion on name. Ignore this
3396 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3397 out_of_space
= true;
3399 finished
= !NT_STATUS_IS_OK(ntstatus
);
3403 if (!finished
&& !out_of_space
)
3407 * As an optimisation if we know we aren't looking
3408 * for a wildcard name (ie. the name matches the wildcard exactly)
3409 * then we can finish on any (first) match.
3410 * This speeds up large directory searches. JRA.
3416 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3419 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3420 smb_fn_name(req
->cmd
),
3421 mask
, directory
, dirtype
, numentries
) );
3423 /* Check if we can close the dirptr */
3424 if(close_after_request
|| (finished
&& close_if_end
)) {
3425 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3426 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3433 /* Set up the return parameter block */
3434 SSVAL(params
,0,numentries
);
3435 SSVAL(params
,2,finished
);
3436 SSVAL(params
,4,0); /* Never an EA error */
3437 SSVAL(params
,6,last_entry_off
);
3439 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3445 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3447 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3451 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3453 SMB_ASSERT(extended_info
!= NULL
);
3455 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3456 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3457 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3458 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3459 #ifdef SAMBA_VERSION_REVISION
3460 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3462 extended_info
->samba_subversion
= 0;
3463 #ifdef SAMBA_VERSION_RC_RELEASE
3464 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3466 #ifdef SAMBA_VERSION_PRE_RELEASE
3467 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3470 #ifdef SAMBA_VERSION_VENDOR_PATCH
3471 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3473 extended_info
->samba_gitcommitdate
= 0;
3474 #ifdef SAMBA_VERSION_COMMIT_TIME
3475 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3478 memset(extended_info
->samba_version_string
, 0,
3479 sizeof(extended_info
->samba_version_string
));
3481 snprintf (extended_info
->samba_version_string
,
3482 sizeof(extended_info
->samba_version_string
),
3483 "%s", samba_version_string());
3486 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3487 connection_struct
*conn
,
3488 TALLOC_CTX
*mem_ctx
,
3489 uint16_t info_level
,
3491 unsigned int max_data_bytes
,
3492 size_t *fixed_portion
,
3493 struct smb_filename
*fname
,
3497 char *pdata
, *end_data
;
3500 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3501 int snum
= SNUM(conn
);
3502 const char *fstype
= lp_fstype(SNUM(conn
));
3503 const char *filename
= NULL
;
3504 const uint64_t bytes_per_sector
= 512;
3505 uint32_t additional_flags
= 0;
3506 struct smb_filename smb_fname
;
3508 NTSTATUS status
= NT_STATUS_OK
;
3511 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3514 filename
= fname
->base_name
;
3518 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3519 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3520 "info level (0x%x) on IPC$.\n",
3521 (unsigned int)info_level
));
3522 return NT_STATUS_ACCESS_DENIED
;
3526 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3528 ZERO_STRUCT(smb_fname
);
3529 smb_fname
.base_name
= discard_const_p(char, filename
);
3531 if(info_level
!= SMB_FS_QUOTA_INFORMATION
3532 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3533 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3534 return map_nt_error_from_unix(errno
);
3539 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3540 return NT_STATUS_INVALID_PARAMETER
;
3543 *ppdata
= (char *)SMB_REALLOC(
3544 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3545 if (*ppdata
== NULL
) {
3546 return NT_STATUS_NO_MEMORY
;
3550 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3551 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3555 switch (info_level
) {
3556 case SMB_INFO_ALLOCATION
:
3558 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3560 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3562 if (df_ret
== (uint64_t)-1) {
3563 return map_nt_error_from_unix(errno
);
3566 block_size
= lp_block_size(snum
);
3567 if (bsize
< block_size
) {
3568 uint64_t factor
= block_size
/bsize
;
3573 if (bsize
> block_size
) {
3574 uint64_t factor
= bsize
/block_size
;
3579 sectors_per_unit
= bsize
/bytes_per_sector
;
3581 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3582 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3583 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3586 * For large drives, return max values and not modulo.
3588 dsize
= MIN(dsize
, UINT32_MAX
);
3589 dfree
= MIN(dfree
, UINT32_MAX
);
3591 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3592 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3593 SIVAL(pdata
,l1_cUnit
,dsize
);
3594 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3595 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3599 case SMB_INFO_VOLUME
:
3600 /* Return volume name */
3602 * Add volume serial number - hash of a combination of
3603 * the called hostname and the service name.
3605 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3607 * Win2k3 and previous mess this up by sending a name length
3608 * one byte short. I believe only older clients (OS/2 Win9x) use
3609 * this call so try fixing this by adding a terminating null to
3610 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3612 status
= srvstr_push(
3614 pdata
+l2_vol_szVolLabel
, vname
,
3615 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3616 STR_NOALIGN
|STR_TERMINATE
, &len
);
3617 if (!NT_STATUS_IS_OK(status
)) {
3620 SCVAL(pdata
,l2_vol_cch
,len
);
3621 data_len
= l2_vol_szVolLabel
+ len
;
3622 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3623 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3624 (unsigned)len
, vname
));
3627 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3628 case SMB_FS_ATTRIBUTE_INFORMATION
:
3630 additional_flags
= 0;
3631 #if defined(HAVE_SYS_QUOTAS)
3632 additional_flags
|= FILE_VOLUME_QUOTAS
;
3635 if(lp_nt_acl_support(SNUM(conn
))) {
3636 additional_flags
|= FILE_PERSISTENT_ACLS
;
3639 /* Capabilities are filled in at connection time through STATVFS call */
3640 additional_flags
|= conn
->fs_capabilities
;
3641 additional_flags
|= lp_parm_int(conn
->params
->service
,
3642 "share", "fake_fscaps",
3645 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3646 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3647 additional_flags
); /* FS ATTRIBUTES */
3649 SIVAL(pdata
,4,255); /* Max filename component length */
3650 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3651 and will think we can't do long filenames */
3652 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3653 PTR_DIFF(end_data
, pdata
+12),
3655 if (!NT_STATUS_IS_OK(status
)) {
3659 data_len
= 12 + len
;
3660 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3661 /* the client only requested a portion of the
3663 data_len
= max_data_bytes
;
3664 status
= STATUS_BUFFER_OVERFLOW
;
3666 *fixed_portion
= 16;
3669 case SMB_QUERY_FS_LABEL_INFO
:
3670 case SMB_FS_LABEL_INFORMATION
:
3671 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3672 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3673 if (!NT_STATUS_IS_OK(status
)) {
3680 case SMB_QUERY_FS_VOLUME_INFO
:
3681 case SMB_FS_VOLUME_INFORMATION
:
3684 * Add volume serial number - hash of a combination of
3685 * the called hostname and the service name.
3687 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3688 (str_checksum(get_local_machine_name())<<16));
3690 /* Max label len is 32 characters. */
3691 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3692 PTR_DIFF(end_data
, pdata
+18),
3694 if (!NT_STATUS_IS_OK(status
)) {
3697 SIVAL(pdata
,12,len
);
3700 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3701 (int)strlen(vname
),vname
,
3702 lp_servicename(talloc_tos(), snum
)));
3703 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3704 /* the client only requested a portion of the
3706 data_len
= max_data_bytes
;
3707 status
= STATUS_BUFFER_OVERFLOW
;
3709 *fixed_portion
= 24;
3712 case SMB_QUERY_FS_SIZE_INFO
:
3713 case SMB_FS_SIZE_INFORMATION
:
3715 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3717 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3719 if (df_ret
== (uint64_t)-1) {
3720 return map_nt_error_from_unix(errno
);
3722 block_size
= lp_block_size(snum
);
3723 if (bsize
< block_size
) {
3724 uint64_t factor
= block_size
/bsize
;
3729 if (bsize
> block_size
) {
3730 uint64_t factor
= bsize
/block_size
;
3735 sectors_per_unit
= bsize
/bytes_per_sector
;
3736 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3737 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3738 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3739 SBIG_UINT(pdata
,0,dsize
);
3740 SBIG_UINT(pdata
,8,dfree
);
3741 SIVAL(pdata
,16,sectors_per_unit
);
3742 SIVAL(pdata
,20,bytes_per_sector
);
3743 *fixed_portion
= 24;
3747 case SMB_FS_FULL_SIZE_INFORMATION
:
3749 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3751 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3753 if (df_ret
== (uint64_t)-1) {
3754 return map_nt_error_from_unix(errno
);
3756 block_size
= lp_block_size(snum
);
3757 if (bsize
< block_size
) {
3758 uint64_t factor
= block_size
/bsize
;
3763 if (bsize
> block_size
) {
3764 uint64_t factor
= bsize
/block_size
;
3769 sectors_per_unit
= bsize
/bytes_per_sector
;
3770 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3771 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3772 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3773 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3774 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3775 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3776 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3777 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3778 *fixed_portion
= 32;
3782 case SMB_QUERY_FS_DEVICE_INFO
:
3783 case SMB_FS_DEVICE_INFORMATION
:
3785 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3787 if (!CAN_WRITE(conn
)) {
3788 characteristics
|= FILE_READ_ONLY_DEVICE
;
3791 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3792 SIVAL(pdata
,4,characteristics
);
3797 #ifdef HAVE_SYS_QUOTAS
3798 case SMB_FS_QUOTA_INFORMATION
:
3800 * what we have to send --metze:
3802 * Unknown1: 24 NULL bytes
3803 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3804 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3805 * Quota Flags: 2 byte :
3806 * Unknown3: 6 NULL bytes
3810 * details for Quota Flags:
3812 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3813 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3814 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3815 * 0x0001 Enable Quotas: enable quota for this fs
3819 /* we need to fake up a fsp here,
3820 * because its not send in this call
3823 SMB_NTQUOTA_STRUCT quotas
;
3826 ZERO_STRUCT(quotas
);
3829 fsp
.fnum
= FNUM_FIELD_INVALID
;
3832 if (get_current_uid(conn
) != 0) {
3833 DEBUG(0,("get_user_quota: access_denied "
3834 "service [%s] user [%s]\n",
3835 lp_servicename(talloc_tos(), SNUM(conn
)),
3836 conn
->session_info
->unix_info
->unix_name
));
3837 return NT_STATUS_ACCESS_DENIED
;
3840 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
3842 if (!NT_STATUS_IS_OK(status
)) {
3843 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3849 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3850 lp_servicename(talloc_tos(), SNUM(conn
))));
3852 /* Unknown1 24 NULL bytes*/
3853 SBIG_UINT(pdata
,0,(uint64_t)0);
3854 SBIG_UINT(pdata
,8,(uint64_t)0);
3855 SBIG_UINT(pdata
,16,(uint64_t)0);
3857 /* Default Soft Quota 8 bytes */
3858 SBIG_UINT(pdata
,24,quotas
.softlim
);
3860 /* Default Hard Quota 8 bytes */
3861 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3863 /* Quota flag 2 bytes */
3864 SSVAL(pdata
,40,quotas
.qflags
);
3866 /* Unknown3 6 NULL bytes */
3872 #endif /* HAVE_SYS_QUOTAS */
3873 case SMB_FS_OBJECTID_INFORMATION
:
3875 unsigned char objid
[16];
3876 struct smb_extended_info extended_info
;
3877 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3878 samba_extended_info_version (&extended_info
);
3879 SIVAL(pdata
,16,extended_info
.samba_magic
);
3880 SIVAL(pdata
,20,extended_info
.samba_version
);
3881 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3882 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3883 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3888 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3892 * These values match a physical Windows Server 2012
3893 * share backed by NTFS atop spinning rust.
3895 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3896 /* logical_bytes_per_sector */
3897 SIVAL(pdata
, 0, bytes_per_sector
);
3898 /* phys_bytes_per_sector_atomic */
3899 SIVAL(pdata
, 4, bytes_per_sector
);
3900 /* phys_bytes_per_sector_perf */
3901 SIVAL(pdata
, 8, bytes_per_sector
);
3902 /* fs_effective_phys_bytes_per_sector_atomic */
3903 SIVAL(pdata
, 12, bytes_per_sector
);
3905 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3906 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3907 /* byte_off_sector_align */
3908 SIVAL(pdata
, 20, 0);
3909 /* byte_off_partition_align */
3910 SIVAL(pdata
, 24, 0);
3911 *fixed_portion
= 28;
3917 * Query the version and capabilities of the CIFS UNIX extensions
3921 case SMB_QUERY_CIFS_UNIX_INFO
:
3923 bool large_write
= lp_min_receive_file_size() &&
3924 !srv_is_signing_active(xconn
);
3925 bool large_read
= !srv_is_signing_active(xconn
);
3926 int encrypt_caps
= 0;
3928 if (!lp_unix_extensions()) {
3929 return NT_STATUS_INVALID_LEVEL
;
3932 switch (conn
->encrypt_level
) {
3933 case SMB_SIGNING_OFF
:
3936 case SMB_SIGNING_DESIRED
:
3937 case SMB_SIGNING_IF_REQUIRED
:
3938 case SMB_SIGNING_DEFAULT
:
3939 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3941 case SMB_SIGNING_REQUIRED
:
3942 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3943 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3944 large_write
= false;
3950 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3951 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3953 /* We have POSIX ACLs, pathname, encryption,
3954 * large read/write, and locking capability. */
3956 SBIG_UINT(pdata
,4,((uint64_t)(
3957 CIFS_UNIX_POSIX_ACLS_CAP
|
3958 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3959 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3960 CIFS_UNIX_EXTATTR_CAP
|
3961 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3963 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3965 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3969 case SMB_QUERY_POSIX_FS_INFO
:
3972 vfs_statvfs_struct svfs
;
3974 if (!lp_unix_extensions()) {
3975 return NT_STATUS_INVALID_LEVEL
;
3978 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
3982 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3983 SIVAL(pdata
,4,svfs
.BlockSize
);
3984 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3985 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3986 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3987 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3988 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3989 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3990 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3992 } else if (rc
== EOPNOTSUPP
) {
3993 return NT_STATUS_INVALID_LEVEL
;
3994 #endif /* EOPNOTSUPP */
3996 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3997 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
4002 case SMB_QUERY_POSIX_WHOAMI
:
4008 if (!lp_unix_extensions()) {
4009 return NT_STATUS_INVALID_LEVEL
;
4012 if (max_data_bytes
< 40) {
4013 return NT_STATUS_BUFFER_TOO_SMALL
;
4016 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
4017 flags
|= SMB_WHOAMI_GUEST
;
4020 /* NOTE: 8 bytes for UID/GID, irrespective of native
4021 * platform size. This matches
4022 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4024 data_len
= 4 /* flags */
4031 + 4 /* pad/reserved */
4032 + (conn
->session_info
->unix_token
->ngroups
* 8)
4034 + (conn
->session_info
->security_token
->num_sids
*
4038 SIVAL(pdata
, 0, flags
);
4039 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
4041 (uint64_t)conn
->session_info
->unix_token
->uid
);
4042 SBIG_UINT(pdata
, 16,
4043 (uint64_t)conn
->session_info
->unix_token
->gid
);
4046 if (data_len
>= max_data_bytes
) {
4047 /* Potential overflow, skip the GIDs and SIDs. */
4049 SIVAL(pdata
, 24, 0); /* num_groups */
4050 SIVAL(pdata
, 28, 0); /* num_sids */
4051 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
4052 SIVAL(pdata
, 36, 0); /* reserved */
4058 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
4059 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
4061 /* We walk the SID list twice, but this call is fairly
4062 * infrequent, and I don't expect that it's performance
4063 * sensitive -- jpeach
4065 for (i
= 0, sid_bytes
= 0;
4066 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4067 sid_bytes
+= ndr_size_dom_sid(
4068 &conn
->session_info
->security_token
->sids
[i
],
4072 /* SID list byte count */
4073 SIVAL(pdata
, 32, sid_bytes
);
4075 /* 4 bytes pad/reserved - must be zero */
4076 SIVAL(pdata
, 36, 0);
4080 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
4081 SBIG_UINT(pdata
, data_len
,
4082 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
4088 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4089 int sid_len
= ndr_size_dom_sid(
4090 &conn
->session_info
->security_token
->sids
[i
],
4093 sid_linearize((uint8_t *)(pdata
+ data_len
),
4095 &conn
->session_info
->security_token
->sids
[i
]);
4096 data_len
+= sid_len
;
4102 case SMB_MAC_QUERY_FS_INFO
:
4104 * Thursby MAC extension... ONLY on NTFS filesystems
4105 * once we do streams then we don't need this
4107 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
4109 SIVAL(pdata
,84,0x100); /* Don't support mac... */
4115 return NT_STATUS_INVALID_LEVEL
;
4118 *ret_data_len
= data_len
;
4122 static NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
4123 struct smb_request
*req
,
4125 const DATA_BLOB
*qdata
)
4128 SMB_NTQUOTA_STRUCT quotas
;
4130 ZERO_STRUCT(quotas
);
4133 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4134 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4135 lp_servicename(talloc_tos(), SNUM(conn
)),
4136 conn
->session_info
->unix_info
->unix_name
));
4137 return NT_STATUS_ACCESS_DENIED
;
4140 if (!check_fsp_ntquota_handle(conn
, req
,
4142 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4143 return NT_STATUS_INVALID_HANDLE
;
4146 /* note: normally there're 48 bytes,
4147 * but we didn't use the last 6 bytes for now
4150 if (qdata
->length
< 42) {
4151 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4152 (unsigned int)qdata
->length
));
4153 return NT_STATUS_INVALID_PARAMETER
;
4156 /* unknown_1 24 NULL bytes in pdata*/
4158 /* the soft quotas 8 bytes (uint64_t)*/
4159 quotas
.softlim
= BVAL(qdata
->data
,24);
4161 /* the hard quotas 8 bytes (uint64_t)*/
4162 quotas
.hardlim
= BVAL(qdata
->data
,32);
4164 /* quota_flags 2 bytes **/
4165 quotas
.qflags
= SVAL(qdata
->data
,40);
4167 /* unknown_2 6 NULL bytes follow*/
4169 /* now set the quotas */
4170 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4171 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4172 lp_servicename(talloc_tos(), SNUM(conn
))));
4173 status
= map_nt_error_from_unix(errno
);
4175 status
= NT_STATUS_OK
;
4180 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
4181 struct smb_request
*req
,
4182 TALLOC_CTX
*mem_ctx
,
4183 uint16_t info_level
,
4185 const DATA_BLOB
*pdata
)
4187 switch (info_level
) {
4188 case SMB_FS_QUOTA_INFORMATION
:
4190 return smb_set_fsquota(conn
,
4199 return NT_STATUS_INVALID_LEVEL
;
4202 /****************************************************************************
4203 Reply to a TRANS2_QFSINFO (query filesystem info).
4204 ****************************************************************************/
4206 static void call_trans2qfsinfo(connection_struct
*conn
,
4207 struct smb_request
*req
,
4208 char **pparams
, int total_params
,
4209 char **ppdata
, int total_data
,
4210 unsigned int max_data_bytes
)
4212 char *params
= *pparams
;
4213 uint16_t info_level
;
4215 size_t fixed_portion
;
4218 if (total_params
< 2) {
4219 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4223 info_level
= SVAL(params
,0);
4225 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4226 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
4227 DEBUG(0,("call_trans2qfsinfo: encryption required "
4228 "and info level 0x%x sent.\n",
4229 (unsigned int)info_level
));
4230 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4235 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
4237 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
4244 if (!NT_STATUS_IS_OK(status
)) {
4245 reply_nterror(req
, status
);
4249 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
4252 DEBUG( 4, ( "%s info_level = %d\n",
4253 smb_fn_name(req
->cmd
), info_level
) );
4258 /****************************************************************************
4259 Reply to a TRANS2_SETFSINFO (set filesystem info).
4260 ****************************************************************************/
4262 static void call_trans2setfsinfo(connection_struct
*conn
,
4263 struct smb_request
*req
,
4264 char **pparams
, int total_params
,
4265 char **ppdata
, int total_data
,
4266 unsigned int max_data_bytes
)
4268 struct smbXsrv_connection
*xconn
= req
->xconn
;
4269 char *pdata
= *ppdata
;
4270 char *params
= *pparams
;
4271 uint16_t info_level
;
4273 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4274 lp_servicename(talloc_tos(), SNUM(conn
))));
4277 if (total_params
< 4) {
4278 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4280 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4284 info_level
= SVAL(params
,2);
4287 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
4288 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
4289 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4290 "info level (0x%x) on IPC$.\n",
4291 (unsigned int)info_level
));
4292 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4297 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4298 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
4299 DEBUG(0,("call_trans2setfsinfo: encryption required "
4300 "and info level 0x%x sent.\n",
4301 (unsigned int)info_level
));
4302 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4307 switch(info_level
) {
4308 case SMB_SET_CIFS_UNIX_INFO
:
4309 if (!lp_unix_extensions()) {
4310 DEBUG(2,("call_trans2setfsinfo: "
4311 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4312 "unix extensions off\n"));
4314 NT_STATUS_INVALID_LEVEL
);
4318 /* There should be 12 bytes of capabilities set. */
4319 if (total_data
< 12) {
4322 NT_STATUS_INVALID_PARAMETER
);
4325 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
4326 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
4327 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
4328 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
4329 /* Just print these values for now. */
4330 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4331 "major = %u, minor = %u cap_low = 0x%x, "
4333 (unsigned int)xconn
->
4334 smb1
.unix_info
.client_major
,
4335 (unsigned int)xconn
->
4336 smb1
.unix_info
.client_minor
,
4337 (unsigned int)xconn
->
4338 smb1
.unix_info
.client_cap_low
,
4339 (unsigned int)xconn
->
4340 smb1
.unix_info
.client_cap_high
));
4342 /* Here is where we must switch to posix pathname processing... */
4343 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
4344 lp_set_posix_pathnames();
4345 mangle_change_to_posix();
4348 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
4349 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
4350 /* Client that knows how to do posix locks,
4351 * but not posix open/mkdir operations. Set a
4352 * default type for read/write checks. */
4354 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
4359 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4362 size_t param_len
= 0;
4363 size_t data_len
= total_data
;
4365 if (!lp_unix_extensions()) {
4368 NT_STATUS_INVALID_LEVEL
);
4372 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
4375 NT_STATUS_NOT_SUPPORTED
);
4379 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4380 DEBUG( 2,("call_trans2setfsinfo: "
4381 "request transport encryption disabled"
4382 "with 'fork echo handler = yes'\n"));
4385 NT_STATUS_NOT_SUPPORTED
);
4389 DEBUG( 4,("call_trans2setfsinfo: "
4390 "request transport encryption.\n"));
4392 status
= srv_request_encryption_setup(conn
,
4393 (unsigned char **)ppdata
,
4395 (unsigned char **)pparams
,
4398 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4399 !NT_STATUS_IS_OK(status
)) {
4400 reply_nterror(req
, status
);
4404 send_trans2_replies(conn
, req
,
4412 if (NT_STATUS_IS_OK(status
)) {
4413 /* Server-side transport
4414 * encryption is now *on*. */
4415 status
= srv_encryption_start(conn
);
4416 if (!NT_STATUS_IS_OK(status
)) {
4417 char *reason
= talloc_asprintf(talloc_tos(),
4418 "Failure in setting "
4419 "up encrypted transport: %s",
4421 exit_server_cleanly(reason
);
4427 case SMB_FS_QUOTA_INFORMATION
:
4431 .data
= (uint8_t *)pdata
,
4432 .length
= total_data
4434 files_struct
*fsp
= NULL
;
4435 fsp
= file_fsp(req
, SVAL(params
,0));
4437 status
= smb_set_fsquota(conn
,
4441 if (!NT_STATUS_IS_OK(status
)) {
4442 reply_nterror(req
, status
);
4448 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4450 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4456 * sending this reply works fine,
4457 * but I'm not sure it's the same
4458 * like windows do...
4461 reply_outbuf(req
, 10, 0);
4464 #if defined(HAVE_POSIX_ACLS)
4465 /****************************************************************************
4466 Utility function to count the number of entries in a POSIX acl.
4467 ****************************************************************************/
4469 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4471 unsigned int ace_count
= 0;
4472 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4473 SMB_ACL_ENTRY_T entry
;
4475 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4477 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4478 entry_id
= SMB_ACL_NEXT_ENTRY
;
4485 /****************************************************************************
4486 Utility function to marshall a POSIX acl into wire format.
4487 ****************************************************************************/
4489 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4491 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4492 SMB_ACL_ENTRY_T entry
;
4494 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4495 SMB_ACL_TAG_T tagtype
;
4496 SMB_ACL_PERMSET_T permset
;
4497 unsigned char perms
= 0;
4498 unsigned int own_grp
;
4501 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4502 entry_id
= SMB_ACL_NEXT_ENTRY
;
4505 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4506 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4510 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4511 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4515 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4516 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4517 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4519 SCVAL(pdata
,1,perms
);
4522 case SMB_ACL_USER_OBJ
:
4523 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4524 own_grp
= (unsigned int)pst
->st_ex_uid
;
4525 SIVAL(pdata
,2,own_grp
);
4530 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4532 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4535 own_grp
= (unsigned int)*puid
;
4536 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4537 SIVAL(pdata
,2,own_grp
);
4541 case SMB_ACL_GROUP_OBJ
:
4542 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4543 own_grp
= (unsigned int)pst
->st_ex_gid
;
4544 SIVAL(pdata
,2,own_grp
);
4549 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4551 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4554 own_grp
= (unsigned int)*pgid
;
4555 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4556 SIVAL(pdata
,2,own_grp
);
4561 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4562 SIVAL(pdata
,2,0xFFFFFFFF);
4563 SIVAL(pdata
,6,0xFFFFFFFF);
4566 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4567 SIVAL(pdata
,2,0xFFFFFFFF);
4568 SIVAL(pdata
,6,0xFFFFFFFF);
4571 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4574 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4581 /****************************************************************************
4582 Store the FILE_UNIX_BASIC info.
4583 ****************************************************************************/
4585 static char *store_file_unix_basic(connection_struct
*conn
,
4588 const SMB_STRUCT_STAT
*psbuf
)
4592 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4593 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4595 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4598 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4601 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4602 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4603 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4606 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4610 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4614 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4617 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4618 devno
= psbuf
->st_ex_rdev
;
4620 devno
= psbuf
->st_ex_dev
;
4623 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4627 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4631 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
4634 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4638 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4645 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4646 * the chflags(2) (or equivalent) flags.
4648 * XXX: this really should be behind the VFS interface. To do this, we would
4649 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4650 * Each VFS module could then implement its own mapping as appropriate for the
4651 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4653 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4657 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4661 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4665 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4669 { UF_HIDDEN
, EXT_HIDDEN
},
4672 /* Do not remove. We need to guarantee that this array has at least one
4673 * entry to build on HP-UX.
4679 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4680 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4684 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4685 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4686 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4687 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4692 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4693 const uint32_t smb_fflags
,
4694 const uint32_t smb_fmask
,
4697 uint32_t max_fmask
= 0;
4700 *stat_fflags
= psbuf
->st_ex_flags
;
4702 /* For each flags requested in smb_fmask, check the state of the
4703 * corresponding flag in smb_fflags and set or clear the matching
4707 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4708 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4709 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4710 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4711 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4713 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4718 /* If smb_fmask is asking to set any bits that are not supported by
4719 * our flag mappings, we should fail.
4721 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4729 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4730 * of file flags and birth (create) time.
4732 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4735 const SMB_STRUCT_STAT
*psbuf
)
4737 uint32_t file_flags
= 0;
4738 uint32_t flags_mask
= 0;
4740 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4742 /* Create (birth) time 64 bit */
4743 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4746 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4747 SIVAL(pdata
, 0, file_flags
); /* flags */
4748 SIVAL(pdata
, 4, flags_mask
); /* mask */
4754 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4755 const struct stream_struct
*streams
,
4757 unsigned int max_data_bytes
,
4758 unsigned int *data_size
)
4761 unsigned int ofs
= 0;
4763 if (max_data_bytes
< 32) {
4764 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4767 for (i
= 0; i
< num_streams
; i
++) {
4768 unsigned int next_offset
;
4770 smb_ucs2_t
*namebuf
;
4772 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4773 streams
[i
].name
, &namelen
) ||
4776 return NT_STATUS_INVALID_PARAMETER
;
4780 * name_buf is now null-terminated, we need to marshall as not
4787 * We cannot overflow ...
4789 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4790 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4792 TALLOC_FREE(namebuf
);
4793 return STATUS_BUFFER_OVERFLOW
;
4796 SIVAL(data
, ofs
+4, namelen
);
4797 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4798 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4799 memcpy(data
+ofs
+24, namebuf
, namelen
);
4800 TALLOC_FREE(namebuf
);
4802 next_offset
= ofs
+ 24 + namelen
;
4804 if (i
== num_streams
-1) {
4805 SIVAL(data
, ofs
, 0);
4808 unsigned int align
= ndr_align_size(next_offset
, 8);
4810 if ((next_offset
+ align
) > max_data_bytes
) {
4811 DEBUG(10, ("refusing to overflow align "
4812 "reply at stream %u\n",
4814 TALLOC_FREE(namebuf
);
4815 return STATUS_BUFFER_OVERFLOW
;
4818 memset(data
+next_offset
, 0, align
);
4819 next_offset
+= align
;
4821 SIVAL(data
, ofs
, next_offset
- ofs
);
4828 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4832 return NT_STATUS_OK
;
4835 #if defined(HAVE_POSIX_ACLS)
4836 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
4837 struct smb_request
*req
,
4839 struct smb_filename
*smb_fname
,
4841 unsigned int data_size_in
,
4842 unsigned int *pdata_size_out
)
4844 SMB_ACL_T file_acl
= NULL
;
4845 SMB_ACL_T def_acl
= NULL
;
4846 uint16_t num_file_acls
= 0;
4847 uint16_t num_def_acls
= 0;
4848 unsigned int size_needed
= 0;
4854 * Ensure we always operate on a file descriptor, not just
4858 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
4859 FILE_READ_ATTRIBUTES
|
4860 FILE_WRITE_ATTRIBUTES
;
4862 status
= get_posix_fsp(conn
,
4868 if (!NT_STATUS_IS_OK(status
)) {
4874 SMB_ASSERT(fsp
!= NULL
);
4876 status
= refuse_symlink(conn
,
4879 if (!NT_STATUS_IS_OK(status
)) {
4883 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
4886 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4887 DBG_INFO("ACLs not implemented on "
4888 "filesystem containing %s\n",
4890 status
= NT_STATUS_NOT_IMPLEMENTED
;
4894 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
4896 * We can only have default POSIX ACLs on
4899 if (!fsp
->is_directory
) {
4900 DBG_INFO("Non-directory open %s\n",
4902 status
= NT_STATUS_INVALID_HANDLE
;
4905 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
,
4907 SMB_ACL_TYPE_DEFAULT
,
4909 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4912 num_file_acls
= count_acl_entries(conn
, file_acl
);
4913 num_def_acls
= count_acl_entries(conn
, def_acl
);
4916 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
4917 status
= NT_STATUS_INVALID_PARAMETER
;
4921 size_needed
= num_file_acls
+ num_def_acls
;
4924 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4925 * than UINT_MAX, so check by division.
4927 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
4928 status
= NT_STATUS_INVALID_PARAMETER
;
4932 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
4933 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
4934 status
= NT_STATUS_INVALID_PARAMETER
;
4937 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
4939 if ( data_size_in
< size_needed
) {
4940 DBG_INFO("data_size too small (%u) need %u\n",
4943 status
= NT_STATUS_BUFFER_TOO_SMALL
;
4947 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4948 SSVAL(pdata
,2,num_file_acls
);
4949 SSVAL(pdata
,4,num_def_acls
);
4950 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
4952 ok
= marshall_posix_acl(conn
,
4957 status
= NT_STATUS_INTERNAL_ERROR
;
4960 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
4962 ok
= marshall_posix_acl(conn
,
4967 status
= NT_STATUS_INTERNAL_ERROR
;
4971 *pdata_size_out
= size_needed
;
4972 status
= NT_STATUS_OK
;
4978 * Ensure the stat struct in smb_fname is up to
4979 * date. Structure copy.
4981 smb_fname
->st
= fsp
->fsp_name
->st
;
4982 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
4986 TALLOC_FREE(file_acl
);
4987 TALLOC_FREE(def_acl
);
4992 /****************************************************************************
4993 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4994 ****************************************************************************/
4996 static void call_trans2qpipeinfo(connection_struct
*conn
,
4997 struct smb_request
*req
,
4998 unsigned int tran_call
,
4999 char **pparams
, int total_params
,
5000 char **ppdata
, int total_data
,
5001 unsigned int max_data_bytes
)
5003 char *params
= *pparams
;
5004 char *pdata
= *ppdata
;
5005 unsigned int data_size
= 0;
5006 unsigned int param_size
= 2;
5007 uint16_t info_level
;
5011 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5015 if (total_params
< 4) {
5016 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5020 fsp
= file_fsp(req
, SVAL(params
,0));
5021 if (!fsp_is_np(fsp
)) {
5022 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5026 info_level
= SVAL(params
,2);
5028 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5029 if (*pparams
== NULL
) {
5030 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5035 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5036 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5039 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5040 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5041 if (*ppdata
== NULL
) {
5042 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5047 switch (info_level
) {
5048 case SMB_FILE_STANDARD_INFORMATION
:
5050 SOFF_T(pdata
,0,4096LL);
5057 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5061 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5067 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
5068 TALLOC_CTX
*mem_ctx
,
5069 struct smb_request
*req
,
5070 uint16_t info_level
,
5072 struct smb_filename
*smb_fname
,
5073 bool delete_pending
,
5074 struct timespec write_time_ts
,
5075 struct ea_list
*ea_list
,
5076 int lock_data_count
,
5079 unsigned int max_data_bytes
,
5080 size_t *fixed_portion
,
5082 unsigned int *pdata_size
)
5084 char *pdata
= *ppdata
;
5085 char *dstart
, *dend
;
5086 unsigned int data_size
;
5087 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
5088 time_t create_time
, mtime
, atime
, c_time
;
5089 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
5096 uint64_t file_size
= 0;
5098 uint64_t allocation_size
= 0;
5099 uint64_t file_id
= 0;
5100 uint32_t access_mask
= 0;
5103 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5104 return NT_STATUS_INVALID_LEVEL
;
5107 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5108 smb_fname_str_dbg(smb_fname
),
5110 info_level
, max_data_bytes
));
5112 mode
= dos_mode(conn
, smb_fname
);
5113 nlink
= psbuf
->st_ex_nlink
;
5115 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
5119 if ((nlink
> 0) && delete_pending
) {
5123 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5124 return NT_STATUS_INVALID_PARAMETER
;
5127 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5128 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5129 if (*ppdata
== NULL
) {
5130 return NT_STATUS_NO_MEMORY
;
5134 dend
= dstart
+ data_size
- 1;
5136 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
5137 update_stat_ex_mtime(psbuf
, write_time_ts
);
5140 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
5141 mtime_ts
= psbuf
->st_ex_mtime
;
5142 atime_ts
= psbuf
->st_ex_atime
;
5143 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
5145 if (lp_dos_filetime_resolution(SNUM(conn
))) {
5146 dos_filetime_timespec(&create_time_ts
);
5147 dos_filetime_timespec(&mtime_ts
);
5148 dos_filetime_timespec(&atime_ts
);
5149 dos_filetime_timespec(&ctime_ts
);
5152 create_time
= convert_timespec_to_time_t(create_time_ts
);
5153 mtime
= convert_timespec_to_time_t(mtime_ts
);
5154 atime
= convert_timespec_to_time_t(atime_ts
);
5155 c_time
= convert_timespec_to_time_t(ctime_ts
);
5157 p
= strrchr_m(smb_fname
->base_name
,'/');
5159 base_name
= smb_fname
->base_name
;
5163 /* NT expects the name to be in an exact form of the *full*
5164 filename. See the trans2 torture test */
5165 if (ISDOT(base_name
)) {
5166 dos_fname
= talloc_strdup(mem_ctx
, "\\");
5168 return NT_STATUS_NO_MEMORY
;
5171 dos_fname
= talloc_asprintf(mem_ctx
,
5173 smb_fname
->base_name
);
5175 return NT_STATUS_NO_MEMORY
;
5177 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5178 dos_fname
= talloc_asprintf(dos_fname
, "%s",
5179 smb_fname
->stream_name
);
5181 return NT_STATUS_NO_MEMORY
;
5185 string_replace(dos_fname
, '/', '\\');
5188 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
5191 /* Do we have this path open ? */
5193 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
5194 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
5195 if (fsp1
&& fsp1
->initial_allocation_size
) {
5196 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
5200 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
5201 file_size
= get_file_size_stat(psbuf
);
5205 pos
= fsp
->fh
->position_information
;
5209 access_mask
= fsp
->access_mask
;
5211 /* GENERIC_EXECUTE mapping from Windows */
5212 access_mask
= 0x12019F;
5215 /* This should be an index number - looks like
5218 I think this causes us to fail the IFSKIT
5219 BasicFileInformationTest. -tpot */
5220 file_id
= SMB_VFS_FS_FILE_ID(conn
, psbuf
);
5224 switch (info_level
) {
5225 case SMB_INFO_STANDARD
:
5226 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5228 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
5229 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
5230 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
5231 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
5232 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
5233 SSVAL(pdata
,l1_attrFile
,mode
);
5236 case SMB_INFO_QUERY_EA_SIZE
:
5238 unsigned int ea_size
=
5239 estimate_ea_size(conn
, fsp
,
5241 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5243 srv_put_dos_date2(pdata
,0,create_time
);
5244 srv_put_dos_date2(pdata
,4,atime
);
5245 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
5246 SIVAL(pdata
,12,(uint32_t)file_size
);
5247 SIVAL(pdata
,16,(uint32_t)allocation_size
);
5248 SSVAL(pdata
,20,mode
);
5249 SIVAL(pdata
,22,ea_size
);
5253 case SMB_INFO_IS_NAME_VALID
:
5254 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5256 /* os/2 needs this ? really ?*/
5257 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
5259 /* This is only reached for qpathinfo */
5263 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5265 size_t total_ea_len
= 0;
5266 struct ea_list
*ea_file_list
= NULL
;
5267 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5270 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5272 &total_ea_len
, &ea_file_list
);
5273 if (!NT_STATUS_IS_OK(status
)) {
5277 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
5279 if (!ea_list
|| (total_ea_len
> data_size
)) {
5281 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5285 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5289 case SMB_INFO_QUERY_ALL_EAS
:
5291 /* We have data_size bytes to put EA's into. */
5292 size_t total_ea_len
= 0;
5293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5295 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5297 &total_ea_len
, &ea_list
);
5298 if (!NT_STATUS_IS_OK(status
)) {
5302 if (!ea_list
|| (total_ea_len
> data_size
)) {
5304 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5308 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5312 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5314 /* This is FileFullEaInformation - 0xF which maps to
5315 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5317 /* We have data_size bytes to put EA's into. */
5318 size_t total_ea_len
= 0;
5319 struct ea_list
*ea_file_list
= NULL
;
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5323 /*TODO: add filtering and index handling */
5326 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5328 &total_ea_len
, &ea_file_list
);
5329 if (!NT_STATUS_IS_OK(status
)) {
5332 if (!ea_file_list
) {
5333 return NT_STATUS_NO_EAS_ON_FILE
;
5336 status
= fill_ea_chained_buffer(mem_ctx
,
5340 conn
, ea_file_list
);
5341 if (!NT_STATUS_IS_OK(status
)) {
5347 case SMB_FILE_BASIC_INFORMATION
:
5348 case SMB_QUERY_FILE_BASIC_INFO
:
5350 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
5351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5352 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
5354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5358 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5359 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5360 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5361 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5362 SIVAL(pdata
,32,mode
);
5364 DEBUG(5,("SMB_QFBI - "));
5365 DEBUG(5,("create: %s ", ctime(&create_time
)));
5366 DEBUG(5,("access: %s ", ctime(&atime
)));
5367 DEBUG(5,("write: %s ", ctime(&mtime
)));
5368 DEBUG(5,("change: %s ", ctime(&c_time
)));
5369 DEBUG(5,("mode: %x\n", mode
));
5370 *fixed_portion
= data_size
;
5373 case SMB_FILE_STANDARD_INFORMATION
:
5374 case SMB_QUERY_FILE_STANDARD_INFO
:
5376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5378 SOFF_T(pdata
,0,allocation_size
);
5379 SOFF_T(pdata
,8,file_size
);
5380 SIVAL(pdata
,16,nlink
);
5381 SCVAL(pdata
,20,delete_pending
?1:0);
5382 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5383 SSVAL(pdata
,22,0); /* Padding. */
5384 *fixed_portion
= 24;
5387 case SMB_FILE_EA_INFORMATION
:
5388 case SMB_QUERY_FILE_EA_INFO
:
5390 unsigned int ea_size
=
5391 estimate_ea_size(conn
, fsp
, smb_fname
);
5392 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5395 SIVAL(pdata
,0,ea_size
);
5399 /* Get the 8.3 name - used if NT SMB was negotiated. */
5400 case SMB_QUERY_FILE_ALT_NAME_INFO
:
5401 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
5403 char mangled_name
[13];
5404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5405 if (!name_to_8_3(base_name
,mangled_name
,
5406 True
,conn
->params
)) {
5407 return NT_STATUS_NO_MEMORY
;
5409 status
= srvstr_push(dstart
, flags2
,
5410 pdata
+4, mangled_name
,
5411 PTR_DIFF(dend
, pdata
+4),
5413 if (!NT_STATUS_IS_OK(status
)) {
5416 data_size
= 4 + len
;
5422 case SMB_QUERY_FILE_NAME_INFO
:
5425 this must be *exactly* right for ACLs on mapped drives to work
5427 status
= srvstr_push(dstart
, flags2
,
5429 PTR_DIFF(dend
, pdata
+4),
5431 if (!NT_STATUS_IS_OK(status
)) {
5434 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5435 data_size
= 4 + len
;
5440 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
5442 char *nfname
= NULL
;
5444 if (!fsp
->conn
->sconn
->using_smb2
) {
5445 return NT_STATUS_INVALID_LEVEL
;
5448 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
5449 if (nfname
== NULL
) {
5450 return NT_STATUS_NO_MEMORY
;
5453 if (ISDOT(nfname
)) {
5456 string_replace(nfname
, '/', '\\');
5458 if (smb_fname
->stream_name
!= NULL
) {
5459 const char *s
= smb_fname
->stream_name
;
5460 const char *e
= NULL
;
5463 SMB_ASSERT(s
[0] != '\0');
5466 * smb_fname->stream_name is in form
5467 * of ':StrEam:$DATA', but we should only
5468 * append ':StrEam' here.
5471 e
= strchr(&s
[1], ':');
5477 nfname
= talloc_strndup_append(nfname
, s
, n
);
5478 if (nfname
== NULL
) {
5479 return NT_STATUS_NO_MEMORY
;
5483 status
= srvstr_push(dstart
, flags2
,
5485 PTR_DIFF(dend
, pdata
+4),
5487 if (!NT_STATUS_IS_OK(status
)) {
5490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5491 data_size
= 4 + len
;
5497 case SMB_FILE_ALLOCATION_INFORMATION
:
5498 case SMB_QUERY_FILE_ALLOCATION_INFO
:
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5501 SOFF_T(pdata
,0,allocation_size
);
5504 case SMB_FILE_END_OF_FILE_INFORMATION
:
5505 case SMB_QUERY_FILE_END_OF_FILEINFO
:
5506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5508 SOFF_T(pdata
,0,file_size
);
5511 case SMB_QUERY_FILE_ALL_INFO
:
5512 case SMB_FILE_ALL_INFORMATION
:
5514 unsigned int ea_size
=
5515 estimate_ea_size(conn
, fsp
, smb_fname
);
5516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5517 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5518 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5519 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5520 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5521 SIVAL(pdata
,32,mode
);
5522 SIVAL(pdata
,36,0); /* padding. */
5524 SOFF_T(pdata
,0,allocation_size
);
5525 SOFF_T(pdata
,8,file_size
);
5526 SIVAL(pdata
,16,nlink
);
5527 SCVAL(pdata
,20,delete_pending
);
5528 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5531 SIVAL(pdata
,0,ea_size
);
5532 pdata
+= 4; /* EA info */
5533 status
= srvstr_push(dstart
, flags2
,
5535 PTR_DIFF(dend
, pdata
+4),
5537 if (!NT_STATUS_IS_OK(status
)) {
5542 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5543 *fixed_portion
= 10;
5547 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5549 unsigned int ea_size
=
5550 estimate_ea_size(conn
, fsp
, smb_fname
);
5551 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5552 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5553 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5554 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5555 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5556 SIVAL(pdata
, 0x20, mode
);
5557 SIVAL(pdata
, 0x24, 0); /* padding. */
5558 SBVAL(pdata
, 0x28, allocation_size
);
5559 SBVAL(pdata
, 0x30, file_size
);
5560 SIVAL(pdata
, 0x38, nlink
);
5561 SCVAL(pdata
, 0x3C, delete_pending
);
5562 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5563 SSVAL(pdata
, 0x3E, 0); /* padding */
5564 SBVAL(pdata
, 0x40, file_id
);
5565 SIVAL(pdata
, 0x48, ea_size
);
5566 SIVAL(pdata
, 0x4C, access_mask
);
5567 SBVAL(pdata
, 0x50, pos
);
5568 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5569 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5573 status
= srvstr_push(dstart
, flags2
,
5575 PTR_DIFF(dend
, pdata
+4),
5577 if (!NT_STATUS_IS_OK(status
)) {
5582 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5583 *fixed_portion
= 104;
5586 case SMB_FILE_INTERNAL_INFORMATION
:
5588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5589 SBVAL(pdata
, 0, file_id
);
5594 case SMB_FILE_ACCESS_INFORMATION
:
5595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5596 SIVAL(pdata
, 0, access_mask
);
5601 case SMB_FILE_NAME_INFORMATION
:
5602 /* Pathname with leading '\'. */
5605 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5607 SIVAL(pdata
,0,byte_len
);
5608 data_size
= 4 + byte_len
;
5612 case SMB_FILE_DISPOSITION_INFORMATION
:
5613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5615 SCVAL(pdata
,0,delete_pending
);
5619 case SMB_FILE_POSITION_INFORMATION
:
5620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5622 SOFF_T(pdata
,0,pos
);
5626 case SMB_FILE_MODE_INFORMATION
:
5627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5628 SIVAL(pdata
,0,mode
);
5633 case SMB_FILE_ALIGNMENT_INFORMATION
:
5634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5635 SIVAL(pdata
,0,0); /* No alignment needed. */
5641 * NT4 server just returns "invalid query" to this - if we try
5642 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5645 /* The first statement above is false - verified using Thursby
5646 * client against NT4 -- gcolley.
5648 case SMB_QUERY_FILE_STREAM_INFO
:
5649 case SMB_FILE_STREAM_INFORMATION
: {
5650 unsigned int num_streams
= 0;
5651 struct stream_struct
*streams
= NULL
;
5653 DEBUG(10,("smbd_do_qfilepathinfo: "
5654 "SMB_FILE_STREAM_INFORMATION\n"));
5656 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5657 return NT_STATUS_INVALID_PARAMETER
;
5660 status
= vfs_streaminfo(conn
,
5667 if (!NT_STATUS_IS_OK(status
)) {
5668 DEBUG(10, ("could not get stream info: %s\n",
5669 nt_errstr(status
)));
5673 status
= marshall_stream_info(num_streams
, streams
,
5674 pdata
, max_data_bytes
,
5677 if (!NT_STATUS_IS_OK(status
)) {
5678 DEBUG(10, ("marshall_stream_info failed: %s\n",
5679 nt_errstr(status
)));
5680 TALLOC_FREE(streams
);
5684 TALLOC_FREE(streams
);
5686 *fixed_portion
= 32;
5690 case SMB_QUERY_COMPRESSION_INFO
:
5691 case SMB_FILE_COMPRESSION_INFORMATION
:
5692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5693 SOFF_T(pdata
,0,file_size
);
5694 SIVAL(pdata
,8,0); /* ??? */
5695 SIVAL(pdata
,12,0); /* ??? */
5697 *fixed_portion
= 16;
5700 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5702 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5703 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5704 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5705 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5706 SOFF_T(pdata
,32,allocation_size
);
5707 SOFF_T(pdata
,40,file_size
);
5708 SIVAL(pdata
,48,mode
);
5709 SIVAL(pdata
,52,0); /* ??? */
5711 *fixed_portion
= 56;
5714 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5716 SIVAL(pdata
,0,mode
);
5723 * CIFS UNIX Extensions.
5726 case SMB_QUERY_FILE_UNIX_BASIC
:
5728 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5729 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5731 DEBUG(4,("smbd_do_qfilepathinfo: "
5732 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5733 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5737 case SMB_QUERY_FILE_UNIX_INFO2
:
5739 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5740 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5744 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5746 for (i
=0; i
<100; i
++)
5747 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5753 case SMB_QUERY_FILE_UNIX_LINK
:
5756 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5759 return NT_STATUS_NO_MEMORY
;
5762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5764 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5765 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5768 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5770 link_len
= SMB_VFS_READLINK(conn
,
5773 if (link_len
== -1) {
5774 return map_nt_error_from_unix(errno
);
5776 buffer
[link_len
] = 0;
5777 status
= srvstr_push(dstart
, flags2
,
5779 PTR_DIFF(dend
, pdata
),
5780 STR_TERMINATE
, &len
);
5781 if (!NT_STATUS_IS_OK(status
)) {
5785 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5790 #if defined(HAVE_POSIX_ACLS)
5791 case SMB_QUERY_POSIX_ACL
:
5793 status
= smb_query_posix_acl(conn
,
5800 if (!NT_STATUS_IS_OK(status
)) {
5808 case SMB_QUERY_POSIX_LOCK
:
5813 enum brl_type lock_type
;
5815 /* We need an open file with a real fd for this. */
5816 if (!fsp
|| fsp
->fh
->fd
== -1) {
5817 return NT_STATUS_INVALID_LEVEL
;
5820 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5821 return NT_STATUS_INVALID_PARAMETER
;
5824 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5825 case POSIX_LOCK_TYPE_READ
:
5826 lock_type
= READ_LOCK
;
5828 case POSIX_LOCK_TYPE_WRITE
:
5829 lock_type
= WRITE_LOCK
;
5831 case POSIX_LOCK_TYPE_UNLOCK
:
5833 /* There's no point in asking for an unlock... */
5834 return NT_STATUS_INVALID_PARAMETER
;
5837 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5838 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5839 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5841 status
= query_lock(fsp
,
5848 if (ERROR_WAS_LOCK_DENIED(status
)) {
5849 /* Here we need to report who has it locked... */
5850 data_size
= POSIX_LOCK_DATA_SIZE
;
5852 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5853 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5854 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5855 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5856 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5858 } else if (NT_STATUS_IS_OK(status
)) {
5859 /* For success we just return a copy of what we sent
5860 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5861 data_size
= POSIX_LOCK_DATA_SIZE
;
5862 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5863 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5871 return NT_STATUS_INVALID_LEVEL
;
5874 *pdata_size
= data_size
;
5875 return NT_STATUS_OK
;
5878 /****************************************************************************
5879 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5880 file name or file id).
5881 ****************************************************************************/
5883 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5884 struct smb_request
*req
,
5885 unsigned int tran_call
,
5886 char **pparams
, int total_params
,
5887 char **ppdata
, int total_data
,
5888 unsigned int max_data_bytes
)
5890 char *params
= *pparams
;
5891 char *pdata
= *ppdata
;
5892 uint16_t info_level
;
5893 unsigned int data_size
= 0;
5894 unsigned int param_size
= 2;
5895 struct smb_filename
*smb_fname
= NULL
;
5896 bool delete_pending
= False
;
5897 struct timespec write_time_ts
;
5898 files_struct
*fsp
= NULL
;
5899 struct file_id fileid
;
5900 struct ea_list
*ea_list
= NULL
;
5901 int lock_data_count
= 0;
5902 char *lock_data
= NULL
;
5903 size_t fixed_portion
;
5904 NTSTATUS status
= NT_STATUS_OK
;
5907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5911 ZERO_STRUCT(write_time_ts
);
5913 if (tran_call
== TRANSACT2_QFILEINFO
) {
5914 if (total_params
< 4) {
5915 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5920 call_trans2qpipeinfo(conn
, req
, tran_call
,
5921 pparams
, total_params
,
5927 fsp
= file_fsp(req
, SVAL(params
,0));
5928 info_level
= SVAL(params
,2);
5930 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5932 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5933 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5937 /* Initial check for valid fsp ptr. */
5938 if (!check_fsp_open(conn
, req
, fsp
)) {
5942 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5943 if (smb_fname
== NULL
) {
5944 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5948 if(fsp
->fake_file_handle
) {
5950 * This is actually for the QUOTA_FAKE_FILE --metze
5953 /* We know this name is ok, it's already passed the checks. */
5955 } else if(fsp
->fh
->fd
== -1) {
5957 * This is actually a QFILEINFO on a directory
5958 * handle (returned from an NT SMB). NT5.0 seems
5959 * to do this call. JRA.
5962 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5963 /* Always do lstat for UNIX calls. */
5964 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5965 DEBUG(3,("call_trans2qfilepathinfo: "
5966 "SMB_VFS_LSTAT of %s failed "
5968 smb_fname_str_dbg(smb_fname
),
5971 map_nt_error_from_unix(errno
));
5974 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5975 DEBUG(3,("call_trans2qfilepathinfo: "
5976 "SMB_VFS_STAT of %s failed (%s)\n",
5977 smb_fname_str_dbg(smb_fname
),
5980 map_nt_error_from_unix(errno
));
5984 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
5985 fileid
= vfs_file_id_from_sbuf(
5986 conn
, &smb_fname
->st
);
5987 get_file_infos(fileid
, fsp
->name_hash
,
5993 * Original code - this is an open file.
5995 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5996 DEBUG(3, ("fstat of %s failed (%s)\n",
5997 fsp_fnum_dbg(fsp
), strerror(errno
)));
5999 map_nt_error_from_unix(errno
));
6002 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6003 fileid
= vfs_file_id_from_sbuf(
6004 conn
, &smb_fname
->st
);
6005 get_file_infos(fileid
, fsp
->name_hash
,
6014 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6017 if (total_params
< 7) {
6018 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6022 info_level
= SVAL(params
,0);
6024 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
6026 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6027 if (!lp_unix_extensions()) {
6028 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6031 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
6032 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
6033 info_level
== SMB_QUERY_FILE_UNIX_LINK
||
6034 req
->posix_pathnames
) {
6035 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
6039 if (req
->posix_pathnames
) {
6040 srvstr_get_path_posix(req
,
6049 srvstr_get_path(req
,
6058 if (!NT_STATUS_IS_OK(status
)) {
6059 reply_nterror(req
, status
);
6063 status
= filename_convert(req
,
6070 if (!NT_STATUS_IS_OK(status
)) {
6071 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6072 reply_botherror(req
,
6073 NT_STATUS_PATH_NOT_COVERED
,
6074 ERRSRV
, ERRbadpath
);
6077 reply_nterror(req
, status
);
6081 /* If this is a stream, check if there is a delete_pending. */
6082 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
6083 && is_ntfs_stream_smb_fname(smb_fname
)) {
6084 struct smb_filename
*smb_fname_base
;
6086 /* Create an smb_filename with stream_name == NULL. */
6087 smb_fname_base
= synthetic_smb_fname(
6089 smb_fname
->base_name
,
6093 if (smb_fname_base
== NULL
) {
6094 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6098 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6099 /* Always do lstat for UNIX calls. */
6100 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
6101 DEBUG(3,("call_trans2qfilepathinfo: "
6102 "SMB_VFS_LSTAT of %s failed "
6104 smb_fname_str_dbg(smb_fname_base
),
6106 TALLOC_FREE(smb_fname_base
);
6108 map_nt_error_from_unix(errno
));
6112 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
6113 DEBUG(3,("call_trans2qfilepathinfo: "
6114 "fileinfo of %s failed "
6116 smb_fname_str_dbg(smb_fname_base
),
6118 TALLOC_FREE(smb_fname_base
);
6120 map_nt_error_from_unix(errno
));
6125 status
= file_name_hash(conn
,
6126 smb_fname_str_dbg(smb_fname_base
),
6128 if (!NT_STATUS_IS_OK(status
)) {
6129 TALLOC_FREE(smb_fname_base
);
6130 reply_nterror(req
, status
);
6134 fileid
= vfs_file_id_from_sbuf(conn
,
6135 &smb_fname_base
->st
);
6136 TALLOC_FREE(smb_fname_base
);
6137 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
6138 if (delete_pending
) {
6139 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6144 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6145 /* Always do lstat for UNIX calls. */
6146 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
6147 DEBUG(3,("call_trans2qfilepathinfo: "
6148 "SMB_VFS_LSTAT of %s failed (%s)\n",
6149 smb_fname_str_dbg(smb_fname
),
6152 map_nt_error_from_unix(errno
));
6157 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
6158 DEBUG(3,("call_trans2qfilepathinfo: "
6159 "SMB_VFS_STAT of %s failed (%s)\n",
6160 smb_fname_str_dbg(smb_fname
),
6163 map_nt_error_from_unix(errno
));
6168 status
= file_name_hash(conn
,
6169 smb_fname_str_dbg(smb_fname
),
6171 if (!NT_STATUS_IS_OK(status
)) {
6172 reply_nterror(req
, status
);
6176 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6177 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
6178 get_file_infos(fileid
, name_hash
, &delete_pending
,
6182 if (delete_pending
) {
6183 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6188 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6189 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
6191 info_level
,tran_call
,total_data
));
6193 /* Pull out any data sent here before we realloc. */
6194 switch (info_level
) {
6195 case SMB_INFO_QUERY_EAS_FROM_LIST
:
6197 /* Pull any EA list from the data portion. */
6200 if (total_data
< 4) {
6202 req
, NT_STATUS_INVALID_PARAMETER
);
6205 ea_size
= IVAL(pdata
,0);
6207 if (total_data
> 0 && ea_size
!= total_data
) {
6208 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6209 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
6211 req
, NT_STATUS_INVALID_PARAMETER
);
6215 if (!lp_ea_support(SNUM(conn
))) {
6216 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
6220 /* Pull out the list of names. */
6221 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
6224 req
, NT_STATUS_INVALID_PARAMETER
);
6230 case SMB_QUERY_POSIX_LOCK
:
6232 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6233 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6237 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6239 req
, NT_STATUS_INVALID_PARAMETER
);
6243 /* Copy the lock range data. */
6244 lock_data
= (char *)talloc_memdup(
6245 req
, pdata
, total_data
);
6247 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6250 lock_data_count
= total_data
;
6256 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6257 if (*pparams
== NULL
) {
6258 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6265 * draft-leach-cifs-v1-spec-02.txt
6266 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6269 * The requested information is placed in the Data portion of the
6270 * transaction response. For the information levels greater than 0x100,
6271 * the transaction response has 1 parameter word which should be
6272 * ignored by the client.
6274 * However Windows only follows this rule for the IS_NAME_VALID call.
6276 switch (info_level
) {
6277 case SMB_INFO_IS_NAME_VALID
:
6282 if ((info_level
& 0xFF00) == 0xFF00) {
6284 * We use levels that start with 0xFF00
6285 * internally to represent SMB2 specific levels
6287 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6291 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
6293 delete_pending
, write_time_ts
,
6295 lock_data_count
, lock_data
,
6296 req
->flags2
, max_data_bytes
,
6298 ppdata
, &data_size
);
6299 if (!NT_STATUS_IS_OK(status
)) {
6300 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6301 /* We have re-scheduled this call. */
6304 reply_nterror(req
, status
);
6307 if (fixed_portion
> max_data_bytes
) {
6308 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
6312 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
6318 /****************************************************************************
6319 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6321 ****************************************************************************/
6323 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
6324 connection_struct
*conn
,
6325 struct smb_request
*req
,
6326 bool overwrite_if_exists
,
6327 const struct smb_filename
*smb_fname_old
,
6328 struct smb_filename
*smb_fname_new
)
6330 NTSTATUS status
= NT_STATUS_OK
;
6333 /* source must already exist. */
6334 if (!VALID_STAT(smb_fname_old
->st
)) {
6335 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6338 if (VALID_STAT(smb_fname_new
->st
)) {
6339 if (overwrite_if_exists
) {
6340 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
6341 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6343 status
= unlink_internals(conn
,
6345 FILE_ATTRIBUTE_NORMAL
,
6348 if (!NT_STATUS_IS_OK(status
)) {
6352 /* Disallow if newname already exists. */
6353 return NT_STATUS_OBJECT_NAME_COLLISION
;
6357 /* No links from a directory. */
6358 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
6359 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6362 /* Setting a hardlink to/from a stream isn't currently supported. */
6363 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
6365 DBG_DEBUG("Old name has streams\n");
6366 return NT_STATUS_INVALID_PARAMETER
;
6368 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
6370 DBG_DEBUG("New name has streams\n");
6371 return NT_STATUS_INVALID_PARAMETER
;
6374 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6375 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
6377 if (SMB_VFS_LINK(conn
, smb_fname_old
, smb_fname_new
) != 0) {
6378 status
= map_nt_error_from_unix(errno
);
6379 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6380 nt_errstr(status
), smb_fname_old
->base_name
,
6381 smb_fname_new
->base_name
));
6386 /****************************************************************************
6387 Deal with setting the time from any of the setfilepathinfo functions.
6388 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6389 calling this function.
6390 ****************************************************************************/
6392 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
6394 const struct smb_filename
*smb_fname
,
6395 struct smb_file_time
*ft
,
6396 bool setting_write_time
)
6398 struct smb_filename smb_fname_base
;
6400 FILE_NOTIFY_CHANGE_LAST_ACCESS
6401 |FILE_NOTIFY_CHANGE_LAST_WRITE
6402 |FILE_NOTIFY_CHANGE_CREATION
;
6404 if (!VALID_STAT(smb_fname
->st
)) {
6405 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6408 /* get some defaults (no modifications) if any info is zero or -1. */
6409 if (null_timespec(ft
->create_time
)) {
6410 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
6413 if (null_timespec(ft
->atime
)) {
6414 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
6417 if (null_timespec(ft
->mtime
)) {
6418 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6421 if (!setting_write_time
) {
6422 /* ft->mtime comes from change time, not write time. */
6423 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6426 /* Ensure the resolution is the correct for
6427 * what we can store on this filesystem. */
6429 round_timespec(conn
->ts_res
, &ft
->create_time
);
6430 round_timespec(conn
->ts_res
, &ft
->ctime
);
6431 round_timespec(conn
->ts_res
, &ft
->atime
);
6432 round_timespec(conn
->ts_res
, &ft
->mtime
);
6434 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6435 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
6436 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6437 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6438 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6439 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
6440 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6441 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
6443 if (setting_write_time
) {
6445 * This was a Windows setfileinfo on an open file.
6446 * NT does this a lot. We also need to
6447 * set the time here, as it can be read by
6448 * FindFirst/FindNext and with the patch for bug #2045
6449 * in smbd/fileio.c it ensures that this timestamp is
6450 * kept sticky even after a write. We save the request
6451 * away and will set it on file close and after a write. JRA.
6454 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6455 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6458 if (fsp
->base_fsp
) {
6459 set_sticky_write_time_fsp(fsp
->base_fsp
,
6462 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
6465 set_sticky_write_time_path(
6466 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
6471 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6473 /* Always call ntimes on the base, even if a stream was passed in. */
6474 smb_fname_base
= *smb_fname
;
6475 smb_fname_base
.stream_name
= NULL
;
6477 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
6478 return map_nt_error_from_unix(errno
);
6481 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
6482 smb_fname
->base_name
);
6483 return NT_STATUS_OK
;
6486 /****************************************************************************
6487 Deal with setting the dosmode from any of the setfilepathinfo functions.
6488 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6489 done before calling this function.
6490 ****************************************************************************/
6492 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
6493 const struct smb_filename
*smb_fname
,
6496 struct smb_filename
*smb_fname_base
;
6499 if (!VALID_STAT(smb_fname
->st
)) {
6500 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6503 /* Always operate on the base_name, even if a stream was passed in. */
6504 smb_fname_base
= synthetic_smb_fname(talloc_tos(),
6505 smb_fname
->base_name
,
6509 if (smb_fname_base
== NULL
) {
6510 return NT_STATUS_NO_MEMORY
;
6514 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6515 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6517 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6521 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6523 /* check the mode isn't different, before changing it */
6524 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6525 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6526 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6527 (unsigned int)dosmode
));
6529 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6531 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6533 smb_fname_str_dbg(smb_fname_base
),
6535 status
= map_nt_error_from_unix(errno
);
6539 status
= NT_STATUS_OK
;
6541 TALLOC_FREE(smb_fname_base
);
6545 /****************************************************************************
6546 Deal with setting the size from any of the setfilepathinfo functions.
6547 ****************************************************************************/
6549 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6550 struct smb_request
*req
,
6552 const struct smb_filename
*smb_fname
,
6553 const SMB_STRUCT_STAT
*psbuf
,
6555 bool fail_after_createfile
)
6557 NTSTATUS status
= NT_STATUS_OK
;
6558 struct smb_filename
*smb_fname_tmp
= NULL
;
6559 files_struct
*new_fsp
= NULL
;
6561 if (!VALID_STAT(*psbuf
)) {
6562 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6565 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
6567 get_file_size_stat(psbuf
));
6569 if (size
== get_file_size_stat(psbuf
)) {
6570 return NT_STATUS_OK
;
6573 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6574 smb_fname_str_dbg(smb_fname
), (double)size
));
6576 if (fsp
&& fsp
->fh
->fd
!= -1) {
6577 /* Handle based call. */
6578 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6579 return NT_STATUS_ACCESS_DENIED
;
6582 if (vfs_set_filelen(fsp
, size
) == -1) {
6583 return map_nt_error_from_unix(errno
);
6585 trigger_write_time_update_immediate(fsp
);
6586 return NT_STATUS_OK
;
6589 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6590 if (smb_fname_tmp
== NULL
) {
6591 return NT_STATUS_NO_MEMORY
;
6594 smb_fname_tmp
->st
= *psbuf
;
6596 status
= SMB_VFS_CREATE_FILE(
6599 0, /* root_dir_fid */
6600 smb_fname_tmp
, /* fname */
6601 FILE_WRITE_DATA
, /* access_mask */
6602 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6604 FILE_OPEN
, /* create_disposition*/
6605 0, /* create_options */
6606 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6607 0, /* oplock_request */
6609 0, /* allocation_size */
6610 0, /* private_flags */
6613 &new_fsp
, /* result */
6615 NULL
, NULL
); /* create context */
6617 TALLOC_FREE(smb_fname_tmp
);
6619 if (!NT_STATUS_IS_OK(status
)) {
6620 /* NB. We check for open_was_deferred in the caller. */
6624 /* See RAW-SFILEINFO-END-OF-FILE */
6625 if (fail_after_createfile
) {
6626 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6627 return NT_STATUS_INVALID_LEVEL
;
6630 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6631 status
= map_nt_error_from_unix(errno
);
6632 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6636 trigger_write_time_update_immediate(new_fsp
);
6637 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6638 return NT_STATUS_OK
;
6641 /****************************************************************************
6642 Deal with SMB_INFO_SET_EA.
6643 ****************************************************************************/
6645 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6649 const struct smb_filename
*smb_fname
)
6651 struct ea_list
*ea_list
= NULL
;
6652 TALLOC_CTX
*ctx
= NULL
;
6653 NTSTATUS status
= NT_STATUS_OK
;
6655 if (total_data
< 10) {
6657 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6658 length. They seem to have no effect. Bug #3212. JRA */
6660 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6661 /* We're done. We only get EA info in this call. */
6662 return NT_STATUS_OK
;
6665 return NT_STATUS_INVALID_PARAMETER
;
6668 if (IVAL(pdata
,0) > total_data
) {
6669 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6670 IVAL(pdata
,0), (unsigned int)total_data
));
6671 return NT_STATUS_INVALID_PARAMETER
;
6675 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6677 return NT_STATUS_INVALID_PARAMETER
;
6680 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6685 /****************************************************************************
6686 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6687 ****************************************************************************/
6689 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6694 struct ea_list
*ea_list
= NULL
;
6698 return NT_STATUS_INVALID_HANDLE
;
6701 if (!lp_ea_support(SNUM(conn
))) {
6702 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6703 "EA's not supported.\n",
6704 (unsigned int)total_data
));
6705 return NT_STATUS_EAS_NOT_SUPPORTED
;
6708 if (total_data
< 10) {
6709 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6711 (unsigned int)total_data
));
6712 return NT_STATUS_INVALID_PARAMETER
;
6715 ea_list
= read_nttrans_ea_list(talloc_tos(),
6720 return NT_STATUS_INVALID_PARAMETER
;
6723 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6725 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6726 smb_fname_str_dbg(fsp
->fsp_name
),
6727 nt_errstr(status
) ));
6733 /****************************************************************************
6734 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6735 ****************************************************************************/
6737 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6741 struct smb_filename
*smb_fname
)
6743 NTSTATUS status
= NT_STATUS_OK
;
6744 bool delete_on_close
;
6745 uint32_t dosmode
= 0;
6747 if (total_data
< 1) {
6748 return NT_STATUS_INVALID_PARAMETER
;
6752 return NT_STATUS_INVALID_HANDLE
;
6755 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6756 dosmode
= dos_mode(conn
, smb_fname
);
6758 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6759 "delete_on_close = %u\n",
6760 smb_fname_str_dbg(smb_fname
),
6761 (unsigned int)dosmode
,
6762 (unsigned int)delete_on_close
));
6764 if (delete_on_close
) {
6765 status
= can_set_delete_on_close(fsp
, dosmode
);
6766 if (!NT_STATUS_IS_OK(status
)) {
6771 /* The set is across all open files on this dev/inode pair. */
6772 if (!set_delete_on_close(fsp
, delete_on_close
,
6773 conn
->session_info
->security_token
,
6774 conn
->session_info
->unix_token
)) {
6775 return NT_STATUS_ACCESS_DENIED
;
6777 return NT_STATUS_OK
;
6780 /****************************************************************************
6781 Deal with SMB_FILE_POSITION_INFORMATION.
6782 ****************************************************************************/
6784 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6789 uint64_t position_information
;
6791 if (total_data
< 8) {
6792 return NT_STATUS_INVALID_PARAMETER
;
6796 /* Ignore on pathname based set. */
6797 return NT_STATUS_OK
;
6800 position_information
= (uint64_t)IVAL(pdata
,0);
6801 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6803 DEBUG(10,("smb_file_position_information: Set file position "
6804 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6805 (double)position_information
));
6806 fsp
->fh
->position_information
= position_information
;
6807 return NT_STATUS_OK
;
6810 /****************************************************************************
6811 Deal with SMB_FILE_MODE_INFORMATION.
6812 ****************************************************************************/
6814 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6820 if (total_data
< 4) {
6821 return NT_STATUS_INVALID_PARAMETER
;
6823 mode
= IVAL(pdata
,0);
6824 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6825 return NT_STATUS_INVALID_PARAMETER
;
6827 return NT_STATUS_OK
;
6830 /****************************************************************************
6831 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6832 ****************************************************************************/
6834 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6835 struct smb_request
*req
,
6838 const struct smb_filename
*new_smb_fname
)
6840 char *link_target
= NULL
;
6841 TALLOC_CTX
*ctx
= talloc_tos();
6843 /* Set a symbolic link. */
6844 /* Don't allow this if follow links is false. */
6846 if (total_data
== 0) {
6847 return NT_STATUS_INVALID_PARAMETER
;
6850 if (!lp_follow_symlinks(SNUM(conn
))) {
6851 return NT_STATUS_ACCESS_DENIED
;
6854 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6855 total_data
, STR_TERMINATE
);
6858 return NT_STATUS_INVALID_PARAMETER
;
6861 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6862 new_smb_fname
->base_name
, link_target
));
6864 if (SMB_VFS_SYMLINK(conn
,link_target
,new_smb_fname
) != 0) {
6865 return map_nt_error_from_unix(errno
);
6868 return NT_STATUS_OK
;
6871 /****************************************************************************
6872 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6873 ****************************************************************************/
6875 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6876 struct smb_request
*req
,
6877 const char *pdata
, int total_data
,
6878 struct smb_filename
*smb_fname_new
)
6880 char *oldname
= NULL
;
6881 struct smb_filename
*smb_fname_old
= NULL
;
6882 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6883 TALLOC_CTX
*ctx
= talloc_tos();
6884 NTSTATUS status
= NT_STATUS_OK
;
6886 /* Set a hard link. */
6887 if (total_data
== 0) {
6888 return NT_STATUS_INVALID_PARAMETER
;
6891 if (req
->posix_pathnames
) {
6892 srvstr_get_path_posix(ctx
,
6901 srvstr_get_path(ctx
,
6910 if (!NT_STATUS_IS_OK(status
)) {
6914 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6915 smb_fname_str_dbg(smb_fname_new
), oldname
));
6917 status
= filename_convert(ctx
,
6924 if (!NT_STATUS_IS_OK(status
)) {
6928 return hardlink_internals(ctx
, conn
, req
, false,
6929 smb_fname_old
, smb_fname_new
);
6932 /****************************************************************************
6933 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6934 ****************************************************************************/
6936 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6937 struct smb_request
*req
,
6941 struct smb_filename
*smb_fname_src
)
6945 char *newname
= NULL
;
6946 struct smb_filename
*smb_fname_dst
= NULL
;
6947 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
6948 ucf_flags_from_smb_request(req
);
6949 NTSTATUS status
= NT_STATUS_OK
;
6950 TALLOC_CTX
*ctx
= talloc_tos();
6953 return NT_STATUS_INVALID_HANDLE
;
6956 if (total_data
< 20) {
6957 return NT_STATUS_INVALID_PARAMETER
;
6960 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6961 len
= IVAL(pdata
,16);
6963 if (len
> (total_data
- 20) || (len
== 0)) {
6964 return NT_STATUS_INVALID_PARAMETER
;
6967 if (req
->posix_pathnames
) {
6968 srvstr_get_path_posix(ctx
,
6977 srvstr_get_path(ctx
,
6986 if (!NT_STATUS_IS_OK(status
)) {
6990 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6993 status
= filename_convert(ctx
,
7000 if (!NT_STATUS_IS_OK(status
)) {
7004 if (fsp
->base_fsp
) {
7005 /* newname must be a stream name. */
7006 if (newname
[0] != ':') {
7007 return NT_STATUS_NOT_SUPPORTED
;
7010 /* Create an smb_fname to call rename_internals_fsp() with. */
7011 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7012 fsp
->base_fsp
->fsp_name
->base_name
,
7015 fsp
->base_fsp
->fsp_name
->flags
);
7016 if (smb_fname_dst
== NULL
) {
7017 status
= NT_STATUS_NO_MEMORY
;
7022 * Set the original last component, since
7023 * rename_internals_fsp() requires it.
7025 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7027 if (smb_fname_dst
->original_lcomp
== NULL
) {
7028 status
= NT_STATUS_NO_MEMORY
;
7034 DEBUG(10,("smb2_file_rename_information: "
7035 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7036 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7037 smb_fname_str_dbg(smb_fname_dst
)));
7038 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7039 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
7043 TALLOC_FREE(smb_fname_dst
);
7047 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
7048 struct smb_request
*req
,
7052 struct smb_filename
*smb_fname_src
)
7056 char *newname
= NULL
;
7057 struct smb_filename
*smb_fname_dst
= NULL
;
7058 NTSTATUS status
= NT_STATUS_OK
;
7059 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
7060 ucf_flags_from_smb_request(req
);
7061 TALLOC_CTX
*ctx
= talloc_tos();
7064 return NT_STATUS_INVALID_HANDLE
;
7067 if (total_data
< 20) {
7068 return NT_STATUS_INVALID_PARAMETER
;
7071 overwrite
= (CVAL(pdata
,0) ? true : false);
7072 len
= IVAL(pdata
,16);
7074 if (len
> (total_data
- 20) || (len
== 0)) {
7075 return NT_STATUS_INVALID_PARAMETER
;
7078 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
7079 srvstr_get_path_posix(ctx
,
7087 ucf_flags
|= UCF_POSIX_PATHNAMES
;
7089 srvstr_get_path(ctx
,
7098 if (!NT_STATUS_IS_OK(status
)) {
7102 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7105 status
= filename_convert(ctx
,
7112 if (!NT_STATUS_IS_OK(status
)) {
7116 if (fsp
->base_fsp
) {
7117 /* No stream names. */
7118 return NT_STATUS_NOT_SUPPORTED
;
7121 DEBUG(10,("smb_file_link_information: "
7122 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7123 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7124 smb_fname_str_dbg(smb_fname_dst
)));
7125 status
= hardlink_internals(ctx
,
7132 TALLOC_FREE(smb_fname_dst
);
7136 /****************************************************************************
7137 Deal with SMB_FILE_RENAME_INFORMATION.
7138 ****************************************************************************/
7140 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
7141 struct smb_request
*req
,
7145 struct smb_filename
*smb_fname_src
)
7150 char *newname
= NULL
;
7151 struct smb_filename
*smb_fname_dst
= NULL
;
7152 bool dest_has_wcard
= False
;
7153 NTSTATUS status
= NT_STATUS_OK
;
7155 TALLOC_CTX
*ctx
= talloc_tos();
7157 if (total_data
< 13) {
7158 return NT_STATUS_INVALID_PARAMETER
;
7161 overwrite
= (CVAL(pdata
,0) ? True
: False
);
7162 root_fid
= IVAL(pdata
,4);
7163 len
= IVAL(pdata
,8);
7165 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
7166 return NT_STATUS_INVALID_PARAMETER
;
7169 if (req
->posix_pathnames
) {
7170 srvstr_get_path_wcard_posix(ctx
,
7180 srvstr_get_path_wcard(ctx
,
7190 if (!NT_STATUS_IS_OK(status
)) {
7194 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7197 if (req
->flags2
& FLAGS2_DFS_PATHNAMES
) {
7198 status
= resolve_dfspath_wcard(ctx
, conn
,
7200 UCF_COND_ALLOW_WCARD_LCOMP
,
7201 !conn
->sconn
->using_smb2
,
7204 if (!NT_STATUS_IS_OK(status
)) {
7209 /* Check the new name has no '/' characters. */
7210 if (strchr_m(newname
, '/')) {
7211 return NT_STATUS_NOT_SUPPORTED
;
7214 if (fsp
&& fsp
->base_fsp
) {
7215 /* newname must be a stream name. */
7216 if (newname
[0] != ':') {
7217 return NT_STATUS_NOT_SUPPORTED
;
7220 /* Create an smb_fname to call rename_internals_fsp() with. */
7221 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7222 fsp
->base_fsp
->fsp_name
->base_name
,
7225 fsp
->base_fsp
->fsp_name
->flags
);
7226 if (smb_fname_dst
== NULL
) {
7227 status
= NT_STATUS_NO_MEMORY
;
7232 * Set the original last component, since
7233 * rename_internals_fsp() requires it.
7235 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7237 if (smb_fname_dst
->original_lcomp
== NULL
) {
7238 status
= NT_STATUS_NO_MEMORY
;
7244 * Build up an smb_fname_dst based on the filename passed in.
7245 * We basically just strip off the last component, and put on
7246 * the newname instead.
7248 char *base_name
= NULL
;
7249 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
7250 ucf_flags_from_smb_request(req
);
7252 if (dest_has_wcard
) {
7253 ucf_flags
|= UCF_ALWAYS_ALLOW_WCARD_LCOMP
;
7256 /* newname must *not* be a stream name. */
7257 if (newname
[0] == ':') {
7258 return NT_STATUS_NOT_SUPPORTED
;
7262 * Strip off the last component (filename) of the path passed
7265 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
7267 return NT_STATUS_NO_MEMORY
;
7269 p
= strrchr_m(base_name
, '/');
7273 base_name
= talloc_strdup(ctx
, "");
7275 return NT_STATUS_NO_MEMORY
;
7278 /* Append the new name. */
7279 base_name
= talloc_asprintf_append(base_name
,
7283 return NT_STATUS_NO_MEMORY
;
7286 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
7289 /* If an error we expect this to be
7290 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7292 if (!NT_STATUS_IS_OK(status
)) {
7293 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
7297 /* Create an smb_fname to call rename_internals_fsp() */
7298 smb_fname_dst
= synthetic_smb_fname(ctx
,
7302 smb_fname_src
->flags
);
7303 if (smb_fname_dst
== NULL
) {
7304 status
= NT_STATUS_NO_MEMORY
;
7311 DEBUG(10,("smb_file_rename_information: "
7312 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7313 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7314 smb_fname_str_dbg(smb_fname_dst
)));
7315 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
7318 DEBUG(10,("smb_file_rename_information: "
7319 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7320 smb_fname_str_dbg(smb_fname_src
),
7321 smb_fname_str_dbg(smb_fname_dst
)));
7322 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
7323 smb_fname_dst
, 0, overwrite
, false,
7325 FILE_WRITE_ATTRIBUTES
);
7328 TALLOC_FREE(smb_fname_dst
);
7332 /****************************************************************************
7333 Deal with SMB_SET_POSIX_ACL.
7334 ****************************************************************************/
7336 #if defined(HAVE_POSIX_ACLS)
7337 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
7338 struct smb_request
*req
,
7342 const struct smb_filename
*smb_fname
)
7344 uint16_t posix_acl_version
;
7345 uint16_t num_file_acls
;
7346 uint16_t num_def_acls
;
7347 bool valid_file_acls
= true;
7348 bool valid_def_acls
= true;
7350 unsigned int size_needed
;
7351 unsigned int total_data
;
7352 bool close_fsp
= false;
7354 if (total_data_in
< 0) {
7355 status
= NT_STATUS_INVALID_PARAMETER
;
7359 total_data
= total_data_in
;
7361 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
7362 status
= NT_STATUS_INVALID_PARAMETER
;
7365 posix_acl_version
= SVAL(pdata
,0);
7366 num_file_acls
= SVAL(pdata
,2);
7367 num_def_acls
= SVAL(pdata
,4);
7369 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7370 valid_file_acls
= false;
7374 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7375 valid_def_acls
= false;
7379 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
7380 status
= NT_STATUS_INVALID_PARAMETER
;
7385 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
7386 status
= NT_STATUS_INVALID_PARAMETER
;
7390 size_needed
= num_file_acls
+ num_def_acls
;
7393 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7394 * than UINT_MAX, so check by division.
7396 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
7397 status
= NT_STATUS_INVALID_PARAMETER
;
7401 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
7402 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
7403 status
= NT_STATUS_INVALID_PARAMETER
;
7406 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
7408 if (total_data
< size_needed
) {
7409 status
= NT_STATUS_INVALID_PARAMETER
;
7414 * Ensure we always operate on a file descriptor, not just
7418 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
7420 SEC_STD_READ_CONTROL
|
7421 FILE_READ_ATTRIBUTES
|
7422 FILE_WRITE_ATTRIBUTES
;
7424 status
= get_posix_fsp(conn
,
7430 if (!NT_STATUS_IS_OK(status
)) {
7436 /* Here we know fsp != NULL */
7437 SMB_ASSERT(fsp
!= NULL
);
7439 status
= refuse_symlink(conn
, fsp
, fsp
->fsp_name
);
7440 if (!NT_STATUS_IS_OK(status
)) {
7444 /* If we have a default acl, this *must* be a directory. */
7445 if (valid_def_acls
&& !fsp
->is_directory
) {
7446 DBG_INFO("Can't set default acls on "
7447 "non-directory %s\n",
7449 return NT_STATUS_INVALID_HANDLE
;
7452 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
7453 "num_def_acls = %"PRIu16
"\n",
7458 /* Move pdata to the start of the file ACL entries. */
7459 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
7461 if (valid_file_acls
) {
7462 status
= set_unix_posix_acl(conn
,
7466 if (!NT_STATUS_IS_OK(status
)) {
7471 /* Move pdata to the start of the default ACL entries. */
7472 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
7474 if (valid_def_acls
) {
7475 status
= set_unix_posix_default_acl(conn
,
7479 if (!NT_STATUS_IS_OK(status
)) {
7484 status
= NT_STATUS_OK
;
7489 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
7496 /****************************************************************************
7497 Deal with SMB_SET_POSIX_LOCK.
7498 ****************************************************************************/
7500 static void smb_set_posix_lock_done(struct tevent_req
*subreq
);
7502 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
7503 struct smb_request
*req
,
7508 struct tevent_req
*subreq
= NULL
;
7509 struct smbd_lock_element
*lck
= NULL
;
7513 bool blocking_lock
= False
;
7514 enum brl_type lock_type
;
7516 NTSTATUS status
= NT_STATUS_OK
;
7518 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
7519 return NT_STATUS_INVALID_HANDLE
;
7522 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
7523 return NT_STATUS_INVALID_PARAMETER
;
7526 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
7527 case POSIX_LOCK_TYPE_READ
:
7528 lock_type
= READ_LOCK
;
7530 case POSIX_LOCK_TYPE_WRITE
:
7531 /* Return the right POSIX-mappable error code for files opened read-only. */
7532 if (!fsp
->can_write
) {
7533 return NT_STATUS_INVALID_HANDLE
;
7535 lock_type
= WRITE_LOCK
;
7537 case POSIX_LOCK_TYPE_UNLOCK
:
7538 lock_type
= UNLOCK_LOCK
;
7541 return NT_STATUS_INVALID_PARAMETER
;
7544 switch (SVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
)) {
7545 case POSIX_LOCK_FLAG_NOWAIT
:
7546 blocking_lock
= false;
7548 case POSIX_LOCK_FLAG_WAIT
:
7549 blocking_lock
= true;
7552 return NT_STATUS_INVALID_PARAMETER
;
7555 if (!lp_blocking_locks(SNUM(conn
))) {
7556 blocking_lock
= False
;
7559 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
7560 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
7561 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
7562 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
7563 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
7565 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64
", "
7566 "count = %"PRIu64
", offset = %"PRIu64
"\n",
7568 (unsigned int)lock_type
,
7573 if (lock_type
== UNLOCK_LOCK
) {
7574 struct smbd_lock_element l
= {
7576 .brltype
= UNLOCK_LOCK
,
7580 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, POSIX_LOCK
);
7584 lck
= talloc(req
, struct smbd_lock_element
);
7586 return NT_STATUS_NO_MEMORY
;
7589 *lck
= (struct smbd_lock_element
) {
7591 .brltype
= lock_type
,
7596 subreq
= smbd_smb1_do_locks_send(
7601 blocking_lock
? UINT32_MAX
: 0,
7602 true, /* large_offset */
7606 if (subreq
== NULL
) {
7608 return NT_STATUS_NO_MEMORY
;
7610 tevent_req_set_callback(subreq
, smb_set_posix_lock_done
, req
);
7611 return NT_STATUS_EVENT_PENDING
;
7614 static void smb_set_posix_lock_done(struct tevent_req
*subreq
)
7616 struct smb_request
*req
= NULL
;
7620 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
7623 status
= smbd_smb1_do_locks_recv(subreq
);
7624 TALLOC_FREE(subreq
);
7626 if (NT_STATUS_IS_OK(status
)) {
7627 char params
[2] = {0};
7628 /* Fake up max_data_bytes here - we know it fits. */
7629 send_trans2_replies(
7639 reply_nterror(req
, status
);
7642 (char *)req
->outbuf
,
7645 IS_CONN_ENCRYPTED(req
->conn
),
7648 exit_server_cleanly("smb_set_posix_lock_done: "
7649 "srv_send_smb failed.");
7657 /****************************************************************************
7658 Deal with SMB_SET_FILE_BASIC_INFO.
7659 ****************************************************************************/
7661 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
7665 const struct smb_filename
*smb_fname
)
7667 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7668 struct smb_file_time ft
;
7669 uint32_t dosmode
= 0;
7670 NTSTATUS status
= NT_STATUS_OK
;
7674 if (total_data
< 36) {
7675 return NT_STATUS_INVALID_PARAMETER
;
7678 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7679 if (!NT_STATUS_IS_OK(status
)) {
7683 /* Set the attributes */
7684 dosmode
= IVAL(pdata
,32);
7685 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
7686 if (!NT_STATUS_IS_OK(status
)) {
7691 ft
.create_time
= interpret_long_date(pdata
);
7694 ft
.atime
= interpret_long_date(pdata
+8);
7697 ft
.mtime
= interpret_long_date(pdata
+16);
7700 ft
.ctime
= interpret_long_date(pdata
+24);
7702 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7703 smb_fname_str_dbg(smb_fname
)));
7705 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
7709 /****************************************************************************
7710 Deal with SMB_INFO_STANDARD.
7711 ****************************************************************************/
7713 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
7717 const struct smb_filename
*smb_fname
)
7720 struct smb_file_time ft
;
7724 if (total_data
< 12) {
7725 return NT_STATUS_INVALID_PARAMETER
;
7729 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
7731 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
7733 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
7735 DEBUG(10,("smb_set_info_standard: file %s\n",
7736 smb_fname_str_dbg(smb_fname
)));
7738 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7739 if (!NT_STATUS_IS_OK(status
)) {
7743 return smb_set_file_time(conn
,
7750 /****************************************************************************
7751 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7752 ****************************************************************************/
7754 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7755 struct smb_request
*req
,
7759 struct smb_filename
*smb_fname
)
7761 uint64_t allocation_size
= 0;
7762 NTSTATUS status
= NT_STATUS_OK
;
7763 files_struct
*new_fsp
= NULL
;
7765 if (!VALID_STAT(smb_fname
->st
)) {
7766 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7769 if (total_data
< 8) {
7770 return NT_STATUS_INVALID_PARAMETER
;
7773 allocation_size
= (uint64_t)IVAL(pdata
,0);
7774 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7775 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7776 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7777 (double)allocation_size
));
7779 if (allocation_size
) {
7780 allocation_size
= smb_roundup(conn
, allocation_size
);
7783 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7784 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7785 (double)allocation_size
));
7787 if (fsp
&& fsp
->fh
->fd
!= -1) {
7788 /* Open file handle. */
7789 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7790 return NT_STATUS_ACCESS_DENIED
;
7793 /* Only change if needed. */
7794 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7795 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7796 return map_nt_error_from_unix(errno
);
7799 /* But always update the time. */
7801 * This is equivalent to a write. Ensure it's seen immediately
7802 * if there are no pending writes.
7804 trigger_write_time_update_immediate(fsp
);
7805 return NT_STATUS_OK
;
7808 /* Pathname or stat or directory file. */
7809 status
= SMB_VFS_CREATE_FILE(
7812 0, /* root_dir_fid */
7813 smb_fname
, /* fname */
7814 FILE_WRITE_DATA
, /* access_mask */
7815 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7817 FILE_OPEN
, /* create_disposition*/
7818 0, /* create_options */
7819 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7820 0, /* oplock_request */
7822 0, /* allocation_size */
7823 0, /* private_flags */
7826 &new_fsp
, /* result */
7828 NULL
, NULL
); /* create context */
7830 if (!NT_STATUS_IS_OK(status
)) {
7831 /* NB. We check for open_was_deferred in the caller. */
7835 /* Only change if needed. */
7836 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7837 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7838 status
= map_nt_error_from_unix(errno
);
7839 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7844 /* Changing the allocation size should set the last mod time. */
7846 * This is equivalent to a write. Ensure it's seen immediately
7847 * if there are no pending writes.
7849 trigger_write_time_update_immediate(new_fsp
);
7850 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7851 return NT_STATUS_OK
;
7854 /****************************************************************************
7855 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7856 ****************************************************************************/
7858 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7859 struct smb_request
*req
,
7863 const struct smb_filename
*smb_fname
,
7864 bool fail_after_createfile
)
7868 if (total_data
< 8) {
7869 return NT_STATUS_INVALID_PARAMETER
;
7872 size
= IVAL(pdata
,0);
7873 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7874 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7875 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7878 return smb_set_file_size(conn
, req
,
7883 fail_after_createfile
);
7886 /****************************************************************************
7887 Allow a UNIX info mknod.
7888 ****************************************************************************/
7890 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7893 const struct smb_filename
*smb_fname
)
7895 uint32_t file_type
= IVAL(pdata
,56);
7896 #if defined(HAVE_MAKEDEV)
7897 uint32_t dev_major
= IVAL(pdata
,60);
7898 uint32_t dev_minor
= IVAL(pdata
,68);
7900 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7901 uint32_t raw_unixmode
= IVAL(pdata
,84);
7905 if (total_data
< 100) {
7906 return NT_STATUS_INVALID_PARAMETER
;
7909 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7910 PERM_NEW_FILE
, &unixmode
);
7911 if (!NT_STATUS_IS_OK(status
)) {
7915 #if defined(HAVE_MAKEDEV)
7916 dev
= makedev(dev_major
, dev_minor
);
7919 switch (file_type
) {
7920 #if defined(S_IFIFO)
7921 case UNIX_TYPE_FIFO
:
7922 unixmode
|= S_IFIFO
;
7925 #if defined(S_IFSOCK)
7926 case UNIX_TYPE_SOCKET
:
7927 unixmode
|= S_IFSOCK
;
7930 #if defined(S_IFCHR)
7931 case UNIX_TYPE_CHARDEV
:
7932 unixmode
|= S_IFCHR
;
7935 #if defined(S_IFBLK)
7936 case UNIX_TYPE_BLKDEV
:
7937 unixmode
|= S_IFBLK
;
7941 return NT_STATUS_INVALID_PARAMETER
;
7944 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7945 "%.0f mode 0%o for file %s\n", (double)dev
,
7946 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7948 /* Ok - do the mknod. */
7949 if (SMB_VFS_MKNOD(conn
, smb_fname
, unixmode
, dev
) != 0) {
7950 return map_nt_error_from_unix(errno
);
7953 /* If any of the other "set" calls fail we
7954 * don't want to end up with a half-constructed mknod.
7957 if (lp_inherit_permissions(SNUM(conn
))) {
7959 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7961 return NT_STATUS_NO_MEMORY
;
7963 inherit_access_posix_acl(conn
, parent
, smb_fname
,
7965 TALLOC_FREE(parent
);
7968 return NT_STATUS_OK
;
7971 /****************************************************************************
7972 Deal with SMB_SET_FILE_UNIX_BASIC.
7973 ****************************************************************************/
7975 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7976 struct smb_request
*req
,
7980 const struct smb_filename
*smb_fname
)
7982 struct smb_file_time ft
;
7983 uint32_t raw_unixmode
;
7986 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7987 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7988 NTSTATUS status
= NT_STATUS_OK
;
7989 bool delete_on_fail
= False
;
7990 enum perm_type ptype
;
7991 files_struct
*all_fsps
= NULL
;
7992 bool modify_mtime
= true;
7994 struct smb_filename
*smb_fname_tmp
= NULL
;
7995 SMB_STRUCT_STAT sbuf
;
7999 if (total_data
< 100) {
8000 return NT_STATUS_INVALID_PARAMETER
;
8003 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
8004 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
8005 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
8006 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
8009 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
8010 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
8011 set_owner
= (uid_t
)IVAL(pdata
,40);
8012 set_grp
= (gid_t
)IVAL(pdata
,48);
8013 raw_unixmode
= IVAL(pdata
,84);
8015 if (VALID_STAT(smb_fname
->st
)) {
8016 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
8017 ptype
= PERM_EXISTING_DIR
;
8019 ptype
= PERM_EXISTING_FILE
;
8022 ptype
= PERM_NEW_FILE
;
8025 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8027 if (!NT_STATUS_IS_OK(status
)) {
8031 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8032 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8033 smb_fname_str_dbg(smb_fname
), (double)size
,
8034 (unsigned int)set_owner
, (unsigned int)set_grp
,
8035 (int)raw_unixmode
));
8037 sbuf
= smb_fname
->st
;
8039 if (!VALID_STAT(sbuf
)) {
8041 * The only valid use of this is to create character and block
8042 * devices, and named pipes. This is deprecated (IMHO) and
8043 * a new info level should be used for mknod. JRA.
8046 status
= smb_unix_mknod(conn
,
8050 if (!NT_STATUS_IS_OK(status
)) {
8054 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
8055 if (smb_fname_tmp
== NULL
) {
8056 return NT_STATUS_NO_MEMORY
;
8059 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
8060 status
= map_nt_error_from_unix(errno
);
8061 TALLOC_FREE(smb_fname_tmp
);
8062 SMB_VFS_UNLINK(conn
, smb_fname
);
8066 sbuf
= smb_fname_tmp
->st
;
8067 smb_fname
= smb_fname_tmp
;
8069 /* Ensure we don't try and change anything else. */
8070 raw_unixmode
= SMB_MODE_NO_CHANGE
;
8071 size
= get_file_size_stat(&sbuf
);
8072 ft
.atime
= sbuf
.st_ex_atime
;
8073 ft
.mtime
= sbuf
.st_ex_mtime
;
8075 * We continue here as we might want to change the
8078 delete_on_fail
= True
;
8082 /* Horrible backwards compatibility hack as an old server bug
8083 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8087 size
= get_file_size_stat(&sbuf
);
8092 * Deal with the UNIX specific mode set.
8095 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
8098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8099 "setting mode 0%o for file %s\n",
8100 (unsigned int)unixmode
,
8101 smb_fname_str_dbg(smb_fname
)));
8102 if (fsp
&& fsp
->fh
->fd
!= -1) {
8103 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
8105 ret
= SMB_VFS_CHMOD(conn
, smb_fname
, unixmode
);
8108 return map_nt_error_from_unix(errno
);
8113 * Deal with the UNIX specific uid set.
8116 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
8117 (sbuf
.st_ex_uid
!= set_owner
)) {
8120 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8121 "changing owner %u for path %s\n",
8122 (unsigned int)set_owner
,
8123 smb_fname_str_dbg(smb_fname
)));
8125 if (fsp
&& fsp
->fh
->fd
!= -1) {
8126 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
8129 * UNIX extensions calls must always operate
8132 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
8133 set_owner
, (gid_t
)-1);
8137 status
= map_nt_error_from_unix(errno
);
8138 if (delete_on_fail
) {
8139 SMB_VFS_UNLINK(conn
, smb_fname
);
8146 * Deal with the UNIX specific gid set.
8149 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
8150 (sbuf
.st_ex_gid
!= set_grp
)) {
8153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8154 "changing group %u for file %s\n",
8155 (unsigned int)set_grp
,
8156 smb_fname_str_dbg(smb_fname
)));
8157 if (fsp
&& fsp
->fh
->fd
!= -1) {
8158 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
8161 * UNIX extensions calls must always operate
8164 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
8168 status
= map_nt_error_from_unix(errno
);
8169 if (delete_on_fail
) {
8170 SMB_VFS_UNLINK(conn
, smb_fname
);
8176 /* Deal with any size changes. */
8178 status
= smb_set_file_size(conn
, req
,
8184 if (!NT_STATUS_IS_OK(status
)) {
8188 /* Deal with any time changes. */
8189 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
8190 /* No change, don't cancel anything. */
8194 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
8195 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
8196 all_fsps
= file_find_di_next(all_fsps
)) {
8198 * We're setting the time explicitly for UNIX.
8199 * Cancel any pending changes over all handles.
8201 all_fsps
->update_write_time_on_close
= false;
8202 TALLOC_FREE(all_fsps
->update_write_time_event
);
8206 * Override the "setting_write_time"
8207 * parameter here as it almost does what
8208 * we need. Just remember if we modified
8209 * mtime and send the notify ourselves.
8211 if (null_timespec(ft
.mtime
)) {
8212 modify_mtime
= false;
8215 status
= smb_set_file_time(conn
,
8221 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
8222 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
8227 /****************************************************************************
8228 Deal with SMB_SET_FILE_UNIX_INFO2.
8229 ****************************************************************************/
8231 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
8232 struct smb_request
*req
,
8236 const struct smb_filename
*smb_fname
)
8239 uint32_t smb_fflags
;
8242 if (total_data
< 116) {
8243 return NT_STATUS_INVALID_PARAMETER
;
8246 /* Start by setting all the fields that are common between UNIX_BASIC
8249 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
8251 if (!NT_STATUS_IS_OK(status
)) {
8255 smb_fflags
= IVAL(pdata
, 108);
8256 smb_fmask
= IVAL(pdata
, 112);
8258 /* NB: We should only attempt to alter the file flags if the client
8259 * sends a non-zero mask.
8261 if (smb_fmask
!= 0) {
8262 int stat_fflags
= 0;
8264 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
8265 smb_fmask
, &stat_fflags
)) {
8266 /* Client asked to alter a flag we don't understand. */
8267 return NT_STATUS_INVALID_PARAMETER
;
8270 if (fsp
&& fsp
->fh
->fd
!= -1) {
8271 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8272 return NT_STATUS_NOT_SUPPORTED
;
8274 if (SMB_VFS_CHFLAGS(conn
, smb_fname
,
8275 stat_fflags
) != 0) {
8276 return map_nt_error_from_unix(errno
);
8281 /* XXX: need to add support for changing the create_time here. You
8282 * can do this for paths on Darwin with setattrlist(2). The right way
8283 * to hook this up is probably by extending the VFS utimes interface.
8286 return NT_STATUS_OK
;
8289 /****************************************************************************
8290 Create a directory with POSIX semantics.
8291 ****************************************************************************/
8293 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
8294 struct smb_request
*req
,
8297 struct smb_filename
*smb_fname
,
8298 int *pdata_return_size
)
8300 NTSTATUS status
= NT_STATUS_OK
;
8301 uint32_t raw_unixmode
= 0;
8302 uint32_t mod_unixmode
= 0;
8303 mode_t unixmode
= (mode_t
)0;
8304 files_struct
*fsp
= NULL
;
8305 uint16_t info_level_return
= 0;
8307 char *pdata
= *ppdata
;
8309 if (total_data
< 18) {
8310 return NT_STATUS_INVALID_PARAMETER
;
8313 raw_unixmode
= IVAL(pdata
,8);
8314 /* Next 4 bytes are not yet defined. */
8316 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8317 PERM_NEW_DIR
, &unixmode
);
8318 if (!NT_STATUS_IS_OK(status
)) {
8322 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
8324 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8325 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
8327 status
= SMB_VFS_CREATE_FILE(
8330 0, /* root_dir_fid */
8331 smb_fname
, /* fname */
8332 FILE_READ_ATTRIBUTES
, /* access_mask */
8333 FILE_SHARE_NONE
, /* share_access */
8334 FILE_CREATE
, /* create_disposition*/
8335 FILE_DIRECTORY_FILE
, /* create_options */
8336 mod_unixmode
, /* file_attributes */
8337 0, /* oplock_request */
8339 0, /* allocation_size */
8340 0, /* private_flags */
8345 NULL
, NULL
); /* create context */
8347 if (NT_STATUS_IS_OK(status
)) {
8348 close_file(req
, fsp
, NORMAL_CLOSE
);
8351 info_level_return
= SVAL(pdata
,16);
8353 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8354 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8355 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8356 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8358 *pdata_return_size
= 12;
8361 /* Realloc the data size */
8362 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8363 if (*ppdata
== NULL
) {
8364 *pdata_return_size
= 0;
8365 return NT_STATUS_NO_MEMORY
;
8369 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8370 SSVAL(pdata
,2,0); /* No fnum. */
8371 SIVAL(pdata
,4,info
); /* Was directory created. */
8373 switch (info_level_return
) {
8374 case SMB_QUERY_FILE_UNIX_BASIC
:
8375 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8376 SSVAL(pdata
,10,0); /* Padding. */
8377 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8380 case SMB_QUERY_FILE_UNIX_INFO2
:
8381 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8382 SSVAL(pdata
,10,0); /* Padding. */
8383 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8387 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8388 SSVAL(pdata
,10,0); /* Padding. */
8395 /****************************************************************************
8396 Open/Create a file with POSIX semantics.
8397 ****************************************************************************/
8399 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8400 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8402 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
8403 struct smb_request
*req
,
8406 struct smb_filename
*smb_fname
,
8407 int *pdata_return_size
)
8409 bool extended_oplock_granted
= False
;
8410 char *pdata
= *ppdata
;
8412 uint32_t wire_open_mode
= 0;
8413 uint32_t raw_unixmode
= 0;
8414 uint32_t mod_unixmode
= 0;
8415 uint32_t create_disp
= 0;
8416 uint32_t access_mask
= 0;
8417 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
8418 NTSTATUS status
= NT_STATUS_OK
;
8419 mode_t unixmode
= (mode_t
)0;
8420 files_struct
*fsp
= NULL
;
8421 int oplock_request
= 0;
8423 uint16_t info_level_return
= 0;
8425 if (total_data
< 18) {
8426 return NT_STATUS_INVALID_PARAMETER
;
8429 flags
= IVAL(pdata
,0);
8430 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
8431 if (oplock_request
) {
8432 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
8435 wire_open_mode
= IVAL(pdata
,4);
8437 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
8438 return smb_posix_mkdir(conn
, req
,
8445 switch (wire_open_mode
& SMB_ACCMODE
) {
8447 access_mask
= SMB_O_RDONLY_MAPPING
;
8450 access_mask
= SMB_O_WRONLY_MAPPING
;
8453 access_mask
= (SMB_O_RDONLY_MAPPING
|
8454 SMB_O_WRONLY_MAPPING
);
8457 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8458 (unsigned int)wire_open_mode
));
8459 return NT_STATUS_INVALID_PARAMETER
;
8462 wire_open_mode
&= ~SMB_ACCMODE
;
8464 /* First take care of O_CREAT|O_EXCL interactions. */
8465 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
8466 case (SMB_O_CREAT
| SMB_O_EXCL
):
8467 /* File exists fail. File not exist create. */
8468 create_disp
= FILE_CREATE
;
8471 /* File exists open. File not exist create. */
8472 create_disp
= FILE_OPEN_IF
;
8475 /* O_EXCL on its own without O_CREAT is undefined.
8476 We deliberately ignore it as some versions of
8477 Linux CIFSFS can send a bare O_EXCL on the
8478 wire which other filesystems in the kernel
8479 ignore. See bug 9519 for details. */
8484 /* File exists open. File not exist fail. */
8485 create_disp
= FILE_OPEN
;
8488 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8489 (unsigned int)wire_open_mode
));
8490 return NT_STATUS_INVALID_PARAMETER
;
8493 /* Next factor in the effects of O_TRUNC. */
8494 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
8496 if (wire_open_mode
& SMB_O_TRUNC
) {
8497 switch (create_disp
) {
8499 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8500 /* Leave create_disp alone as
8501 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8503 /* File exists fail. File not exist create. */
8506 /* SMB_O_CREAT | SMB_O_TRUNC */
8507 /* File exists overwrite. File not exist create. */
8508 create_disp
= FILE_OVERWRITE_IF
;
8512 /* File exists overwrite. File not exist fail. */
8513 create_disp
= FILE_OVERWRITE
;
8516 /* Cannot get here. */
8517 smb_panic("smb_posix_open: logic error");
8518 return NT_STATUS_INVALID_PARAMETER
;
8522 raw_unixmode
= IVAL(pdata
,8);
8523 /* Next 4 bytes are not yet defined. */
8525 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8526 (VALID_STAT(smb_fname
->st
) ?
8527 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
8530 if (!NT_STATUS_IS_OK(status
)) {
8534 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
8536 if (wire_open_mode
& SMB_O_SYNC
) {
8537 create_options
|= FILE_WRITE_THROUGH
;
8539 if (wire_open_mode
& SMB_O_APPEND
) {
8540 access_mask
|= FILE_APPEND_DATA
;
8542 if (wire_open_mode
& SMB_O_DIRECT
) {
8543 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
8546 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
8547 VALID_STAT_OF_DIR(smb_fname
->st
)) {
8548 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
8549 return NT_STATUS_FILE_IS_A_DIRECTORY
;
8551 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
8552 create_options
|= FILE_DIRECTORY_FILE
;
8555 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8556 smb_fname_str_dbg(smb_fname
),
8557 (unsigned int)wire_open_mode
,
8558 (unsigned int)unixmode
));
8560 status
= SMB_VFS_CREATE_FILE(
8563 0, /* root_dir_fid */
8564 smb_fname
, /* fname */
8565 access_mask
, /* access_mask */
8566 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8568 create_disp
, /* create_disposition*/
8569 create_options
, /* create_options */
8570 mod_unixmode
, /* file_attributes */
8571 oplock_request
, /* oplock_request */
8573 0, /* allocation_size */
8574 0, /* private_flags */
8579 NULL
, NULL
); /* create context */
8581 if (!NT_STATUS_IS_OK(status
)) {
8585 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
8586 extended_oplock_granted
= True
;
8589 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
8590 extended_oplock_granted
= True
;
8593 info_level_return
= SVAL(pdata
,16);
8595 /* Allocate the correct return size. */
8597 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8598 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8599 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8600 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8602 *pdata_return_size
= 12;
8605 /* Realloc the data size */
8606 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8607 if (*ppdata
== NULL
) {
8608 close_file(req
, fsp
, ERROR_CLOSE
);
8609 *pdata_return_size
= 0;
8610 return NT_STATUS_NO_MEMORY
;
8614 if (extended_oplock_granted
) {
8615 if (flags
& REQUEST_BATCH_OPLOCK
) {
8616 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
8618 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
8620 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
8621 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
8623 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8626 SSVAL(pdata
,2,fsp
->fnum
);
8627 SIVAL(pdata
,4,info
); /* Was file created etc. */
8629 switch (info_level_return
) {
8630 case SMB_QUERY_FILE_UNIX_BASIC
:
8631 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8632 SSVAL(pdata
,10,0); /* padding. */
8633 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8636 case SMB_QUERY_FILE_UNIX_INFO2
:
8637 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8638 SSVAL(pdata
,10,0); /* padding. */
8639 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8643 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8644 SSVAL(pdata
,10,0); /* padding. */
8647 return NT_STATUS_OK
;
8650 /****************************************************************************
8651 Delete a file with POSIX semantics.
8652 ****************************************************************************/
8654 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
8655 struct smb_request
*req
,
8658 struct smb_filename
*smb_fname
)
8660 struct server_id self
= messaging_server_id(conn
->sconn
->msg_ctx
);
8661 NTSTATUS status
= NT_STATUS_OK
;
8662 files_struct
*fsp
= NULL
;
8666 int create_options
= 0;
8667 struct share_mode_lock
*lck
= NULL
;
8668 bool other_nonposix_opens
;
8670 if (total_data
< 2) {
8671 return NT_STATUS_INVALID_PARAMETER
;
8674 flags
= SVAL(pdata
,0);
8676 if (!VALID_STAT(smb_fname
->st
)) {
8677 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8680 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
8681 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
8682 return NT_STATUS_NOT_A_DIRECTORY
;
8685 DEBUG(10,("smb_posix_unlink: %s %s\n",
8686 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
8687 smb_fname_str_dbg(smb_fname
)));
8689 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
8690 create_options
|= FILE_DIRECTORY_FILE
;
8693 status
= SMB_VFS_CREATE_FILE(
8696 0, /* root_dir_fid */
8697 smb_fname
, /* fname */
8698 DELETE_ACCESS
, /* access_mask */
8699 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8701 FILE_OPEN
, /* create_disposition*/
8702 create_options
, /* create_options */
8703 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
8704 0, /* oplock_request */
8706 0, /* allocation_size */
8707 0, /* private_flags */
8712 NULL
, NULL
); /* create context */
8714 if (!NT_STATUS_IS_OK(status
)) {
8719 * Don't lie to client. If we can't really delete due to
8720 * non-POSIX opens return SHARING_VIOLATION.
8723 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
8725 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8726 "lock for file %s\n", fsp_str_dbg(fsp
)));
8727 close_file(req
, fsp
, NORMAL_CLOSE
);
8728 return NT_STATUS_INVALID_PARAMETER
;
8731 other_nonposix_opens
= has_other_nonposix_opens(lck
, fsp
, self
);
8732 if (other_nonposix_opens
) {
8733 /* Fail with sharing violation. */
8735 close_file(req
, fsp
, NORMAL_CLOSE
);
8736 return NT_STATUS_SHARING_VIOLATION
;
8740 * Set the delete on close.
8742 status
= smb_set_file_disposition_info(conn
,
8750 if (!NT_STATUS_IS_OK(status
)) {
8751 close_file(req
, fsp
, NORMAL_CLOSE
);
8754 return close_file(req
, fsp
, NORMAL_CLOSE
);
8757 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8758 struct smb_request
*req
,
8759 TALLOC_CTX
*mem_ctx
,
8760 uint16_t info_level
,
8762 struct smb_filename
*smb_fname
,
8763 char **ppdata
, int total_data
,
8766 char *pdata
= *ppdata
;
8767 NTSTATUS status
= NT_STATUS_OK
;
8768 int data_return_size
= 0;
8772 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8773 return NT_STATUS_INVALID_LEVEL
;
8776 if (!CAN_WRITE(conn
)) {
8777 /* Allow POSIX opens. The open path will deny
8778 * any non-readonly opens. */
8779 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8780 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8784 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8785 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8787 info_level
, total_data
));
8789 switch (info_level
) {
8791 case SMB_INFO_STANDARD
:
8793 status
= smb_set_info_standard(conn
,
8801 case SMB_INFO_SET_EA
:
8803 status
= smb_info_set_ea(conn
,
8811 case SMB_SET_FILE_BASIC_INFO
:
8812 case SMB_FILE_BASIC_INFORMATION
:
8814 status
= smb_set_file_basic_info(conn
,
8822 case SMB_FILE_ALLOCATION_INFORMATION
:
8823 case SMB_SET_FILE_ALLOCATION_INFO
:
8825 status
= smb_set_file_allocation_info(conn
, req
,
8833 case SMB_FILE_END_OF_FILE_INFORMATION
:
8834 case SMB_SET_FILE_END_OF_FILE_INFO
:
8837 * XP/Win7 both fail after the createfile with
8838 * SMB_SET_FILE_END_OF_FILE_INFO but not
8839 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8840 * The level is known here, so pass it down
8844 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8846 status
= smb_set_file_end_of_file_info(conn
, req
,
8855 case SMB_FILE_DISPOSITION_INFORMATION
:
8856 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8859 /* JRA - We used to just ignore this on a path ?
8860 * Shouldn't this be invalid level on a pathname
8863 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8864 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8867 status
= smb_set_file_disposition_info(conn
,
8875 case SMB_FILE_POSITION_INFORMATION
:
8877 status
= smb_file_position_information(conn
,
8884 case SMB_FILE_FULL_EA_INFORMATION
:
8886 status
= smb_set_file_full_ea_info(conn
,
8893 /* From tridge Samba4 :
8894 * MODE_INFORMATION in setfileinfo (I have no
8895 * idea what "mode information" on a file is - it takes a value of 0,
8896 * 2, 4 or 6. What could it be?).
8899 case SMB_FILE_MODE_INFORMATION
:
8901 status
= smb_file_mode_information(conn
,
8907 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8908 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
8909 case SMB_FILE_SHORT_NAME_INFORMATION
:
8910 return NT_STATUS_NOT_SUPPORTED
;
8913 * CIFS UNIX extensions.
8916 case SMB_SET_FILE_UNIX_BASIC
:
8918 status
= smb_set_file_unix_basic(conn
, req
,
8926 case SMB_SET_FILE_UNIX_INFO2
:
8928 status
= smb_set_file_unix_info2(conn
, req
,
8936 case SMB_SET_FILE_UNIX_LINK
:
8939 /* We must have a pathname for this. */
8940 return NT_STATUS_INVALID_LEVEL
;
8942 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8943 total_data
, smb_fname
);
8947 case SMB_SET_FILE_UNIX_HLINK
:
8950 /* We must have a pathname for this. */
8951 return NT_STATUS_INVALID_LEVEL
;
8953 status
= smb_set_file_unix_hlink(conn
, req
,
8959 case SMB_FILE_RENAME_INFORMATION
:
8961 status
= smb_file_rename_information(conn
, req
,
8967 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8969 /* SMB2 rename information. */
8970 status
= smb2_file_rename_information(conn
, req
,
8976 case SMB_FILE_LINK_INFORMATION
:
8978 status
= smb_file_link_information(conn
, req
,
8984 #if defined(HAVE_POSIX_ACLS)
8985 case SMB_SET_POSIX_ACL
:
8987 status
= smb_set_posix_acl(conn
,
8997 case SMB_SET_POSIX_LOCK
:
9000 return NT_STATUS_INVALID_LEVEL
;
9002 status
= smb_set_posix_lock(conn
, req
,
9003 pdata
, total_data
, fsp
);
9007 case SMB_POSIX_PATH_OPEN
:
9010 /* We must have a pathname for this. */
9011 return NT_STATUS_INVALID_LEVEL
;
9014 status
= smb_posix_open(conn
, req
,
9022 case SMB_POSIX_PATH_UNLINK
:
9025 /* We must have a pathname for this. */
9026 return NT_STATUS_INVALID_LEVEL
;
9029 status
= smb_posix_unlink(conn
, req
,
9037 return NT_STATUS_INVALID_LEVEL
;
9040 if (!NT_STATUS_IS_OK(status
)) {
9044 *ret_data_size
= data_return_size
;
9045 return NT_STATUS_OK
;
9048 /****************************************************************************
9049 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9050 ****************************************************************************/
9052 static void call_trans2setfilepathinfo(connection_struct
*conn
,
9053 struct smb_request
*req
,
9054 unsigned int tran_call
,
9055 char **pparams
, int total_params
,
9056 char **ppdata
, int total_data
,
9057 unsigned int max_data_bytes
)
9059 char *params
= *pparams
;
9060 char *pdata
= *ppdata
;
9061 uint16_t info_level
;
9062 struct smb_filename
*smb_fname
= NULL
;
9063 files_struct
*fsp
= NULL
;
9064 NTSTATUS status
= NT_STATUS_OK
;
9065 int data_return_size
= 0;
9068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9072 if (tran_call
== TRANSACT2_SETFILEINFO
) {
9073 if (total_params
< 4) {
9074 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9078 fsp
= file_fsp(req
, SVAL(params
,0));
9079 /* Basic check for non-null fsp. */
9080 if (!check_fsp_open(conn
, req
, fsp
)) {
9083 info_level
= SVAL(params
,2);
9085 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
9086 if (smb_fname
== NULL
) {
9087 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9091 if(fsp
->fh
->fd
== -1) {
9093 * This is actually a SETFILEINFO on a directory
9094 * handle (returned from an NT SMB). NT5.0 seems
9095 * to do this call. JRA.
9097 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9098 /* Always do lstat for UNIX calls. */
9099 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
9100 DEBUG(3,("call_trans2setfilepathinfo: "
9101 "SMB_VFS_LSTAT of %s failed "
9103 smb_fname_str_dbg(smb_fname
),
9105 reply_nterror(req
, map_nt_error_from_unix(errno
));
9109 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
9110 DEBUG(3,("call_trans2setfilepathinfo: "
9111 "fileinfo of %s failed (%s)\n",
9112 smb_fname_str_dbg(smb_fname
),
9114 reply_nterror(req
, map_nt_error_from_unix(errno
));
9118 } else if (fsp
->print_file
) {
9120 * Doing a DELETE_ON_CLOSE should cancel a print job.
9122 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
9123 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
9125 DEBUG(3,("call_trans2setfilepathinfo: "
9126 "Cancelling print job (%s)\n",
9130 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
9136 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
9141 * Original code - this is an open file.
9143 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
9144 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9145 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
9147 reply_nterror(req
, map_nt_error_from_unix(errno
));
9153 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9156 if (total_params
< 7) {
9157 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9161 info_level
= SVAL(params
,0);
9162 if (req
->posix_pathnames
) {
9163 srvstr_get_path_posix(req
,
9172 srvstr_get_path(req
,
9181 if (!NT_STATUS_IS_OK(status
)) {
9182 reply_nterror(req
, status
);
9186 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
9187 info_level
== SMB_SET_FILE_UNIX_INFO2
||
9188 info_level
== SMB_FILE_RENAME_INFORMATION
||
9189 info_level
== SMB_POSIX_PATH_OPEN
||
9190 info_level
== SMB_POSIX_PATH_UNLINK
) {
9191 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
9194 status
= filename_convert(req
, conn
,
9200 if (!NT_STATUS_IS_OK(status
)) {
9201 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9202 reply_botherror(req
,
9203 NT_STATUS_PATH_NOT_COVERED
,
9204 ERRSRV
, ERRbadpath
);
9207 reply_nterror(req
, status
);
9211 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9213 * For CIFS UNIX extensions the target name may not exist.
9216 /* Always do lstat for UNIX calls. */
9217 SMB_VFS_LSTAT(conn
, smb_fname
);
9219 } else if (!VALID_STAT(smb_fname
->st
) &&
9220 SMB_VFS_STAT(conn
, smb_fname
)) {
9221 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9223 smb_fname_str_dbg(smb_fname
),
9225 reply_nterror(req
, map_nt_error_from_unix(errno
));
9230 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9231 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
9233 info_level
,total_data
));
9235 /* Realloc the parameter size */
9236 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9237 if (*pparams
== NULL
) {
9238 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9245 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
9251 if (!NT_STATUS_IS_OK(status
)) {
9252 if (open_was_deferred(req
->xconn
, req
->mid
)) {
9253 /* We have re-scheduled this call. */
9256 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
9257 /* We have re-scheduled this call. */
9260 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9261 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
9262 ERRSRV
, ERRbadpath
);
9265 if (info_level
== SMB_POSIX_PATH_OPEN
) {
9266 reply_openerror(req
, status
);
9271 * Invalid EA name needs to return 2 param bytes,
9272 * not a zero-length error packet.
9274 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
9275 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
9278 reply_nterror(req
, status
);
9283 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
9289 /****************************************************************************
9290 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9291 ****************************************************************************/
9293 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
9294 char **pparams
, int total_params
,
9295 char **ppdata
, int total_data
,
9296 unsigned int max_data_bytes
)
9298 struct smb_filename
*smb_dname
= NULL
;
9299 char *params
= *pparams
;
9300 char *pdata
= *ppdata
;
9301 char *directory
= NULL
;
9302 NTSTATUS status
= NT_STATUS_OK
;
9303 struct ea_list
*ea_list
= NULL
;
9304 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9305 TALLOC_CTX
*ctx
= talloc_tos();
9307 if (!CAN_WRITE(conn
)) {
9308 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9312 if (total_params
< 5) {
9313 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9317 if (req
->posix_pathnames
) {
9318 srvstr_get_path_posix(ctx
,
9327 srvstr_get_path(ctx
,
9336 if (!NT_STATUS_IS_OK(status
)) {
9337 reply_nterror(req
, status
);
9341 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
9343 status
= filename_convert(ctx
,
9351 if (!NT_STATUS_IS_OK(status
)) {
9352 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9353 reply_botherror(req
,
9354 NT_STATUS_PATH_NOT_COVERED
,
9355 ERRSRV
, ERRbadpath
);
9358 reply_nterror(req
, status
);
9363 * OS/2 workplace shell seems to send SET_EA requests of "null"
9364 * length (4 bytes containing IVAL 4).
9365 * They seem to have no effect. Bug #3212. JRA.
9368 if (total_data
&& (total_data
!= 4)) {
9369 /* Any data in this call is an EA list. */
9370 if (total_data
< 10) {
9371 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9375 if (IVAL(pdata
,0) > total_data
) {
9376 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9377 IVAL(pdata
,0), (unsigned int)total_data
));
9378 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9382 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
9385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9389 if (!lp_ea_support(SNUM(conn
))) {
9390 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
9394 /* If total_data == 4 Windows doesn't care what values
9395 * are placed in that field, it just ignores them.
9396 * The System i QNTC IBM SMB client puts bad values here,
9397 * so ignore them. */
9399 status
= create_directory(conn
, req
, smb_dname
);
9401 if (!NT_STATUS_IS_OK(status
)) {
9402 reply_nterror(req
, status
);
9406 /* Try and set any given EA. */
9408 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
9409 if (!NT_STATUS_IS_OK(status
)) {
9410 reply_nterror(req
, status
);
9415 /* Realloc the parameter and data sizes */
9416 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9417 if(*pparams
== NULL
) {
9418 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9425 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
9428 TALLOC_FREE(smb_dname
);
9432 /****************************************************************************
9433 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9434 We don't actually do this - we just send a null response.
9435 ****************************************************************************/
9437 static void call_trans2findnotifyfirst(connection_struct
*conn
,
9438 struct smb_request
*req
,
9439 char **pparams
, int total_params
,
9440 char **ppdata
, int total_data
,
9441 unsigned int max_data_bytes
)
9443 char *params
= *pparams
;
9444 uint16_t info_level
;
9446 if (total_params
< 6) {
9447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9451 info_level
= SVAL(params
,4);
9452 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
9454 switch (info_level
) {
9459 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
9463 /* Realloc the parameter and data sizes */
9464 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
9465 if (*pparams
== NULL
) {
9466 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9471 SSVAL(params
,0,fnf_handle
);
9472 SSVAL(params
,2,0); /* No changes */
9473 SSVAL(params
,4,0); /* No EA errors */
9480 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
9485 /****************************************************************************
9486 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9487 changes). Currently this does nothing.
9488 ****************************************************************************/
9490 static void call_trans2findnotifynext(connection_struct
*conn
,
9491 struct smb_request
*req
,
9492 char **pparams
, int total_params
,
9493 char **ppdata
, int total_data
,
9494 unsigned int max_data_bytes
)
9496 char *params
= *pparams
;
9498 DEBUG(3,("call_trans2findnotifynext\n"));
9500 /* Realloc the parameter and data sizes */
9501 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
9502 if (*pparams
== NULL
) {
9503 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9508 SSVAL(params
,0,0); /* No changes */
9509 SSVAL(params
,2,0); /* No EA errors */
9511 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
9516 /****************************************************************************
9517 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9518 ****************************************************************************/
9520 static void call_trans2getdfsreferral(connection_struct
*conn
,
9521 struct smb_request
*req
,
9522 char **pparams
, int total_params
,
9523 char **ppdata
, int total_data
,
9524 unsigned int max_data_bytes
)
9526 char *params
= *pparams
;
9527 char *pathname
= NULL
;
9529 int max_referral_level
;
9530 NTSTATUS status
= NT_STATUS_OK
;
9531 TALLOC_CTX
*ctx
= talloc_tos();
9533 DEBUG(10,("call_trans2getdfsreferral\n"));
9535 if (total_params
< 3) {
9536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9540 max_referral_level
= SVAL(params
,0);
9542 if(!lp_host_msdfs()) {
9543 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9547 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
9548 total_params
- 2, STR_TERMINATE
);
9550 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
9553 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
9554 ppdata
,&status
)) < 0) {
9555 reply_nterror(req
, status
);
9559 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
9560 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
9561 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
9566 #define LMCAT_SPL 0x53
9567 #define LMFUNC_GETJOBID 0x60
9569 /****************************************************************************
9570 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9571 ****************************************************************************/
9573 static void call_trans2ioctl(connection_struct
*conn
,
9574 struct smb_request
*req
,
9575 char **pparams
, int total_params
,
9576 char **ppdata
, int total_data
,
9577 unsigned int max_data_bytes
)
9579 char *pdata
= *ppdata
;
9580 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
9584 /* check for an invalid fid before proceeding */
9587 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9591 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9592 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9593 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
9594 if (*ppdata
== NULL
) {
9595 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9600 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9601 CAN ACCEPT THIS IN UNICODE. JRA. */
9604 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
9606 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
9607 lp_netbios_name(), 15,
9608 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
9609 if (!NT_STATUS_IS_OK(status
)) {
9610 reply_nterror(req
, status
);
9613 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
9614 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
9615 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
9616 if (!NT_STATUS_IS_OK(status
)) {
9617 reply_nterror(req
, status
);
9620 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
9625 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9626 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9629 /****************************************************************************
9630 Reply to a SMBfindclose (stop trans2 directory search).
9631 ****************************************************************************/
9633 void reply_findclose(struct smb_request
*req
)
9636 struct smbd_server_connection
*sconn
= req
->sconn
;
9638 START_PROFILE(SMBfindclose
);
9641 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9642 END_PROFILE(SMBfindclose
);
9646 dptr_num
= SVALS(req
->vwv
+0, 0);
9648 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
9650 dptr_close(sconn
, &dptr_num
);
9652 reply_outbuf(req
, 0, 0);
9654 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
9656 END_PROFILE(SMBfindclose
);
9660 /****************************************************************************
9661 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9662 ****************************************************************************/
9664 void reply_findnclose(struct smb_request
*req
)
9668 START_PROFILE(SMBfindnclose
);
9671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9672 END_PROFILE(SMBfindnclose
);
9676 dptr_num
= SVAL(req
->vwv
+0, 0);
9678 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
9680 /* We never give out valid handles for a
9681 findnotifyfirst - so any dptr_num is ok here.
9684 reply_outbuf(req
, 0, 0);
9686 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
9688 END_PROFILE(SMBfindnclose
);
9692 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
9693 struct trans_state
*state
)
9695 if (get_Protocol() >= PROTOCOL_NT1
) {
9696 req
->flags2
|= 0x40; /* IS_LONG_NAME */
9697 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
9700 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
9701 if (state
->call
!= TRANSACT2_QFSINFO
&&
9702 state
->call
!= TRANSACT2_SETFSINFO
) {
9703 DEBUG(0,("handle_trans2: encryption required "
9705 (unsigned int)state
->call
));
9706 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9711 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
9713 /* Now we must call the relevant TRANS2 function */
9714 switch(state
->call
) {
9715 case TRANSACT2_OPEN
:
9717 START_PROFILE(Trans2_open
);
9718 call_trans2open(conn
, req
,
9719 &state
->param
, state
->total_param
,
9720 &state
->data
, state
->total_data
,
9721 state
->max_data_return
);
9722 END_PROFILE(Trans2_open
);
9726 case TRANSACT2_FINDFIRST
:
9728 START_PROFILE(Trans2_findfirst
);
9729 call_trans2findfirst(conn
, req
,
9730 &state
->param
, state
->total_param
,
9731 &state
->data
, state
->total_data
,
9732 state
->max_data_return
);
9733 END_PROFILE(Trans2_findfirst
);
9737 case TRANSACT2_FINDNEXT
:
9739 START_PROFILE(Trans2_findnext
);
9740 call_trans2findnext(conn
, req
,
9741 &state
->param
, state
->total_param
,
9742 &state
->data
, state
->total_data
,
9743 state
->max_data_return
);
9744 END_PROFILE(Trans2_findnext
);
9748 case TRANSACT2_QFSINFO
:
9750 START_PROFILE(Trans2_qfsinfo
);
9751 call_trans2qfsinfo(conn
, req
,
9752 &state
->param
, state
->total_param
,
9753 &state
->data
, state
->total_data
,
9754 state
->max_data_return
);
9755 END_PROFILE(Trans2_qfsinfo
);
9759 case TRANSACT2_SETFSINFO
:
9761 START_PROFILE(Trans2_setfsinfo
);
9762 call_trans2setfsinfo(conn
, req
,
9763 &state
->param
, state
->total_param
,
9764 &state
->data
, state
->total_data
,
9765 state
->max_data_return
);
9766 END_PROFILE(Trans2_setfsinfo
);
9770 case TRANSACT2_QPATHINFO
:
9771 case TRANSACT2_QFILEINFO
:
9773 START_PROFILE(Trans2_qpathinfo
);
9774 call_trans2qfilepathinfo(conn
, req
, state
->call
,
9775 &state
->param
, state
->total_param
,
9776 &state
->data
, state
->total_data
,
9777 state
->max_data_return
);
9778 END_PROFILE(Trans2_qpathinfo
);
9782 case TRANSACT2_SETPATHINFO
:
9783 case TRANSACT2_SETFILEINFO
:
9785 START_PROFILE(Trans2_setpathinfo
);
9786 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9787 &state
->param
, state
->total_param
,
9788 &state
->data
, state
->total_data
,
9789 state
->max_data_return
);
9790 END_PROFILE(Trans2_setpathinfo
);
9794 case TRANSACT2_FINDNOTIFYFIRST
:
9796 START_PROFILE(Trans2_findnotifyfirst
);
9797 call_trans2findnotifyfirst(conn
, req
,
9798 &state
->param
, state
->total_param
,
9799 &state
->data
, state
->total_data
,
9800 state
->max_data_return
);
9801 END_PROFILE(Trans2_findnotifyfirst
);
9805 case TRANSACT2_FINDNOTIFYNEXT
:
9807 START_PROFILE(Trans2_findnotifynext
);
9808 call_trans2findnotifynext(conn
, req
,
9809 &state
->param
, state
->total_param
,
9810 &state
->data
, state
->total_data
,
9811 state
->max_data_return
);
9812 END_PROFILE(Trans2_findnotifynext
);
9816 case TRANSACT2_MKDIR
:
9818 START_PROFILE(Trans2_mkdir
);
9819 call_trans2mkdir(conn
, req
,
9820 &state
->param
, state
->total_param
,
9821 &state
->data
, state
->total_data
,
9822 state
->max_data_return
);
9823 END_PROFILE(Trans2_mkdir
);
9827 case TRANSACT2_GET_DFS_REFERRAL
:
9829 START_PROFILE(Trans2_get_dfs_referral
);
9830 call_trans2getdfsreferral(conn
, req
,
9831 &state
->param
, state
->total_param
,
9832 &state
->data
, state
->total_data
,
9833 state
->max_data_return
);
9834 END_PROFILE(Trans2_get_dfs_referral
);
9838 case TRANSACT2_IOCTL
:
9840 START_PROFILE(Trans2_ioctl
);
9841 call_trans2ioctl(conn
, req
,
9842 &state
->param
, state
->total_param
,
9843 &state
->data
, state
->total_data
,
9844 state
->max_data_return
);
9845 END_PROFILE(Trans2_ioctl
);
9850 /* Error in request */
9851 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9852 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9856 /****************************************************************************
9857 Reply to a SMBtrans2.
9858 ****************************************************************************/
9860 void reply_trans2(struct smb_request
*req
)
9862 connection_struct
*conn
= req
->conn
;
9867 unsigned int tran_call
;
9868 struct trans_state
*state
;
9871 START_PROFILE(SMBtrans2
);
9873 if (req
->wct
< 14) {
9874 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9875 END_PROFILE(SMBtrans2
);
9879 dsoff
= SVAL(req
->vwv
+12, 0);
9880 dscnt
= SVAL(req
->vwv
+11, 0);
9881 psoff
= SVAL(req
->vwv
+10, 0);
9882 pscnt
= SVAL(req
->vwv
+9, 0);
9883 tran_call
= SVAL(req
->vwv
+14, 0);
9885 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9886 if (!NT_STATUS_IS_OK(result
)) {
9887 DEBUG(2, ("Got invalid trans2 request: %s\n",
9888 nt_errstr(result
)));
9889 reply_nterror(req
, result
);
9890 END_PROFILE(SMBtrans2
);
9895 switch (tran_call
) {
9896 /* List the allowed trans2 calls on IPC$ */
9897 case TRANSACT2_OPEN
:
9898 case TRANSACT2_GET_DFS_REFERRAL
:
9899 case TRANSACT2_QFILEINFO
:
9900 case TRANSACT2_QFSINFO
:
9901 case TRANSACT2_SETFSINFO
:
9904 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9905 END_PROFILE(SMBtrans2
);
9910 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9911 DEBUG(0, ("talloc failed\n"));
9912 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9913 END_PROFILE(SMBtrans2
);
9917 state
->cmd
= SMBtrans2
;
9919 state
->mid
= req
->mid
;
9920 state
->vuid
= req
->vuid
;
9921 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9922 state
->setup
= NULL
;
9923 state
->total_param
= SVAL(req
->vwv
+0, 0);
9924 state
->param
= NULL
;
9925 state
->total_data
= SVAL(req
->vwv
+1, 0);
9927 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9928 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9929 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9930 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9931 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9933 state
->call
= tran_call
;
9935 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9936 is so as a sanity check */
9937 if (state
->setup_count
!= 1) {
9939 * Need to have rc=0 for ioctl to get job id for OS/2.
9940 * Network printing will fail if function is not successful.
9941 * Similar function in reply.c will be used if protocol
9942 * is LANMAN1.0 instead of LM1.2X002.
9943 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9944 * outbuf doesn't have to be set(only job id is used).
9946 if ( (state
->setup_count
== 4)
9947 && (tran_call
== TRANSACT2_IOCTL
)
9948 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9949 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9950 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9952 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9953 DEBUG(2,("Transaction is %d\n",tran_call
));
9955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9956 END_PROFILE(SMBtrans2
);
9961 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9964 if (state
->total_data
) {
9966 if (trans_oob(state
->total_data
, 0, dscnt
)
9967 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9971 /* Can't use talloc here, the core routines do realloc on the
9972 * params and data. */
9973 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9974 if (state
->data
== NULL
) {
9975 DEBUG(0,("reply_trans2: data malloc fail for %u "
9976 "bytes !\n", (unsigned int)state
->total_data
));
9978 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9979 END_PROFILE(SMBtrans2
);
9983 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9986 if (state
->total_param
) {
9988 if (trans_oob(state
->total_param
, 0, pscnt
)
9989 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9993 /* Can't use talloc here, the core routines do realloc on the
9994 * params and data. */
9995 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9996 if (state
->param
== NULL
) {
9997 DEBUG(0,("reply_trans: param malloc fail for %u "
9998 "bytes !\n", (unsigned int)state
->total_param
));
9999 SAFE_FREE(state
->data
);
10000 TALLOC_FREE(state
);
10001 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10002 END_PROFILE(SMBtrans2
);
10006 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
10009 state
->received_data
= dscnt
;
10010 state
->received_param
= pscnt
;
10012 if ((state
->received_param
== state
->total_param
) &&
10013 (state
->received_data
== state
->total_data
)) {
10015 handle_trans2(conn
, req
, state
);
10017 SAFE_FREE(state
->data
);
10018 SAFE_FREE(state
->param
);
10019 TALLOC_FREE(state
);
10020 END_PROFILE(SMBtrans2
);
10024 DLIST_ADD(conn
->pending_trans
, state
);
10026 /* We need to send an interim response then receive the rest
10027 of the parameter/data bytes */
10028 reply_outbuf(req
, 0, 0);
10029 show_msg((char *)req
->outbuf
);
10030 END_PROFILE(SMBtrans2
);
10035 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10036 SAFE_FREE(state
->data
);
10037 SAFE_FREE(state
->param
);
10038 TALLOC_FREE(state
);
10039 END_PROFILE(SMBtrans2
);
10040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10044 /****************************************************************************
10045 Reply to a SMBtranss2
10046 ****************************************************************************/
10048 void reply_transs2(struct smb_request
*req
)
10050 connection_struct
*conn
= req
->conn
;
10051 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
10052 struct trans_state
*state
;
10054 START_PROFILE(SMBtranss2
);
10056 show_msg((const char *)req
->inbuf
);
10058 /* Windows clients expect all replies to
10059 a transact secondary (SMBtranss2 0x33)
10060 to have a command code of transact
10061 (SMBtrans2 0x32). See bug #8989
10062 and also [MS-CIFS] section 2.2.4.47.2
10065 req
->cmd
= SMBtrans2
;
10067 if (req
->wct
< 8) {
10068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10069 END_PROFILE(SMBtranss2
);
10073 for (state
= conn
->pending_trans
; state
!= NULL
;
10074 state
= state
->next
) {
10075 if (state
->mid
== req
->mid
) {
10080 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
10081 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10082 END_PROFILE(SMBtranss2
);
10086 /* Revise state->total_param and state->total_data in case they have
10087 changed downwards */
10089 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
10090 state
->total_param
= SVAL(req
->vwv
+0, 0);
10091 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
10092 state
->total_data
= SVAL(req
->vwv
+1, 0);
10094 pcnt
= SVAL(req
->vwv
+2, 0);
10095 poff
= SVAL(req
->vwv
+3, 0);
10096 pdisp
= SVAL(req
->vwv
+4, 0);
10098 dcnt
= SVAL(req
->vwv
+5, 0);
10099 doff
= SVAL(req
->vwv
+6, 0);
10100 ddisp
= SVAL(req
->vwv
+7, 0);
10102 state
->received_param
+= pcnt
;
10103 state
->received_data
+= dcnt
;
10105 if ((state
->received_data
> state
->total_data
) ||
10106 (state
->received_param
> state
->total_param
))
10110 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
10111 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
10114 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
10118 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
10119 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
10122 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
10125 if ((state
->received_param
< state
->total_param
) ||
10126 (state
->received_data
< state
->total_data
)) {
10127 END_PROFILE(SMBtranss2
);
10131 handle_trans2(conn
, req
, state
);
10133 DLIST_REMOVE(conn
->pending_trans
, state
);
10134 SAFE_FREE(state
->data
);
10135 SAFE_FREE(state
->param
);
10136 TALLOC_FREE(state
);
10138 END_PROFILE(SMBtranss2
);
10143 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10144 DLIST_REMOVE(conn
->pending_trans
, state
);
10145 SAFE_FREE(state
->data
);
10146 SAFE_FREE(state
->param
);
10147 TALLOC_FREE(state
);
10148 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10149 END_PROFILE(SMBtranss2
);