2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct
*conn
,
54 const SMB_STRUCT_STAT
*psbuf
);
56 static char *store_file_unix_basic_info2(connection_struct
*conn
,
59 const SMB_STRUCT_STAT
*psbuf
);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS
refuse_symlink(connection_struct
*conn
,
66 const files_struct
*fsp
,
67 const struct smb_filename
*smb_fname
)
70 const SMB_STRUCT_STAT
*pst
= NULL
;
73 pst
= &fsp
->fsp_name
->st
;
78 if (!VALID_STAT(*pst
)) {
79 int ret
= vfs_stat_smb_basename(conn
,
82 if (ret
== -1 && errno
!= ENOENT
) {
83 return map_nt_error_from_unix(errno
);
84 } else if (ret
== -1) {
85 /* it's not a symlink.. */
91 if (S_ISLNK(pst
->st_ex_mode
)) {
92 return NT_STATUS_ACCESS_DENIED
;
97 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
100 if (!fsp
->fsp_flags
.is_fsa
) {
101 return smbd_check_access_rights_fsp(fsp
,
105 if (!(fsp
->access_mask
& access_mask
)) {
106 return NT_STATUS_ACCESS_DENIED
;
111 #if defined(HAVE_POSIX_ACLS)
112 /****************************************************************************
113 Utility function to open a fsp for a POSIX handle operation.
114 ****************************************************************************/
116 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
117 struct smb_request
*req
,
118 struct smb_filename
*smb_fname
,
119 uint32_t access_mask
,
120 files_struct
**ret_fsp
)
123 uint32_t create_disposition
= FILE_OPEN
;
124 uint32_t share_access
= FILE_SHARE_READ
|
127 struct smb2_create_blobs
*posx
= NULL
;
130 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
131 * but set reasonable defaults.
133 uint32_t file_attributes
= 0664;
134 uint32_t oplock
= NO_OPLOCK
;
135 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
137 /* File or directory must exist. */
138 if (!VALID_STAT(smb_fname
->st
)) {
139 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
141 /* Cannot be a symlink. */
142 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
143 return NT_STATUS_ACCESS_DENIED
;
145 /* Set options correctly for directory open. */
146 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
148 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
149 * directories, but set reasonable defaults.
151 file_attributes
= 0775;
152 create_options
= FILE_DIRECTORY_FILE
;
155 status
= make_smb2_posix_create_ctx(
156 talloc_tos(), &posx
, file_attributes
);
157 if (!NT_STATUS_IS_OK(status
)) {
158 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
163 status
= SMB_VFS_CREATE_FILE(
166 smb_fname
, /* fname */
167 access_mask
, /* access_mask */
168 share_access
, /* share_access */
169 create_disposition
,/* create_disposition*/
170 create_options
, /* create_options */
171 file_attributes
,/* file_attributes */
172 oplock
, /* oplock_request */
174 0, /* allocation_size */
175 0, /* private_flags */
178 ret_fsp
, /* result */
180 posx
, /* in_context */
181 NULL
); /* out_context */
189 /********************************************************************
190 Roundup a value to the nearest allocation roundup size boundary.
191 Only do this for Windows clients.
192 ********************************************************************/
194 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
196 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
198 /* Only roundup for Windows clients. */
199 enum remote_arch_types ra_type
= get_remote_arch();
200 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
201 val
= SMB_ROUNDUP(val
,rval
);
206 /****************************************************************************
207 Utility functions for dealing with extended attributes.
208 ****************************************************************************/
210 /****************************************************************************
211 Refuse to allow clients to overwrite our private xattrs.
212 ****************************************************************************/
214 bool samba_private_attr_name(const char *unix_ea_name
)
216 static const char * const prohibited_ea_names
[] = {
217 SAMBA_POSIX_INHERITANCE_EA_NAME
,
218 SAMBA_XATTR_DOS_ATTRIB
,
226 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
227 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
230 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
231 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
237 /****************************************************************************
238 Get one EA value. Fill in a struct ea_struct.
239 ****************************************************************************/
241 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
,
242 connection_struct
*conn
,
244 const struct smb_filename
*smb_fname
,
246 struct ea_struct
*pea
)
248 /* Get the value of this xattr. Max size is 64k. */
249 size_t attr_size
= 256;
255 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
257 return NT_STATUS_NO_MEMORY
;
260 if (fsp
&& !fsp
->fsp_flags
.is_pathref
&& fsp_get_io_fd(fsp
) != -1) {
261 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
263 sizeret
= SMB_VFS_GETXATTR(conn
, smb_fname
,
264 ea_name
, val
, attr_size
);
267 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
273 return map_nt_error_from_unix(errno
);
276 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
277 dump_data(10, (uint8_t *)val
, sizeret
);
280 if (strnequal(ea_name
, "user.", 5)) {
281 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
283 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
285 if (pea
->name
== NULL
) {
287 return NT_STATUS_NO_MEMORY
;
289 pea
->value
.data
= (unsigned char *)val
;
290 pea
->value
.length
= (size_t)sizeret
;
294 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
,
300 /* Get a list of all xattrs. Max namesize is 64k. */
301 size_t ea_namelist_size
= 1024;
302 char *ea_namelist
= smallbuf
;
303 char *to_free
= NULL
;
308 ssize_t sizeret
= -1;
318 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
319 * symlink. This is ok, handle it here, by just return no EA's
325 /* should be the case that fsp != NULL */
326 SMB_ASSERT(fsp
!= NULL
);
328 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
331 if ((sizeret
== -1) && (errno
== ERANGE
)) {
332 ea_namelist_size
= 65536;
333 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
334 if (ea_namelist
== NULL
) {
335 return NT_STATUS_NO_MEMORY
;
337 to_free
= ea_namelist
;
339 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
344 status
= map_nt_error_from_unix(errno
);
345 TALLOC_FREE(to_free
);
349 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
352 TALLOC_FREE(to_free
);
357 * Ensure the result is 0-terminated
360 if (ea_namelist
[sizeret
-1] != '\0') {
361 TALLOC_FREE(to_free
);
362 return NT_STATUS_INTERNAL_ERROR
;
370 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
374 *pnum_names
= num_names
;
376 if (pnames
== NULL
) {
377 TALLOC_FREE(to_free
);
381 names
= talloc_array(mem_ctx
, char *, num_names
);
383 DEBUG(0, ("talloc failed\n"));
384 TALLOC_FREE(to_free
);
385 return NT_STATUS_NO_MEMORY
;
388 if (ea_namelist
== smallbuf
) {
389 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
390 if (ea_namelist
== NULL
) {
392 return NT_STATUS_NO_MEMORY
;
395 talloc_steal(names
, ea_namelist
);
397 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
399 if (ea_namelist
== NULL
) {
401 return NT_STATUS_NO_MEMORY
;
407 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
408 names
[num_names
++] = p
;
416 /****************************************************************************
417 Return a linked list of the total EA's. Plus the total size
418 ****************************************************************************/
420 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
422 size_t *pea_total_len
,
423 struct ea_list
**ea_list
)
425 /* Get a list of all xattrs. Max namesize is 64k. */
428 struct ea_list
*ea_list_head
= NULL
;
429 bool posix_pathnames
= false;
440 if (!lp_ea_support(SNUM(fsp
->conn
))) {
444 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
445 return NT_STATUS_INVALID_PARAMETER
;
448 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
450 status
= get_ea_names_from_file(talloc_tos(),
455 if (!NT_STATUS_IS_OK(status
)) {
459 if (num_names
== 0) {
463 for (i
=0; i
<num_names
; i
++) {
464 struct ea_list
*listp
;
467 if (strnequal(names
[i
], "system.", 7)
468 || samba_private_attr_name(names
[i
]))
472 * Filter out any underlying POSIX EA names
473 * that a Windows client can't handle.
475 if (!posix_pathnames
&&
476 is_invalid_windows_ea_name(names
[i
])) {
480 listp
= talloc(mem_ctx
, struct ea_list
);
482 return NT_STATUS_NO_MEMORY
;
485 status
= get_ea_value(listp
,
492 if (!NT_STATUS_IS_OK(status
)) {
497 if (listp
->ea
.value
.length
== 0) {
499 * We can never return a zero length EA.
500 * Windows reports the EA's as corrupted.
506 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
509 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
511 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
512 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
513 (unsigned int)listp
->ea
.value
.length
));
515 DLIST_ADD_END(ea_list_head
, listp
);
519 /* Add on 4 for total length. */
520 if (*pea_total_len
) {
524 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
525 (unsigned int)*pea_total_len
));
527 *ea_list
= ea_list_head
;
531 /****************************************************************************
532 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
534 ****************************************************************************/
536 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
537 connection_struct
*conn
, struct ea_list
*ea_list
)
539 unsigned int ret_data_size
= 4;
542 SMB_ASSERT(total_data_size
>= 4);
544 if (!lp_ea_support(SNUM(conn
))) {
549 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
552 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
553 dos_namelen
= strlen(dos_ea_name
);
554 if (dos_namelen
> 255 || dos_namelen
== 0) {
557 if (ea_list
->ea
.value
.length
> 65535) {
560 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
564 /* We know we have room. */
565 SCVAL(p
,0,ea_list
->ea
.flags
);
566 SCVAL(p
,1,dos_namelen
);
567 SSVAL(p
,2,ea_list
->ea
.value
.length
);
568 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
569 if (ea_list
->ea
.value
.length
> 0) {
570 memcpy(p
+ 4 + dos_namelen
+ 1,
571 ea_list
->ea
.value
.data
,
572 ea_list
->ea
.value
.length
);
575 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
576 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
579 ret_data_size
= PTR_DIFF(p
, pdata
);
580 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
581 SIVAL(pdata
,0,ret_data_size
);
582 return ret_data_size
;
585 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
587 unsigned int total_data_size
,
588 unsigned int *ret_data_size
,
589 connection_struct
*conn
,
590 struct ea_list
*ea_list
)
592 uint8_t *p
= (uint8_t *)pdata
;
593 uint8_t *last_start
= NULL
;
594 bool do_store_data
= (pdata
!= NULL
);
598 if (!lp_ea_support(SNUM(conn
))) {
599 return NT_STATUS_NO_EAS_ON_FILE
;
602 for (; ea_list
; ea_list
= ea_list
->next
) {
608 if (last_start
!= NULL
&& do_store_data
) {
609 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
613 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
614 dos_namelen
= strlen(dos_ea_name
);
615 if (dos_namelen
> 255 || dos_namelen
== 0) {
616 return NT_STATUS_INTERNAL_ERROR
;
618 if (ea_list
->ea
.value
.length
> 65535) {
619 return NT_STATUS_INTERNAL_ERROR
;
622 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
625 pad
= (4 - (this_size
% 4)) % 4;
630 if (this_size
> total_data_size
) {
631 return NT_STATUS_INFO_LENGTH_MISMATCH
;
634 /* We know we have room. */
635 SIVAL(p
, 0x00, 0); /* next offset */
636 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
637 SCVAL(p
, 0x05, dos_namelen
);
638 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
639 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
640 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
642 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
646 total_data_size
-= this_size
;
652 *ret_data_size
= PTR_DIFF(p
, pdata
);
653 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
657 static unsigned int estimate_ea_size(files_struct
*fsp
)
659 size_t total_ea_len
= 0;
661 struct ea_list
*ea_list
= NULL
;
669 mem_ctx
= talloc_stackframe();
670 if (!lp_ea_support(SNUM(fsp
->conn
))) {
674 /* If this is a stream fsp, then we need to instead find the
675 * estimated ea len from the main file, not the stream
676 * (streams cannot have EAs), but the estimate isn't just 0 in
678 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
681 (void)get_ea_list_from_fsp(mem_ctx
,
686 if(fsp
->conn
->sconn
->using_smb2
) {
687 unsigned int ret_data_size
;
689 * We're going to be using fill_ea_chained_buffer() to
690 * marshall EA's - this size is significantly larger
691 * than the SMB1 buffer. Re-calculate the size without
694 status
= fill_ea_chained_buffer(mem_ctx
,
700 if (!NT_STATUS_IS_OK(status
)) {
703 total_ea_len
= ret_data_size
;
705 TALLOC_FREE(mem_ctx
);
709 /****************************************************************************
710 Ensure the EA name is case insensitive by matching any existing EA name.
711 ****************************************************************************/
713 static void canonicalize_ea_name(files_struct
*fsp
,
714 fstring unix_ea_name
)
717 TALLOC_CTX
*mem_ctx
= talloc_tos();
718 struct ea_list
*ea_list
;
719 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
723 if (!NT_STATUS_IS_OK(status
)) {
727 for (; ea_list
; ea_list
= ea_list
->next
) {
728 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
729 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
730 &unix_ea_name
[5], ea_list
->ea
.name
));
731 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
737 /****************************************************************************
738 Set or delete an extended attribute.
739 ****************************************************************************/
741 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
742 struct ea_list
*ea_list
)
745 bool posix_pathnames
= false;
747 if (!lp_ea_support(SNUM(conn
))) {
748 return NT_STATUS_EAS_NOT_SUPPORTED
;
751 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
753 status
= refuse_symlink(conn
, fsp
, fsp
->fsp_name
);
754 if (!NT_STATUS_IS_OK(status
)) {
758 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
759 if (!NT_STATUS_IS_OK(status
)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(fsp
->fsp_name
)) {
765 return NT_STATUS_INVALID_PARAMETER
;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
774 return STATUS_INVALID_EA_NAME
;
777 for (;ea_list
; ea_list
= ea_list
->next
) {
779 fstring unix_ea_name
;
781 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
784 canonicalize_ea_name(fsp
, unix_ea_name
);
786 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
788 if (samba_private_attr_name(unix_ea_name
)) {
789 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
790 return NT_STATUS_ACCESS_DENIED
;
793 if (ea_list
->ea
.value
.length
== 0) {
794 /* Remove the attribute. */
795 if (!fsp
->fsp_flags
.is_pathref
&&
796 fsp_get_io_fd(fsp
) != -1)
798 DEBUG(10,("set_ea: deleting ea name %s on "
799 "file %s by file descriptor.\n",
800 unix_ea_name
, fsp_str_dbg(fsp
)));
801 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
803 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
804 unix_ea_name
, fsp
->fsp_name
->base_name
));
805 ret
= SMB_VFS_REMOVEXATTR(conn
,
810 /* Removing a non existent attribute always succeeds. */
811 if (ret
== -1 && errno
== ENOATTR
) {
812 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
818 if (!fsp
->fsp_flags
.is_pathref
&&
819 fsp_get_io_fd(fsp
) != -1)
821 DEBUG(10,("set_ea: setting ea name %s on file "
822 "%s by file descriptor.\n",
823 unix_ea_name
, fsp_str_dbg(fsp
)));
824 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
825 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
827 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
828 unix_ea_name
, fsp
->fsp_name
->base_name
));
829 ret
= SMB_VFS_SETXATTR(conn
,
832 ea_list
->ea
.value
.data
,
833 ea_list
->ea
.value
.length
,
840 if (errno
== ENOTSUP
) {
841 return NT_STATUS_EAS_NOT_SUPPORTED
;
844 return map_nt_error_from_unix(errno
);
850 /****************************************************************************
851 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
852 ****************************************************************************/
854 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
856 struct ea_list
*ea_list_head
= NULL
;
857 size_t converted_size
, offset
= 0;
859 while (offset
+ 2 < data_size
) {
860 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
861 unsigned int namelen
= CVAL(pdata
,offset
);
863 offset
++; /* Go past the namelen byte. */
865 /* integer wrap paranioa. */
866 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
867 (offset
> data_size
) || (namelen
> data_size
) ||
868 (offset
+ namelen
>= data_size
)) {
871 /* Ensure the name is null terminated. */
872 if (pdata
[offset
+ namelen
] != '\0') {
875 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
877 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
878 "failed: %s", strerror(errno
)));
884 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
885 DLIST_ADD_END(ea_list_head
, eal
);
886 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
892 /****************************************************************************
893 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
894 ****************************************************************************/
896 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
898 struct ea_list
*ea_list_head
= NULL
;
900 size_t bytes_used
= 0;
902 while (offset
< data_size
) {
903 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
909 DLIST_ADD_END(ea_list_head
, eal
);
910 offset
+= bytes_used
;
916 /****************************************************************************
917 Count the total EA size needed.
918 ****************************************************************************/
920 static size_t ea_list_size(struct ea_list
*ealist
)
923 struct ea_list
*listp
;
926 for (listp
= ealist
; listp
; listp
= listp
->next
) {
927 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
928 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
930 /* Add on 4 for total length. */
938 /****************************************************************************
939 Return a union of EA's from a file list and a list of names.
940 The TALLOC context for the two lists *MUST* be identical as we steal
941 memory from one list to add to another. JRA.
942 ****************************************************************************/
944 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
946 struct ea_list
*nlistp
, *flistp
;
948 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
949 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
950 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
956 /* Copy the data from this entry. */
957 nlistp
->ea
.flags
= flistp
->ea
.flags
;
958 nlistp
->ea
.value
= flistp
->ea
.value
;
961 nlistp
->ea
.flags
= 0;
962 ZERO_STRUCT(nlistp
->ea
.value
);
966 *total_ea_len
= ea_list_size(name_list
);
970 /****************************************************************************
971 Send the required number of replies back.
972 We assume all fields other than the data fields are
973 set correctly for the type of call.
974 HACK ! Always assumes smb_setup field is zero.
975 ****************************************************************************/
977 void send_trans2_replies(connection_struct
*conn
,
978 struct smb_request
*req
,
986 /* As we are using a protocol > LANMAN1 then the max_send
987 variable must have been set in the sessetupX call.
988 This takes precedence over the max_xmit field in the
989 global struct. These different max_xmit variables should
990 be merged as this is now too confusing */
992 int data_to_send
= datasize
;
993 int params_to_send
= paramsize
;
995 const char *pp
= params
;
996 const char *pd
= pdata
;
997 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
998 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
999 int data_alignment_offset
= 0;
1000 bool overflow
= False
;
1001 struct smbXsrv_connection
*xconn
= req
->xconn
;
1002 int max_send
= xconn
->smb1
.sessions
.max_send
;
1004 /* Modify the data_to_send and datasize and set the error if
1005 we're trying to send more than max_data_bytes. We still send
1006 the part of the packet(s) that fit. Strange, but needed
1009 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
1010 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1011 max_data_bytes
, datasize
));
1012 datasize
= data_to_send
= max_data_bytes
;
1016 /* If there genuinely are no parameters or data to send just send the empty packet */
1018 if(params_to_send
== 0 && data_to_send
== 0) {
1019 reply_outbuf(req
, 10, 0);
1020 if (NT_STATUS_V(status
)) {
1023 ntstatus_to_dos(status
, &eclass
, &ecode
);
1024 error_packet_set((char *)req
->outbuf
,
1025 eclass
, ecode
, status
,
1028 show_msg((char *)req
->outbuf
);
1029 if (!srv_send_smb(xconn
,
1030 (char *)req
->outbuf
,
1031 true, req
->seqnum
+1,
1032 IS_CONN_ENCRYPTED(conn
),
1034 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1036 TALLOC_FREE(req
->outbuf
);
1040 /* When sending params and data ensure that both are nicely aligned */
1041 /* Only do this alignment when there is also data to send - else
1042 can cause NT redirector problems. */
1044 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
1045 data_alignment_offset
= 4 - (params_to_send
% 4);
1047 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1048 /* The alignment_offset is to align the param bytes on an even byte
1049 boundary. NT 4.0 Beta needs this to work correctly. */
1051 useable_space
= max_send
- (smb_size
1054 + data_alignment_offset
);
1056 if (useable_space
< 0) {
1057 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1058 "= %d!!!", useable_space
));
1059 exit_server_cleanly("send_trans2_replies: Not enough space");
1062 while (params_to_send
|| data_to_send
) {
1063 /* Calculate whether we will totally or partially fill this packet */
1065 total_sent_thistime
= params_to_send
+ data_to_send
;
1067 /* We can never send more than useable_space */
1069 * Note that 'useable_space' does not include the alignment offsets,
1070 * but we must include the alignment offsets in the calculation of
1071 * the length of the data we send over the wire, as the alignment offsets
1072 * are sent here. Fix from Marc_Jacobsen@hp.com.
1075 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
1077 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
1078 + data_alignment_offset
);
1080 /* Set total params and data to be sent */
1081 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1082 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1084 /* Calculate how many parameters and data we can fit into
1085 * this packet. Parameters get precedence
1088 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1089 data_sent_thistime
= useable_space
- params_sent_thistime
;
1090 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1092 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1094 /* smb_proff is the offset from the start of the SMB header to the
1095 parameter bytes, however the first 4 bytes of outbuf are
1096 the Netbios over TCP header. Thus use smb_base() to subtract
1097 them from the calculation */
1099 SSVAL(req
->outbuf
,smb_proff
,
1100 ((smb_buf(req
->outbuf
)+alignment_offset
)
1101 - smb_base(req
->outbuf
)));
1103 if(params_sent_thistime
== 0)
1104 SSVAL(req
->outbuf
,smb_prdisp
,0);
1106 /* Absolute displacement of param bytes sent in this packet */
1107 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1109 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1110 if(data_sent_thistime
== 0) {
1111 SSVAL(req
->outbuf
,smb_droff
,0);
1112 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1114 /* The offset of the data bytes is the offset of the
1115 parameter bytes plus the number of parameters being sent this time */
1116 SSVAL(req
->outbuf
, smb_droff
,
1117 ((smb_buf(req
->outbuf
)+alignment_offset
)
1118 - smb_base(req
->outbuf
))
1119 + params_sent_thistime
+ data_alignment_offset
);
1120 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1123 /* Initialize the padding for alignment */
1125 if (alignment_offset
!= 0) {
1126 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1129 /* Copy the param bytes into the packet */
1131 if(params_sent_thistime
) {
1132 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1133 params_sent_thistime
);
1136 /* Copy in the data bytes */
1137 if(data_sent_thistime
) {
1138 if (data_alignment_offset
!= 0) {
1139 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1140 params_sent_thistime
), 0,
1141 data_alignment_offset
);
1143 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1144 +params_sent_thistime
+data_alignment_offset
,
1145 pd
,data_sent_thistime
);
1148 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1149 params_sent_thistime
, data_sent_thistime
, useable_space
));
1150 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1151 params_to_send
, data_to_send
, paramsize
, datasize
));
1154 error_packet_set((char *)req
->outbuf
,
1155 ERRDOS
,ERRbufferoverflow
,
1156 STATUS_BUFFER_OVERFLOW
,
1158 } else if (NT_STATUS_V(status
)) {
1161 ntstatus_to_dos(status
, &eclass
, &ecode
);
1162 error_packet_set((char *)req
->outbuf
,
1163 eclass
, ecode
, status
,
1167 /* Send the packet */
1168 show_msg((char *)req
->outbuf
);
1169 if (!srv_send_smb(xconn
,
1170 (char *)req
->outbuf
,
1171 true, req
->seqnum
+1,
1172 IS_CONN_ENCRYPTED(conn
),
1174 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1176 TALLOC_FREE(req
->outbuf
);
1178 pp
+= params_sent_thistime
;
1179 pd
+= data_sent_thistime
;
1181 params_to_send
-= params_sent_thistime
;
1182 data_to_send
-= data_sent_thistime
;
1185 if(params_to_send
< 0 || data_to_send
< 0) {
1186 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1187 params_to_send
, data_to_send
));
1195 /****************************************************************************
1196 Reply to a TRANSACT2_OPEN.
1197 ****************************************************************************/
1199 static void call_trans2open(connection_struct
*conn
,
1200 struct smb_request
*req
,
1201 char **pparams
, int total_params
,
1202 char **ppdata
, int total_data
,
1203 unsigned int max_data_bytes
)
1205 struct smb_filename
*smb_fname
= NULL
;
1206 char *params
= *pparams
;
1207 char *pdata
= *ppdata
;
1210 bool oplock_request
;
1212 bool return_additional_info
;
1221 int fattr
=0,mtime
=0;
1222 SMB_INO_T inode
= 0;
1225 struct ea_list
*ea_list
= NULL
;
1228 uint32_t access_mask
;
1229 uint32_t share_mode
;
1230 uint32_t create_disposition
;
1231 uint32_t create_options
= 0;
1232 uint32_t private_flags
= 0;
1233 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1234 TALLOC_CTX
*ctx
= talloc_tos();
1237 * Ensure we have enough parameters to perform the operation.
1240 if (total_params
< 29) {
1241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1245 flags
= SVAL(params
, 0);
1246 deny_mode
= SVAL(params
, 2);
1247 open_attr
= SVAL(params
,6);
1248 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1249 if (oplock_request
) {
1250 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1254 return_additional_info
= BITSETW(params
,0);
1255 open_sattr
= SVAL(params
, 4);
1256 open_time
= make_unix_date3(params
+8);
1258 open_ofun
= SVAL(params
,12);
1259 open_size
= IVAL(params
,14);
1260 pname
= ¶ms
[28];
1263 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1267 if (req
->posix_pathnames
) {
1268 srvstr_get_path_posix(ctx
,
1277 srvstr_get_path(ctx
,
1286 if (!NT_STATUS_IS_OK(status
)) {
1287 reply_nterror(req
, status
);
1291 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1292 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1293 (unsigned int)open_ofun
, open_size
));
1295 status
= filename_convert(ctx
,
1301 if (!NT_STATUS_IS_OK(status
)) {
1302 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1303 reply_botherror(req
,
1304 NT_STATUS_PATH_NOT_COVERED
,
1305 ERRSRV
, ERRbadpath
);
1308 reply_nterror(req
, status
);
1312 if (open_ofun
== 0) {
1313 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1317 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1319 &access_mask
, &share_mode
,
1320 &create_disposition
,
1323 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1327 /* Any data in this call is an EA list. */
1328 if (total_data
&& (total_data
!= 4)) {
1329 if (total_data
< 10) {
1330 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1334 if (IVAL(pdata
,0) > total_data
) {
1335 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1336 IVAL(pdata
,0), (unsigned int)total_data
));
1337 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1341 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1344 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1348 if (!lp_ea_support(SNUM(conn
))) {
1349 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1353 if (!req
->posix_pathnames
&&
1354 ea_list_has_invalid_name(ea_list
)) {
1356 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1357 if(*pparams
== NULL
) {
1358 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1362 memset(params
, '\0', param_len
);
1363 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1364 params
, param_len
, NULL
, 0, max_data_bytes
);
1369 status
= SMB_VFS_CREATE_FILE(
1372 smb_fname
, /* fname */
1373 access_mask
, /* access_mask */
1374 share_mode
, /* share_access */
1375 create_disposition
, /* create_disposition*/
1376 create_options
, /* create_options */
1377 open_attr
, /* file_attributes */
1378 oplock_request
, /* oplock_request */
1380 open_size
, /* allocation_size */
1383 ea_list
, /* ea_list */
1385 &smb_action
, /* psbuf */
1386 NULL
, NULL
); /* create context */
1388 if (!NT_STATUS_IS_OK(status
)) {
1389 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1390 /* We have re-scheduled this call. */
1394 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1395 reply_openerror(req
, status
);
1399 fsp
= fcb_or_dos_open(
1406 bool ok
= defer_smb1_sharing_violation(req
);
1410 reply_openerror(req
, status
);
1414 smb_action
= FILE_WAS_OPENED
;
1417 size
= get_file_size_stat(&smb_fname
->st
);
1418 fattr
= fdos_mode(fsp
);
1419 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1420 inode
= smb_fname
->st
.st_ex_ino
;
1421 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1422 close_file(req
, fsp
, ERROR_CLOSE
);
1423 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1427 /* Realloc the size of parameters and data we will return */
1428 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1429 if(*pparams
== NULL
) {
1430 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1435 SSVAL(params
,0,fsp
->fnum
);
1436 SSVAL(params
,2,fattr
);
1437 srv_put_dos_date2(params
,4, mtime
);
1438 SIVAL(params
,8, (uint32_t)size
);
1439 SSVAL(params
,12,deny_mode
);
1440 SSVAL(params
,14,0); /* open_type - file or directory. */
1441 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1443 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1444 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1447 SSVAL(params
,18,smb_action
);
1450 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1452 SIVAL(params
,20,inode
);
1453 SSVAL(params
,24,0); /* Padding. */
1455 uint32_t ea_size
= estimate_ea_size(smb_fname
->fsp
);
1456 SIVAL(params
, 26, ea_size
);
1458 SIVAL(params
, 26, 0);
1461 /* Send the required number of replies */
1462 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1464 TALLOC_FREE(smb_fname
);
1467 /*********************************************************
1468 Routine to check if a given string matches exactly.
1469 as a special case a mask of "." does NOT match. That
1470 is required for correct wildcard semantics
1471 Case can be significant or not.
1472 **********************************************************/
1474 static bool exact_match(bool has_wild
,
1475 bool case_sensitive
,
1479 if (mask
[0] == '.' && mask
[1] == 0) {
1487 if (case_sensitive
) {
1488 return strcmp(str
,mask
)==0;
1490 return strcasecmp_m(str
,mask
) == 0;
1494 /****************************************************************************
1495 Return the filetype for UNIX extensions.
1496 ****************************************************************************/
1498 static uint32_t unix_filetype(mode_t mode
)
1501 return UNIX_TYPE_FILE
;
1502 else if(S_ISDIR(mode
))
1503 return UNIX_TYPE_DIR
;
1505 else if(S_ISLNK(mode
))
1506 return UNIX_TYPE_SYMLINK
;
1509 else if(S_ISCHR(mode
))
1510 return UNIX_TYPE_CHARDEV
;
1513 else if(S_ISBLK(mode
))
1514 return UNIX_TYPE_BLKDEV
;
1517 else if(S_ISFIFO(mode
))
1518 return UNIX_TYPE_FIFO
;
1521 else if(S_ISSOCK(mode
))
1522 return UNIX_TYPE_SOCKET
;
1525 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1526 return UNIX_TYPE_UNKNOWN
;
1529 /****************************************************************************
1530 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1531 ****************************************************************************/
1533 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
1534 const SMB_STRUCT_STAT
*psbuf
,
1536 enum perm_type ptype
,
1541 if (perms
== SMB_MODE_NO_CHANGE
) {
1542 if (!VALID_STAT(*psbuf
)) {
1543 return NT_STATUS_INVALID_PARAMETER
;
1545 *ret_perms
= psbuf
->st_ex_mode
;
1546 return NT_STATUS_OK
;
1550 ret
= wire_perms_to_unix(perms
);
1552 if (ptype
== PERM_NEW_FILE
) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret
&= lp_create_mask(SNUM(conn
));
1558 /* Add in force bits */
1559 ret
|= lp_force_create_mode(SNUM(conn
));
1560 } else if (ptype
== PERM_NEW_DIR
) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret
&= lp_directory_mask(SNUM(conn
));
1566 /* Add in force bits */
1567 ret
|= lp_force_directory_mode(SNUM(conn
));
1571 return NT_STATUS_OK
;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct
*conn
,
1580 struct smb_filename
*smb_fname
)
1582 int saved_errno
= errno
;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn
)) &&
1585 is_msdfs_link(conn
, smb_fname
)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1589 smb_fname
->base_name
));
1590 smb_fname
->st
.st_ex_mode
=
1591 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1592 errno
= saved_errno
;
1595 errno
= saved_errno
;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state
{
1605 connection_struct
*conn
;
1606 uint32_t info_level
;
1607 bool check_mangled_names
;
1609 bool got_exact_match
;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1618 struct smbd_dirptr_lanman2_state
*state
=
1619 (struct smbd_dirptr_lanman2_state
*)private_data
;
1621 char mangled_name
[13]; /* mangled 8.3 name. */
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1633 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp
= talloc_array(talloc_tos(),
1638 status
= srvstr_push(NULL
,
1639 FLAGS2_UNICODE_STRINGS
,
1648 if (!NT_STATUS_IS_OK(status
)) {
1652 ok
= name_to_8_3(dname
, mangled_name
,
1653 true, state
->conn
->params
);
1657 fname
= mangled_name
;
1662 got_match
= exact_match(state
->has_wild
,
1663 state
->conn
->case_sensitive
,
1665 state
->got_exact_match
= got_match
;
1667 got_match
= mask_match(fname
, mask
,
1668 state
->conn
->case_sensitive
);
1671 if(!got_match
&& state
->check_mangled_names
&&
1672 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok
= name_to_8_3(fname
, mangled_name
,
1681 false, state
->conn
->params
);
1686 got_match
= exact_match(state
->has_wild
,
1687 state
->conn
->case_sensitive
,
1688 mangled_name
, mask
);
1689 state
->got_exact_match
= got_match
;
1691 got_match
= mask_match(mangled_name
, mask
,
1692 state
->conn
->case_sensitive
);
1700 *_fname
= talloc_strdup(ctx
, fname
);
1701 if (*_fname
== NULL
) {
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1710 struct smb_filename
*smb_fname
,
1714 struct smbd_dirptr_lanman2_state
*state
=
1715 (struct smbd_dirptr_lanman2_state
*)private_data
;
1716 bool ms_dfs_link
= false;
1718 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
1719 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname
),
1727 } else if (!VALID_STAT(smb_fname
->st
) &&
1728 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1729 /* Needed to show the msdfs symlinks as
1732 ms_dfs_link
= check_msdfs_link(state
->conn
,
1735 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1736 "Couldn't stat [%s] (%s)\n",
1737 smb_fname_str_dbg(smb_fname
),
1742 *_mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1750 *_mode
= fdos_mode(smb_fname
->fsp
);
1751 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1756 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1757 connection_struct
*conn
,
1759 uint32_t info_level
,
1760 struct ea_list
*name_list
,
1761 bool check_mangled_names
,
1762 bool requires_resume_key
,
1765 const struct smb_filename
*smb_fname
,
1766 int space_remaining
,
1772 uint64_t *last_entry_off
)
1774 char *p
, *q
, *pdata
= *ppdata
;
1776 uint64_t file_size
= 0;
1777 uint64_t allocation_size
= 0;
1778 uint64_t file_id
= 0;
1780 struct timespec mdate_ts
= {0};
1781 struct timespec adate_ts
= {0};
1782 struct timespec cdate_ts
= {0};
1783 struct timespec create_date_ts
= {0};
1784 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1786 char *last_entry_ptr
;
1791 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1793 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1794 file_size
= get_file_size_stat(&smb_fname
->st
);
1796 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1798 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1799 if (!NT_STATUS_IS_OK(status
)) {
1800 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1805 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1807 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1808 adate_ts
= smb_fname
->st
.st_ex_atime
;
1809 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1810 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1812 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1813 dos_filetime_timespec(&create_date_ts
);
1814 dos_filetime_timespec(&mdate_ts
);
1815 dos_filetime_timespec(&adate_ts
);
1816 dos_filetime_timespec(&cdate_ts
);
1819 create_date
= convert_timespec_to_time_t(create_date_ts
);
1820 mdate
= convert_timespec_to_time_t(mdate_ts
);
1821 adate
= convert_timespec_to_time_t(adate_ts
);
1823 /* align the record */
1824 SMB_ASSERT(align
>= 1);
1826 off
= (int)PTR_DIFF(pdata
, base_data
);
1827 pad
= (off
+ (align
-1)) & ~(align
-1);
1830 if (pad
&& pad
> space_remaining
) {
1831 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1832 "for padding (wanted %u, had %d)\n",
1835 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1839 /* initialize padding to 0 */
1841 memset(pdata
, 0, pad
);
1843 space_remaining
-= pad
;
1845 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1855 switch (info_level
) {
1856 case SMB_FIND_INFO_STANDARD
:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1858 if(requires_resume_key
) {
1862 srv_put_dos_date2(p
,0,create_date
);
1863 srv_put_dos_date2(p
,4,adate
);
1864 srv_put_dos_date2(p
,8,mdate
);
1865 SIVAL(p
,12,(uint32_t)file_size
);
1866 SIVAL(p
,16,(uint32_t)allocation_size
);
1870 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1871 p
+= ucs2_align(base_data
, p
, 0);
1873 status
= srvstr_push(base_data
, flags2
, p
,
1874 fname
, PTR_DIFF(end_data
, p
),
1875 STR_TERMINATE
, &len
);
1876 if (!NT_STATUS_IS_OK(status
)) {
1879 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1881 SCVAL(nameptr
, -1, len
- 2);
1883 SCVAL(nameptr
, -1, 0);
1887 SCVAL(nameptr
, -1, len
- 1);
1889 SCVAL(nameptr
, -1, 0);
1895 case SMB_FIND_EA_SIZE
:
1896 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1897 if (requires_resume_key
) {
1901 srv_put_dos_date2(p
,0,create_date
);
1902 srv_put_dos_date2(p
,4,adate
);
1903 srv_put_dos_date2(p
,8,mdate
);
1904 SIVAL(p
,12,(uint32_t)file_size
);
1905 SIVAL(p
,16,(uint32_t)allocation_size
);
1908 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1909 SIVAL(p
,22,ea_size
); /* Extended attributes */
1913 status
= srvstr_push(base_data
, flags2
,
1914 p
, fname
, PTR_DIFF(end_data
, p
),
1915 STR_TERMINATE
| STR_NOALIGN
, &len
);
1916 if (!NT_STATUS_IS_OK(status
)) {
1919 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1932 SCVAL(nameptr
,0,len
);
1934 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1937 case SMB_FIND_EA_LIST
:
1939 struct ea_list
*file_list
= NULL
;
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1944 return NT_STATUS_INVALID_PARAMETER
;
1946 if (requires_resume_key
) {
1950 srv_put_dos_date2(p
,0,create_date
);
1951 srv_put_dos_date2(p
,4,adate
);
1952 srv_put_dos_date2(p
,8,mdate
);
1953 SIVAL(p
,12,(uint32_t)file_size
);
1954 SIVAL(p
,16,(uint32_t)allocation_size
);
1956 p
+= 22; /* p now points to the EA area. */
1958 status
= get_ea_list_from_fsp(ctx
,
1960 &ea_len
, &file_list
);
1961 if (!NT_STATUS_IS_OK(status
)) {
1964 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1966 /* We need to determine if this entry will fit in the space available. */
1967 /* Max string size is 255 bytes. */
1968 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1969 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1970 "(wanted %u, had %d)\n",
1971 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1973 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1976 /* Push the ea_data followed by the name. */
1977 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1979 status
= srvstr_push(base_data
, flags2
,
1980 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1981 STR_TERMINATE
| STR_NOALIGN
, &len
);
1982 if (!NT_STATUS_IS_OK(status
)) {
1985 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1998 SCVAL(nameptr
,0,len
);
2000 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
2004 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2005 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2006 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2008 SIVAL(p
,0,reskey
); p
+= 4;
2009 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2010 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2011 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2012 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2013 SOFF_T(p
,0,file_size
); p
+= 8;
2014 SOFF_T(p
,0,allocation_size
); p
+= 8;
2015 SIVAL(p
,0,mode
); p
+= 4;
2016 q
= p
; p
+= 4; /* q is placeholder for name length. */
2017 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2018 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2020 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2021 SIVAL(p
,0,ea_size
); /* Extended attributes */
2024 /* Clear the short name buffer. This is
2025 * IMPORTANT as not doing so will trigger
2026 * a Win2k client bug. JRA.
2028 if (!was_8_3
&& check_mangled_names
) {
2029 char mangled_name
[13]; /* mangled 8.3 name. */
2030 if (!name_to_8_3(fname
,mangled_name
,True
,
2032 /* Error - mangle failed ! */
2033 memset(mangled_name
,'\0',12);
2035 mangled_name
[12] = 0;
2036 status
= srvstr_push(base_data
, flags2
,
2037 p
+2, mangled_name
, 24,
2038 STR_UPPER
|STR_UNICODE
, &len
);
2039 if (!NT_STATUS_IS_OK(status
)) {
2043 memset(p
+ 2 + len
,'\0',24 - len
);
2050 status
= srvstr_push(base_data
, flags2
, p
,
2051 fname
, PTR_DIFF(end_data
, p
),
2052 STR_TERMINATE_ASCII
, &len
);
2053 if (!NT_STATUS_IS_OK(status
)) {
2059 len
= PTR_DIFF(p
, pdata
);
2060 pad
= (len
+ (align
-1)) & ~(align
-1);
2062 * offset to the next entry, the caller
2063 * will overwrite it for the last entry
2064 * that's why we always include the padding
2068 * set padding to zero
2071 memset(p
, 0, pad
- len
);
2078 case SMB_FIND_FILE_DIRECTORY_INFO
:
2079 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2081 SIVAL(p
,0,reskey
); p
+= 4;
2082 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2083 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2084 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2085 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2086 SOFF_T(p
,0,file_size
); p
+= 8;
2087 SOFF_T(p
,0,allocation_size
); p
+= 8;
2088 SIVAL(p
,0,mode
); p
+= 4;
2089 status
= srvstr_push(base_data
, flags2
,
2090 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
2091 STR_TERMINATE_ASCII
, &len
);
2092 if (!NT_STATUS_IS_OK(status
)) {
2098 len
= PTR_DIFF(p
, pdata
);
2099 pad
= (len
+ (align
-1)) & ~(align
-1);
2101 * offset to the next entry, the caller
2102 * will overwrite it for the last entry
2103 * that's why we always include the padding
2107 * set padding to zero
2110 memset(p
, 0, pad
- len
);
2117 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2118 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2120 SIVAL(p
,0,reskey
); p
+= 4;
2121 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2122 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2123 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2124 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2125 SOFF_T(p
,0,file_size
); p
+= 8;
2126 SOFF_T(p
,0,allocation_size
); p
+= 8;
2127 SIVAL(p
,0,mode
); p
+= 4;
2128 q
= p
; p
+= 4; /* q is placeholder for name length. */
2129 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2130 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2132 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2133 SIVAL(p
,0,ea_size
); /* Extended attributes */
2136 status
= srvstr_push(base_data
, flags2
, p
,
2137 fname
, PTR_DIFF(end_data
, p
),
2138 STR_TERMINATE_ASCII
, &len
);
2139 if (!NT_STATUS_IS_OK(status
)) {
2145 len
= PTR_DIFF(p
, pdata
);
2146 pad
= (len
+ (align
-1)) & ~(align
-1);
2148 * offset to the next entry, the caller
2149 * will overwrite it for the last entry
2150 * that's why we always include the padding
2154 * set padding to zero
2157 memset(p
, 0, pad
- len
);
2164 case SMB_FIND_FILE_NAMES_INFO
:
2165 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2167 SIVAL(p
,0,reskey
); p
+= 4;
2169 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2170 acl on a dir (tridge) */
2171 status
= srvstr_push(base_data
, flags2
, p
,
2172 fname
, PTR_DIFF(end_data
, p
),
2173 STR_TERMINATE_ASCII
, &len
);
2174 if (!NT_STATUS_IS_OK(status
)) {
2180 len
= PTR_DIFF(p
, pdata
);
2181 pad
= (len
+ (align
-1)) & ~(align
-1);
2183 * offset to the next entry, the caller
2184 * will overwrite it for the last entry
2185 * that's why we always include the padding
2189 * set padding to zero
2192 memset(p
, 0, pad
- len
);
2199 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2200 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2202 SIVAL(p
,0,reskey
); p
+= 4;
2203 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2204 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2205 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2206 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
2207 SOFF_T(p
,0,file_size
); p
+= 8;
2208 SOFF_T(p
,0,allocation_size
); p
+= 8;
2209 SIVAL(p
,0,mode
); p
+= 4;
2210 q
= p
; p
+= 4; /* q is placeholder for name length. */
2211 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2212 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2214 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2215 SIVAL(p
,0,ea_size
); /* Extended attributes */
2218 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2219 SBVAL(p
,0,file_id
); p
+= 8;
2220 status
= srvstr_push(base_data
, flags2
, p
,
2221 fname
, PTR_DIFF(end_data
, p
),
2222 STR_TERMINATE_ASCII
, &len
);
2223 if (!NT_STATUS_IS_OK(status
)) {
2229 len
= PTR_DIFF(p
, pdata
);
2230 pad
= (len
+ (align
-1)) & ~(align
-1);
2232 * offset to the next entry, the caller
2233 * will overwrite it for the last entry
2234 * that's why we always include the padding
2238 * set padding to zero
2241 memset(p
, 0, pad
- len
);
2248 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2249 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2250 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2252 SIVAL(p
,0,reskey
); p
+= 4;
2253 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
2254 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
2255 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
2256 put_long_date_full_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
);
2263 } else if (readdir_attr_data
&&
2264 readdir_attr_data
->type
== RDATTR_AAPL
) {
2266 * OS X specific SMB2 extension negotiated via
2267 * AAPL create context: return max_access in
2270 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2272 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
2273 SIVAL(p
,0,ea_size
); /* Extended attributes */
2277 if (readdir_attr_data
&&
2278 readdir_attr_data
->type
== RDATTR_AAPL
) {
2280 * OS X specific SMB2 extension negotiated via
2281 * AAPL create context: return resource fork
2282 * length and compressed FinderInfo in
2285 * According to documentation short_name_len
2286 * should be 0, but on the wire behaviour
2287 * shows its set to 24 by clients.
2291 /* Resourefork length */
2292 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2294 /* Compressed FinderInfo */
2295 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2296 } else if (!was_8_3
&& check_mangled_names
) {
2297 char mangled_name
[13]; /* mangled 8.3 name. */
2298 if (!name_to_8_3(fname
,mangled_name
,True
,
2300 /* Error - mangle failed ! */
2301 memset(mangled_name
,'\0',12);
2303 mangled_name
[12] = 0;
2304 status
= srvstr_push(base_data
, flags2
,
2305 p
+2, mangled_name
, 24,
2306 STR_UPPER
|STR_UNICODE
, &len
);
2307 if (!NT_STATUS_IS_OK(status
)) {
2312 memset(p
+ 2 + len
,'\0',24 - len
);
2316 /* Clear the short name buffer. This is
2317 * IMPORTANT as not doing so will trigger
2318 * a Win2k client bug. JRA.
2325 if (readdir_attr_data
&&
2326 readdir_attr_data
->type
== RDATTR_AAPL
) {
2328 * OS X specific SMB2 extension negotiated via
2329 * AAPL create context: return UNIX mode in
2332 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2333 SSVAL(p
, 0, aapl_mode
);
2339 SBVAL(p
,0,file_id
); p
+= 8;
2340 status
= srvstr_push(base_data
, flags2
, p
,
2341 fname
, PTR_DIFF(end_data
, p
),
2342 STR_TERMINATE_ASCII
, &len
);
2343 if (!NT_STATUS_IS_OK(status
)) {
2349 len
= PTR_DIFF(p
, pdata
);
2350 pad
= (len
+ (align
-1)) & ~(align
-1);
2352 * offset to the next entry, the caller
2353 * will overwrite it for the last entry
2354 * that's why we always include the padding
2358 * set padding to zero
2361 memset(p
, 0, pad
- len
);
2368 /* CIFS UNIX Extension. */
2370 case SMB_FIND_FILE_UNIX
:
2371 case SMB_FIND_FILE_UNIX_INFO2
:
2373 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2375 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2377 if (info_level
== SMB_FIND_FILE_UNIX
) {
2378 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2379 p
= store_file_unix_basic(conn
, p
,
2380 NULL
, &smb_fname
->st
);
2381 status
= srvstr_push(base_data
, flags2
, p
,
2382 fname
, PTR_DIFF(end_data
, p
),
2383 STR_TERMINATE
, &len
);
2384 if (!NT_STATUS_IS_OK(status
)) {
2388 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2389 p
= store_file_unix_basic_info2(conn
, p
,
2390 NULL
, &smb_fname
->st
);
2393 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2394 PTR_DIFF(end_data
, p
), 0, &len
);
2395 if (!NT_STATUS_IS_OK(status
)) {
2398 SIVAL(nameptr
, 0, len
);
2403 len
= PTR_DIFF(p
, pdata
);
2404 pad
= (len
+ (align
-1)) & ~(align
-1);
2406 * offset to the next entry, the caller
2407 * will overwrite it for the last entry
2408 * that's why we always include the padding
2412 * set padding to zero
2415 memset(p
, 0, pad
- len
);
2420 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2425 return NT_STATUS_INVALID_LEVEL
;
2428 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2429 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2430 "(wanted %u, had %d)\n",
2431 (unsigned int)PTR_DIFF(p
,pdata
),
2433 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2436 /* Setup the last entry pointer, as an offset from base_data */
2437 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2438 /* Advance the data pointer to the next slot */
2441 return NT_STATUS_OK
;
2444 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2445 connection_struct
*conn
,
2446 struct dptr_struct
*dirptr
,
2448 const char *path_mask
,
2451 int requires_resume_key
,
2460 int space_remaining
,
2461 struct smb_filename
**_smb_fname
,
2462 bool *got_exact_match
,
2463 int *_last_entry_off
,
2464 struct ea_list
*name_list
,
2465 struct file_id
*file_id
)
2468 const char *mask
= NULL
;
2469 long prev_dirpos
= 0;
2472 struct smb_filename
*smb_fname
= NULL
;
2473 struct smbd_dirptr_lanman2_state state
;
2475 uint64_t last_entry_off
= 0;
2477 enum mangled_names_options mangled_names
;
2478 bool marshall_with_83_names
;
2480 mangled_names
= lp_mangled_names(conn
->params
);
2484 state
.info_level
= info_level
;
2485 if (mangled_names
!= MANGLED_NAMES_NO
) {
2486 state
.check_mangled_names
= true;
2488 state
.has_wild
= dptr_has_wild(dirptr
);
2489 state
.got_exact_match
= false;
2491 *got_exact_match
= false;
2493 p
= strrchr_m(path_mask
,'/');
2504 ok
= smbd_dirptr_get_entry(ctx
,
2511 smbd_dirptr_lanman2_match_fn
,
2512 smbd_dirptr_lanman2_mode_fn
,
2519 return NT_STATUS_END_OF_FILE
;
2522 *got_exact_match
= state
.got_exact_match
;
2524 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2526 status
= smbd_marshall_dir_entry(ctx
,
2531 marshall_with_83_names
,
2532 requires_resume_key
,
2543 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2544 DEBUG(1,("Conversion error: illegal character: %s\n",
2545 smb_fname_str_dbg(smb_fname
)));
2548 if (file_id
!= NULL
) {
2549 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2552 if (!NT_STATUS_IS_OK(status
) &&
2553 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2555 TALLOC_FREE(smb_fname
);
2560 if (_smb_fname
!= NULL
) {
2561 struct smb_filename
*name
= NULL
;
2563 name
= synthetic_smb_fname(ctx
,
2570 TALLOC_FREE(smb_fname
);
2572 return NT_STATUS_NO_MEMORY
;
2577 TALLOC_FREE(smb_fname
);
2580 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2581 dptr_SeekDir(dirptr
, prev_dirpos
);
2585 *_last_entry_off
= last_entry_off
;
2586 return NT_STATUS_OK
;
2589 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2590 connection_struct
*conn
,
2591 struct dptr_struct
*dirptr
,
2593 const char *path_mask
,
2596 bool requires_resume_key
,
2602 int space_remaining
,
2603 bool *got_exact_match
,
2604 int *last_entry_off
,
2605 struct ea_list
*name_list
)
2608 const bool do_pad
= true;
2610 if (info_level
>= 1 && info_level
<= 3) {
2611 /* No alignment on earlier info levels. */
2615 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2616 path_mask
, dirtype
, info_level
,
2617 requires_resume_key
, dont_descend
, ask_sharemode
,
2618 true, align
, do_pad
,
2619 ppdata
, base_data
, end_data
,
2623 last_entry_off
, name_list
, NULL
);
2626 /****************************************************************************
2627 Reply to a TRANS2_FINDFIRST.
2628 ****************************************************************************/
2630 static void call_trans2findfirst(connection_struct
*conn
,
2631 struct smb_request
*req
,
2632 char **pparams
, int total_params
,
2633 char **ppdata
, int total_data
,
2634 unsigned int max_data_bytes
)
2636 /* We must be careful here that we don't return more than the
2637 allowed number of data bytes. If this means returning fewer than
2638 maxentries then so be it. We assume that the redirector has
2639 enough room for the fixed number of parameter bytes it has
2641 struct smb_filename
*smb_dname
= NULL
;
2642 char *params
= *pparams
;
2643 char *pdata
= *ppdata
;
2647 uint16_t findfirst_flags
;
2648 bool close_after_first
;
2650 bool requires_resume_key
;
2652 char *directory
= NULL
;
2655 int last_entry_off
=0;
2659 bool finished
= False
;
2660 bool dont_descend
= False
;
2661 bool out_of_space
= False
;
2662 int space_remaining
;
2663 struct ea_list
*ea_list
= NULL
;
2664 NTSTATUS ntstatus
= NT_STATUS_OK
;
2665 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
2666 struct smbd_server_connection
*sconn
= req
->sconn
;
2667 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
2668 ucf_flags_from_smb_request(req
);
2669 bool backup_priv
= false;
2670 bool as_root
= false;
2671 files_struct
*fsp
= NULL
;
2672 const struct loadparm_substitution
*lp_sub
=
2673 loadparm_s3_global_substitution();
2676 if (total_params
< 13) {
2677 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2681 dirtype
= SVAL(params
,0);
2682 maxentries
= SVAL(params
,2);
2683 findfirst_flags
= SVAL(params
,4);
2684 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2685 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2686 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2687 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2688 security_token_has_privilege(get_current_nttok(conn
),
2691 info_level
= SVAL(params
,6);
2693 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2694 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2695 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2697 info_level
, max_data_bytes
));
2700 /* W2K3 seems to treat zero as 1. */
2704 switch (info_level
) {
2705 case SMB_FIND_INFO_STANDARD
:
2706 case SMB_FIND_EA_SIZE
:
2707 case SMB_FIND_EA_LIST
:
2708 case SMB_FIND_FILE_DIRECTORY_INFO
:
2709 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2710 case SMB_FIND_FILE_NAMES_INFO
:
2711 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2712 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2713 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2715 case SMB_FIND_FILE_UNIX
:
2716 case SMB_FIND_FILE_UNIX_INFO2
:
2717 if (!lp_unix_extensions()) {
2718 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2723 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2727 if (req
->posix_pathnames
) {
2728 /* Always use filesystem for UNIX mtime query. */
2729 ask_sharemode
= false;
2732 if (req
->posix_pathnames
) {
2733 srvstr_get_path_posix(talloc_tos(),
2742 srvstr_get_path(talloc_tos(),
2751 if (!NT_STATUS_IS_OK(ntstatus
)) {
2752 reply_nterror(req
, ntstatus
);
2759 ntstatus
= filename_convert_with_privilege(talloc_tos(),
2766 ntstatus
= filename_convert(talloc_tos(), conn
,
2773 if (!NT_STATUS_IS_OK(ntstatus
)) {
2774 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2775 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2776 ERRSRV
, ERRbadpath
);
2779 reply_nterror(req
, ntstatus
);
2784 * The above call to filename_convert() is on the path from the client
2785 * including the search mask. Until the code that chops of the search
2786 * mask from the path below is moved before the call to
2787 * filename_convert(), we close a possible pathref fsp to ensure
2788 * SMB_VFS_CREATE_FILE() below will internally open a pathref fsp on the
2791 if (smb_dname
->fsp
!= NULL
) {
2792 ntstatus
= fd_close(smb_dname
->fsp
);
2793 if (!NT_STATUS_IS_OK(ntstatus
)) {
2794 reply_nterror(req
, ntstatus
);
2798 * The pathref fsp link destructor will set smb_dname->fsp to
2799 * NULL. Turning this into an assert to give a hint at readers
2800 * of the code trying to understand the mechanics.
2802 file_free(req
, smb_dname
->fsp
);
2803 SMB_ASSERT(smb_dname
->fsp
== NULL
);
2806 mask
= get_original_lcomp(talloc_tos(),
2811 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2815 directory
= smb_dname
->base_name
;
2817 p
= strrchr_m(directory
,'/');
2819 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2820 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2821 mask
= talloc_strdup(talloc_tos(),"*");
2823 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2831 if (p
== NULL
|| p
== directory
) {
2832 struct smb_filename
*old_name
= smb_dname
;
2834 /* Ensure we don't have a directory name of "". */
2835 smb_dname
= synthetic_smb_fname(talloc_tos(),
2841 TALLOC_FREE(old_name
);
2842 if (smb_dname
== NULL
) {
2843 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2846 directory
= smb_dname
->base_name
;
2849 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2851 if (info_level
== SMB_FIND_EA_LIST
) {
2854 if (total_data
< 4) {
2855 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2859 ea_size
= IVAL(pdata
,0);
2860 if (ea_size
!= total_data
) {
2861 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2862 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2863 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2867 if (!lp_ea_support(SNUM(conn
))) {
2868 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2872 /* Pull out the list of names. */
2873 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
2875 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2880 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2881 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2885 *ppdata
= (char *)SMB_REALLOC(
2886 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2887 if(*ppdata
== NULL
) {
2888 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2892 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2894 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2897 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2898 /* Realloc the params space */
2899 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2900 if (*pparams
== NULL
) {
2901 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2907 * As we've cut off the last component from
2908 * smb_fname we need to re-stat smb_dname
2909 * so FILE_OPEN disposition knows the directory
2912 ret
= vfs_stat(conn
, smb_dname
);
2914 ntstatus
= map_nt_error_from_unix(errno
);
2915 reply_nterror(req
, ntstatus
);
2919 ntstatus
= openat_pathref_fsp(conn
->cwd_fsp
, smb_dname
);
2920 if (!NT_STATUS_IS_OK(ntstatus
)) {
2921 reply_nterror(req
, ntstatus
);
2926 * Open an fsp on this directory for the dptr.
2928 ntstatus
= SMB_VFS_CREATE_FILE(
2931 smb_dname
, /* dname */
2932 FILE_LIST_DIRECTORY
, /* access_mask */
2934 FILE_SHARE_WRITE
, /* share_access */
2935 FILE_OPEN
, /* create_disposition*/
2936 FILE_DIRECTORY_FILE
, /* create_options */
2937 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
2938 NO_OPLOCK
, /* oplock_request */
2940 0, /* allocation_size */
2941 0, /* private_flags */
2946 NULL
, /* in_context */
2947 NULL
);/* out_context */
2949 if (!NT_STATUS_IS_OK(ntstatus
)) {
2950 DBG_ERR("failed to open directory %s\n",
2951 smb_fname_str_dbg(smb_dname
));
2952 reply_nterror(req
, ntstatus
);
2956 /* Save the wildcard match and attribs we are using on this directory -
2957 needed as lanman2 assumes these are being saved between calls */
2959 ntstatus
= dptr_create(conn
,
2969 if (!NT_STATUS_IS_OK(ntstatus
)) {
2971 * Use NULL here for the first parameter (req)
2972 * as this is not a client visible handle so
2973 * can'tbe part of an SMB1 chain.
2975 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2977 reply_nterror(req
, ntstatus
);
2982 /* Remember this in case we have
2983 to do a findnext. */
2984 dptr_set_priv(fsp
->dptr
);
2987 dptr_num
= dptr_dnum(fsp
->dptr
);
2988 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2990 /* We don't need to check for VOL here as this is returned by
2991 a different TRANS2 call. */
2993 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2994 directory
,lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
))));
2995 if (in_list(directory
,
2996 lp_dont_descend(talloc_tos(), lp_sub
, SNUM(conn
)),
2997 conn
->case_sensitive
)) {
2998 dont_descend
= True
;
3002 space_remaining
= max_data_bytes
;
3003 out_of_space
= False
;
3005 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
3006 bool got_exact_match
= False
;
3008 /* this is a heuristic to avoid seeking the dirptr except when
3009 absolutely necessary. It allows for a filename of about 40 chars */
3010 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3011 out_of_space
= True
;
3014 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
3018 mask
,dirtype
,info_level
,
3019 requires_resume_key
,dont_descend
,
3024 &last_entry_off
, ea_list
);
3025 if (NT_STATUS_EQUAL(ntstatus
,
3026 NT_STATUS_ILLEGAL_CHARACTER
)) {
3028 * Bad character conversion on name. Ignore this
3033 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3034 out_of_space
= true;
3036 finished
= !NT_STATUS_IS_OK(ntstatus
);
3040 if (!finished
&& !out_of_space
)
3044 * As an optimisation if we know we aren't looking
3045 * for a wildcard name (ie. the name matches the wildcard exactly)
3046 * then we can finish on any (first) match.
3047 * This speeds up large directory searches. JRA.
3053 /* Ensure space_remaining never goes -ve. */
3054 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
3055 space_remaining
= 0;
3056 out_of_space
= true;
3058 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3062 /* Check if we can close the dirptr */
3063 if(close_after_first
|| (finished
&& close_if_end
)) {
3064 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
3066 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3071 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3072 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3073 * the protocol level is less than NT1. Tested with smbclient. JRA.
3074 * This should fix the OS/2 client bug #2335.
3077 if(numentries
== 0) {
3080 * We may have already closed the file in the
3081 * close_after_first or finished case above.
3084 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3087 if (get_Protocol() < PROTOCOL_NT1
) {
3088 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
3091 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
3092 ERRDOS
, ERRbadfile
);
3097 /* At this point pdata points to numentries directory entries. */
3099 /* Set up the return parameter block */
3100 SSVAL(params
,0,dptr_num
);
3101 SSVAL(params
,2,numentries
);
3102 SSVAL(params
,4,finished
);
3103 SSVAL(params
,6,0); /* Never an EA error */
3104 SSVAL(params
,8,last_entry_off
);
3106 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
3109 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
3110 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
3112 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3116 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3117 smb_fn_name(req
->cmd
),
3118 mask
, directory
, dirtype
, numentries
) );
3121 * Force a name mangle here to ensure that the
3122 * mask as an 8.3 name is top of the mangled cache.
3123 * The reasons for this are subtle. Don't remove
3124 * this code unless you know what you are doing
3125 * (see PR#13758). JRA.
3128 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
3129 char mangled_name
[13];
3130 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
3138 TALLOC_FREE(smb_dname
);
3142 /****************************************************************************
3143 Reply to a TRANS2_FINDNEXT.
3144 ****************************************************************************/
3146 static void call_trans2findnext(connection_struct
*conn
,
3147 struct smb_request
*req
,
3148 char **pparams
, int total_params
,
3149 char **ppdata
, int total_data
,
3150 unsigned int max_data_bytes
)
3152 /* We must be careful here that we don't return more than the
3153 allowed number of data bytes. If this means returning fewer than
3154 maxentries then so be it. We assume that the redirector has
3155 enough room for the fixed number of parameter bytes it has
3157 char *params
= *pparams
;
3158 char *pdata
= *ppdata
;
3162 uint16_t info_level
;
3163 uint32_t resume_key
;
3164 uint16_t findnext_flags
;
3165 bool close_after_request
;
3167 bool requires_resume_key
;
3169 char *resume_name
= NULL
;
3170 const char *mask
= NULL
;
3171 const char *directory
= NULL
;
3175 int i
, last_entry_off
=0;
3176 bool finished
= False
;
3177 bool dont_descend
= False
;
3178 bool out_of_space
= False
;
3179 int space_remaining
;
3180 struct ea_list
*ea_list
= NULL
;
3181 NTSTATUS ntstatus
= NT_STATUS_OK
;
3182 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
3183 TALLOC_CTX
*ctx
= talloc_tos();
3184 struct smbd_server_connection
*sconn
= req
->sconn
;
3185 bool backup_priv
= false;
3186 bool as_root
= false;
3187 files_struct
*fsp
= NULL
;
3188 const struct loadparm_substitution
*lp_sub
=
3189 loadparm_s3_global_substitution();
3191 if (total_params
< 13) {
3192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3196 dptr_num
= SVAL(params
,0);
3197 maxentries
= SVAL(params
,2);
3198 info_level
= SVAL(params
,4);
3199 resume_key
= IVAL(params
,6);
3200 findnext_flags
= SVAL(params
,10);
3201 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
3202 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
3203 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
3204 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
3206 if (!continue_bit
) {
3207 /* We only need resume_name if continue_bit is zero. */
3208 if (req
->posix_pathnames
) {
3209 srvstr_get_path_posix(ctx
,
3218 srvstr_get_path(ctx
,
3227 if (!NT_STATUS_IS_OK(ntstatus
)) {
3228 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3229 complain (it thinks we're asking for the directory above the shared
3230 path or an invalid name). Catch this as the resume name is only compared, never used in
3231 a file access. JRA. */
3232 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
3233 &resume_name
, params
+12,
3237 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
3238 reply_nterror(req
, ntstatus
);
3244 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3245 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3246 resume_key = %d resume name = %s continue=%d level = %d\n",
3247 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
3248 requires_resume_key
, resume_key
,
3249 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
3252 /* W2K3 seems to treat zero as 1. */
3256 switch (info_level
) {
3257 case SMB_FIND_INFO_STANDARD
:
3258 case SMB_FIND_EA_SIZE
:
3259 case SMB_FIND_EA_LIST
:
3260 case SMB_FIND_FILE_DIRECTORY_INFO
:
3261 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
3262 case SMB_FIND_FILE_NAMES_INFO
:
3263 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
3264 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
3265 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
3267 case SMB_FIND_FILE_UNIX
:
3268 case SMB_FIND_FILE_UNIX_INFO2
:
3269 /* Always use filesystem for UNIX mtime query. */
3270 ask_sharemode
= false;
3271 if (!lp_unix_extensions()) {
3272 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3277 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3281 if (info_level
== SMB_FIND_EA_LIST
) {
3284 if (total_data
< 4) {
3285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3289 ea_size
= IVAL(pdata
,0);
3290 if (ea_size
!= total_data
) {
3291 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3292 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3297 if (!lp_ea_support(SNUM(conn
))) {
3298 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
3302 /* Pull out the list of names. */
3303 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3305 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3310 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3315 *ppdata
= (char *)SMB_REALLOC(
3316 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3317 if(*ppdata
== NULL
) {
3318 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3323 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3326 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3329 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3330 /* Realloc the params space */
3331 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3332 if(*pparams
== NULL
) {
3333 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3339 /* Check that the dptr is valid */
3340 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
3342 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3346 directory
= dptr_path(sconn
, dptr_num
);
3348 /* Get the wildcard mask from the dptr */
3349 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3350 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3351 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3355 /* Get the attr mask from the dptr */
3356 dirtype
= dptr_attr(sconn
, dptr_num
);
3358 backup_priv
= dptr_get_priv(fsp
->dptr
);
3360 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3361 "backup_priv = %d\n",
3362 dptr_num
, mask
, dirtype
,
3364 dptr_TellDir(fsp
->dptr
),
3367 /* We don't need to check for VOL here as this is returned by
3368 a different TRANS2 call. */
3370 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3371 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
3372 if (in_list(directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),conn
->case_sensitive
))
3373 dont_descend
= True
;
3376 space_remaining
= max_data_bytes
;
3377 out_of_space
= False
;
3385 * Seek to the correct position. We no longer use the resume key but
3386 * depend on the last file name instead.
3389 if(!continue_bit
&& resume_name
&& *resume_name
) {
3392 long current_pos
= 0;
3394 * Remember, name_to_8_3 is called by
3395 * get_lanman2_dir_entry(), so the resume name
3396 * could be mangled. Ensure we check the unmangled name.
3399 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3400 char *new_resume_name
= NULL
;
3401 mangle_lookup_name_from_8_3(ctx
,
3405 if (new_resume_name
) {
3406 resume_name
= new_resume_name
;
3411 * Fix for NT redirector problem triggered by resume key indexes
3412 * changing between directory scans. We now return a resume key of 0
3413 * and instead look for the filename to continue from (also given
3414 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3415 * findfirst/findnext (as is usual) then the directory pointer
3416 * should already be at the correct place.
3419 finished
= !dptr_SearchDir(fsp
->dptr
, resume_name
, ¤t_pos
, &st
);
3420 } /* end if resume_name && !continue_bit */
3422 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3423 bool got_exact_match
= False
;
3425 /* this is a heuristic to avoid seeking the fsp->dptr except when
3426 absolutely necessary. It allows for a filename of about 40 chars */
3427 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3428 out_of_space
= True
;
3431 ntstatus
= get_lanman2_dir_entry(ctx
,
3435 mask
,dirtype
,info_level
,
3436 requires_resume_key
,dont_descend
,
3441 &last_entry_off
, ea_list
);
3442 if (NT_STATUS_EQUAL(ntstatus
,
3443 NT_STATUS_ILLEGAL_CHARACTER
)) {
3445 * Bad character conversion on name. Ignore this
3450 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3451 out_of_space
= true;
3453 finished
= !NT_STATUS_IS_OK(ntstatus
);
3457 if (!finished
&& !out_of_space
)
3461 * As an optimisation if we know we aren't looking
3462 * for a wildcard name (ie. the name matches the wildcard exactly)
3463 * then we can finish on any (first) match.
3464 * This speeds up large directory searches. JRA.
3470 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3473 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3474 smb_fn_name(req
->cmd
),
3475 mask
, directory
, dirtype
, numentries
) );
3477 /* Check if we can close the fsp->dptr */
3478 if(close_after_request
|| (finished
&& close_if_end
)) {
3479 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3481 close_file(NULL
, fsp
, NORMAL_CLOSE
);
3489 /* Set up the return parameter block */
3490 SSVAL(params
,0,numentries
);
3491 SSVAL(params
,2,finished
);
3492 SSVAL(params
,4,0); /* Never an EA error */
3493 SSVAL(params
,6,last_entry_off
);
3495 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3501 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3503 const struct loadparm_substitution
*lp_sub
=
3504 loadparm_s3_global_substitution();
3506 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
3510 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3512 SMB_ASSERT(extended_info
!= NULL
);
3514 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3515 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3516 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3517 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3518 #ifdef SAMBA_VERSION_REVISION
3519 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3521 extended_info
->samba_subversion
= 0;
3522 #ifdef SAMBA_VERSION_RC_RELEASE
3523 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3525 #ifdef SAMBA_VERSION_PRE_RELEASE
3526 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3529 #ifdef SAMBA_VERSION_VENDOR_PATCH
3530 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3532 extended_info
->samba_gitcommitdate
= 0;
3533 #ifdef SAMBA_VERSION_COMMIT_TIME
3534 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3537 memset(extended_info
->samba_version_string
, 0,
3538 sizeof(extended_info
->samba_version_string
));
3540 snprintf (extended_info
->samba_version_string
,
3541 sizeof(extended_info
->samba_version_string
),
3542 "%s", samba_version_string());
3545 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3546 connection_struct
*conn
,
3547 TALLOC_CTX
*mem_ctx
,
3548 uint16_t info_level
,
3550 unsigned int max_data_bytes
,
3551 size_t *fixed_portion
,
3552 struct smb_filename
*fname
,
3556 const struct loadparm_substitution
*lp_sub
=
3557 loadparm_s3_global_substitution();
3558 char *pdata
, *end_data
;
3561 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3562 int snum
= SNUM(conn
);
3563 const char *fstype
= lp_fstype(SNUM(conn
));
3564 const char *filename
= NULL
;
3565 const uint64_t bytes_per_sector
= 512;
3566 uint32_t additional_flags
= 0;
3567 struct smb_filename smb_fname
;
3569 NTSTATUS status
= NT_STATUS_OK
;
3572 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3575 filename
= fname
->base_name
;
3579 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3580 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3581 "info level (0x%x) on IPC$.\n",
3582 (unsigned int)info_level
));
3583 return NT_STATUS_ACCESS_DENIED
;
3587 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3589 smb_fname
= (struct smb_filename
) {
3590 .base_name
= discard_const_p(char, filename
),
3591 .flags
= fname
? fname
->flags
: 0,
3592 .twrp
= fname
? fname
->twrp
: 0,
3595 if(info_level
!= SMB_FS_QUOTA_INFORMATION
3596 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3597 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3598 return map_nt_error_from_unix(errno
);
3603 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3604 return NT_STATUS_INVALID_PARAMETER
;
3607 *ppdata
= (char *)SMB_REALLOC(
3608 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3609 if (*ppdata
== NULL
) {
3610 return NT_STATUS_NO_MEMORY
;
3614 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3615 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3619 switch (info_level
) {
3620 case SMB_INFO_ALLOCATION
:
3622 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3624 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3626 if (df_ret
== (uint64_t)-1) {
3627 return map_nt_error_from_unix(errno
);
3630 block_size
= lp_block_size(snum
);
3631 if (bsize
< block_size
) {
3632 uint64_t factor
= block_size
/bsize
;
3637 if (bsize
> block_size
) {
3638 uint64_t factor
= bsize
/block_size
;
3643 sectors_per_unit
= bsize
/bytes_per_sector
;
3645 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3647 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3650 * For large drives, return max values and not modulo.
3652 dsize
= MIN(dsize
, UINT32_MAX
);
3653 dfree
= MIN(dfree
, UINT32_MAX
);
3655 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3656 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3657 SIVAL(pdata
,l1_cUnit
,dsize
);
3658 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3659 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3663 case SMB_INFO_VOLUME
:
3664 /* Return volume name */
3666 * Add volume serial number - hash of a combination of
3667 * the called hostname and the service name.
3669 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3671 * Win2k3 and previous mess this up by sending a name length
3672 * one byte short. I believe only older clients (OS/2 Win9x) use
3673 * this call so try fixing this by adding a terminating null to
3674 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3676 status
= srvstr_push(
3678 pdata
+l2_vol_szVolLabel
, vname
,
3679 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3680 STR_NOALIGN
|STR_TERMINATE
, &len
);
3681 if (!NT_STATUS_IS_OK(status
)) {
3684 SCVAL(pdata
,l2_vol_cch
,len
);
3685 data_len
= l2_vol_szVolLabel
+ len
;
3686 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3687 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3688 (unsigned)len
, vname
));
3691 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3692 case SMB_FS_ATTRIBUTE_INFORMATION
:
3694 additional_flags
= 0;
3695 #if defined(HAVE_SYS_QUOTAS)
3696 additional_flags
|= FILE_VOLUME_QUOTAS
;
3699 if(lp_nt_acl_support(SNUM(conn
))) {
3700 additional_flags
|= FILE_PERSISTENT_ACLS
;
3703 /* Capabilities are filled in at connection time through STATVFS call */
3704 additional_flags
|= conn
->fs_capabilities
;
3705 additional_flags
|= lp_parm_int(conn
->params
->service
,
3706 "share", "fake_fscaps",
3709 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3710 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3711 additional_flags
); /* FS ATTRIBUTES */
3713 SIVAL(pdata
,4,255); /* Max filename component length */
3714 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3715 and will think we can't do long filenames */
3716 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3717 PTR_DIFF(end_data
, pdata
+12),
3719 if (!NT_STATUS_IS_OK(status
)) {
3723 data_len
= 12 + len
;
3724 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3725 /* the client only requested a portion of the
3727 data_len
= max_data_bytes
;
3728 status
= STATUS_BUFFER_OVERFLOW
;
3730 *fixed_portion
= 16;
3733 case SMB_QUERY_FS_LABEL_INFO
:
3734 case SMB_FS_LABEL_INFORMATION
:
3735 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3736 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3737 if (!NT_STATUS_IS_OK(status
)) {
3744 case SMB_QUERY_FS_VOLUME_INFO
:
3745 case SMB_FS_VOLUME_INFORMATION
:
3748 * Add volume serial number - hash of a combination of
3749 * the called hostname and the service name.
3751 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
3752 (str_checksum(get_local_machine_name())<<16));
3754 /* Max label len is 32 characters. */
3755 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3756 PTR_DIFF(end_data
, pdata
+18),
3758 if (!NT_STATUS_IS_OK(status
)) {
3761 SIVAL(pdata
,12,len
);
3764 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3765 (int)strlen(vname
),vname
,
3766 lp_servicename(talloc_tos(), lp_sub
, snum
)));
3767 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3768 /* the client only requested a portion of the
3770 data_len
= max_data_bytes
;
3771 status
= STATUS_BUFFER_OVERFLOW
;
3773 *fixed_portion
= 24;
3776 case SMB_QUERY_FS_SIZE_INFO
:
3777 case SMB_FS_SIZE_INFORMATION
:
3779 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3781 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3783 if (df_ret
== (uint64_t)-1) {
3784 return map_nt_error_from_unix(errno
);
3786 block_size
= lp_block_size(snum
);
3787 if (bsize
< block_size
) {
3788 uint64_t factor
= block_size
/bsize
;
3793 if (bsize
> block_size
) {
3794 uint64_t factor
= bsize
/block_size
;
3799 sectors_per_unit
= bsize
/bytes_per_sector
;
3800 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3801 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3802 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3803 SBIG_UINT(pdata
,0,dsize
);
3804 SBIG_UINT(pdata
,8,dfree
);
3805 SIVAL(pdata
,16,sectors_per_unit
);
3806 SIVAL(pdata
,20,bytes_per_sector
);
3807 *fixed_portion
= 24;
3811 case SMB_FS_FULL_SIZE_INFORMATION
:
3813 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3815 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3817 if (df_ret
== (uint64_t)-1) {
3818 return map_nt_error_from_unix(errno
);
3820 block_size
= lp_block_size(snum
);
3821 if (bsize
< block_size
) {
3822 uint64_t factor
= block_size
/bsize
;
3827 if (bsize
> block_size
) {
3828 uint64_t factor
= bsize
/block_size
;
3833 sectors_per_unit
= bsize
/bytes_per_sector
;
3834 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3835 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3836 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3837 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3838 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3839 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3840 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3841 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3842 *fixed_portion
= 32;
3846 case SMB_QUERY_FS_DEVICE_INFO
:
3847 case SMB_FS_DEVICE_INFORMATION
:
3849 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3851 if (!CAN_WRITE(conn
)) {
3852 characteristics
|= FILE_READ_ONLY_DEVICE
;
3855 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3856 SIVAL(pdata
,4,characteristics
);
3861 #ifdef HAVE_SYS_QUOTAS
3862 case SMB_FS_QUOTA_INFORMATION
:
3864 * what we have to send --metze:
3866 * Unknown1: 24 NULL bytes
3867 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3868 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3869 * Quota Flags: 2 byte :
3870 * Unknown3: 6 NULL bytes
3874 * details for Quota Flags:
3876 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3877 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3878 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3879 * 0x0001 Enable Quotas: enable quota for this fs
3883 /* we need to fake up a fsp here,
3884 * because its not send in this call
3887 SMB_NTQUOTA_STRUCT quotas
;
3890 ZERO_STRUCT(quotas
);
3893 fsp
.fnum
= FNUM_FIELD_INVALID
;
3896 if (get_current_uid(conn
) != 0) {
3897 DEBUG(0,("get_user_quota: access_denied "
3898 "service [%s] user [%s]\n",
3899 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
3900 conn
->session_info
->unix_info
->unix_name
));
3901 return NT_STATUS_ACCESS_DENIED
;
3904 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
3906 if (!NT_STATUS_IS_OK(status
)) {
3907 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
3913 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3914 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
3916 /* Unknown1 24 NULL bytes*/
3917 SBIG_UINT(pdata
,0,(uint64_t)0);
3918 SBIG_UINT(pdata
,8,(uint64_t)0);
3919 SBIG_UINT(pdata
,16,(uint64_t)0);
3921 /* Default Soft Quota 8 bytes */
3922 SBIG_UINT(pdata
,24,quotas
.softlim
);
3924 /* Default Hard Quota 8 bytes */
3925 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3927 /* Quota flag 2 bytes */
3928 SSVAL(pdata
,40,quotas
.qflags
);
3930 /* Unknown3 6 NULL bytes */
3936 #endif /* HAVE_SYS_QUOTAS */
3937 case SMB_FS_OBJECTID_INFORMATION
:
3939 unsigned char objid
[16];
3940 struct smb_extended_info extended_info
;
3941 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3942 samba_extended_info_version (&extended_info
);
3943 SIVAL(pdata
,16,extended_info
.samba_magic
);
3944 SIVAL(pdata
,20,extended_info
.samba_version
);
3945 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3946 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3947 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3952 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3956 * These values match a physical Windows Server 2012
3957 * share backed by NTFS atop spinning rust.
3959 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3960 /* logical_bytes_per_sector */
3961 SIVAL(pdata
, 0, bytes_per_sector
);
3962 /* phys_bytes_per_sector_atomic */
3963 SIVAL(pdata
, 4, bytes_per_sector
);
3964 /* phys_bytes_per_sector_perf */
3965 SIVAL(pdata
, 8, bytes_per_sector
);
3966 /* fs_effective_phys_bytes_per_sector_atomic */
3967 SIVAL(pdata
, 12, bytes_per_sector
);
3969 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3970 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3971 /* byte_off_sector_align */
3972 SIVAL(pdata
, 20, 0);
3973 /* byte_off_partition_align */
3974 SIVAL(pdata
, 24, 0);
3975 *fixed_portion
= 28;
3981 * Query the version and capabilities of the CIFS UNIX extensions
3985 case SMB_QUERY_CIFS_UNIX_INFO
:
3987 bool large_write
= lp_min_receive_file_size() &&
3988 !srv_is_signing_active(xconn
);
3989 bool large_read
= !srv_is_signing_active(xconn
);
3990 int encrypt_caps
= 0;
3992 if (!lp_unix_extensions()) {
3993 return NT_STATUS_INVALID_LEVEL
;
3996 switch (conn
->encrypt_level
) {
3997 case SMB_SIGNING_OFF
:
4000 case SMB_SIGNING_DESIRED
:
4001 case SMB_SIGNING_IF_REQUIRED
:
4002 case SMB_SIGNING_DEFAULT
:
4003 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
4005 case SMB_SIGNING_REQUIRED
:
4006 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
4007 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
4008 large_write
= false;
4014 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
4015 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
4017 /* We have POSIX ACLs, pathname, encryption,
4018 * large read/write, and locking capability. */
4020 SBIG_UINT(pdata
,4,((uint64_t)(
4021 CIFS_UNIX_POSIX_ACLS_CAP
|
4022 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
4023 CIFS_UNIX_FCNTL_LOCKS_CAP
|
4024 CIFS_UNIX_EXTATTR_CAP
|
4025 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
4027 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
4029 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
4033 case SMB_QUERY_POSIX_FS_INFO
:
4036 vfs_statvfs_struct svfs
;
4038 if (!lp_unix_extensions()) {
4039 return NT_STATUS_INVALID_LEVEL
;
4042 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
4046 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
4047 SIVAL(pdata
,4,svfs
.BlockSize
);
4048 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
4049 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
4050 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
4051 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
4052 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
4053 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
4054 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4056 } else if (rc
== EOPNOTSUPP
) {
4057 return NT_STATUS_INVALID_LEVEL
;
4058 #endif /* EOPNOTSUPP */
4060 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4061 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
4066 case SMB_QUERY_POSIX_WHOAMI
:
4072 if (!lp_unix_extensions()) {
4073 return NT_STATUS_INVALID_LEVEL
;
4076 if (max_data_bytes
< 40) {
4077 return NT_STATUS_BUFFER_TOO_SMALL
;
4080 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
4081 flags
|= SMB_WHOAMI_GUEST
;
4084 /* NOTE: 8 bytes for UID/GID, irrespective of native
4085 * platform size. This matches
4086 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4088 data_len
= 4 /* flags */
4095 + 4 /* pad/reserved */
4096 + (conn
->session_info
->unix_token
->ngroups
* 8)
4098 + (conn
->session_info
->security_token
->num_sids
*
4102 SIVAL(pdata
, 0, flags
);
4103 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
4105 (uint64_t)conn
->session_info
->unix_token
->uid
);
4106 SBIG_UINT(pdata
, 16,
4107 (uint64_t)conn
->session_info
->unix_token
->gid
);
4110 if (data_len
>= max_data_bytes
) {
4111 /* Potential overflow, skip the GIDs and SIDs. */
4113 SIVAL(pdata
, 24, 0); /* num_groups */
4114 SIVAL(pdata
, 28, 0); /* num_sids */
4115 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
4116 SIVAL(pdata
, 36, 0); /* reserved */
4122 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
4123 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
4125 /* We walk the SID list twice, but this call is fairly
4126 * infrequent, and I don't expect that it's performance
4127 * sensitive -- jpeach
4129 for (i
= 0, sid_bytes
= 0;
4130 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4131 sid_bytes
+= ndr_size_dom_sid(
4132 &conn
->session_info
->security_token
->sids
[i
],
4136 /* SID list byte count */
4137 SIVAL(pdata
, 32, sid_bytes
);
4139 /* 4 bytes pad/reserved - must be zero */
4140 SIVAL(pdata
, 36, 0);
4144 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
4145 SBIG_UINT(pdata
, data_len
,
4146 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
4152 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4153 int sid_len
= ndr_size_dom_sid(
4154 &conn
->session_info
->security_token
->sids
[i
],
4157 sid_linearize((uint8_t *)(pdata
+ data_len
),
4159 &conn
->session_info
->security_token
->sids
[i
]);
4160 data_len
+= sid_len
;
4166 case SMB_MAC_QUERY_FS_INFO
:
4168 * Thursby MAC extension... ONLY on NTFS filesystems
4169 * once we do streams then we don't need this
4171 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
4173 SIVAL(pdata
,84,0x100); /* Don't support mac... */
4179 return NT_STATUS_INVALID_LEVEL
;
4182 *ret_data_len
= data_len
;
4186 static NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
4187 struct smb_request
*req
,
4189 const DATA_BLOB
*qdata
)
4191 const struct loadparm_substitution
*lp_sub
=
4192 loadparm_s3_global_substitution();
4194 SMB_NTQUOTA_STRUCT quotas
;
4196 ZERO_STRUCT(quotas
);
4199 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4200 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4201 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
4202 conn
->session_info
->unix_info
->unix_name
));
4203 return NT_STATUS_ACCESS_DENIED
;
4206 if (!check_fsp_ntquota_handle(conn
, req
,
4208 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4209 return NT_STATUS_INVALID_HANDLE
;
4212 /* note: normally there're 48 bytes,
4213 * but we didn't use the last 6 bytes for now
4216 if (qdata
->length
< 42) {
4217 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4218 (unsigned int)qdata
->length
));
4219 return NT_STATUS_INVALID_PARAMETER
;
4222 /* unknown_1 24 NULL bytes in pdata*/
4224 /* the soft quotas 8 bytes (uint64_t)*/
4225 quotas
.softlim
= BVAL(qdata
->data
,24);
4227 /* the hard quotas 8 bytes (uint64_t)*/
4228 quotas
.hardlim
= BVAL(qdata
->data
,32);
4230 /* quota_flags 2 bytes **/
4231 quotas
.qflags
= SVAL(qdata
->data
,40);
4233 /* unknown_2 6 NULL bytes follow*/
4235 /* now set the quotas */
4236 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4237 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4238 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4239 status
= map_nt_error_from_unix(errno
);
4241 status
= NT_STATUS_OK
;
4246 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
4247 struct smb_request
*req
,
4248 TALLOC_CTX
*mem_ctx
,
4249 uint16_t info_level
,
4251 const DATA_BLOB
*pdata
)
4253 switch (info_level
) {
4254 case SMB_FS_QUOTA_INFORMATION
:
4256 return smb_set_fsquota(conn
,
4265 return NT_STATUS_INVALID_LEVEL
;
4268 /****************************************************************************
4269 Reply to a TRANS2_QFSINFO (query filesystem info).
4270 ****************************************************************************/
4272 static void call_trans2qfsinfo(connection_struct
*conn
,
4273 struct smb_request
*req
,
4274 char **pparams
, int total_params
,
4275 char **ppdata
, int total_data
,
4276 unsigned int max_data_bytes
)
4278 char *params
= *pparams
;
4279 uint16_t info_level
;
4281 size_t fixed_portion
;
4284 if (total_params
< 2) {
4285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4289 info_level
= SVAL(params
,0);
4291 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4292 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
4293 DEBUG(0,("call_trans2qfsinfo: encryption required "
4294 "and info level 0x%x sent.\n",
4295 (unsigned int)info_level
));
4296 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4301 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
4303 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
4310 if (!NT_STATUS_IS_OK(status
)) {
4311 reply_nterror(req
, status
);
4315 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
4318 DEBUG( 4, ( "%s info_level = %d\n",
4319 smb_fn_name(req
->cmd
), info_level
) );
4324 /****************************************************************************
4325 Reply to a TRANS2_SETFSINFO (set filesystem info).
4326 ****************************************************************************/
4328 static void call_trans2setfsinfo(connection_struct
*conn
,
4329 struct smb_request
*req
,
4330 char **pparams
, int total_params
,
4331 char **ppdata
, int total_data
,
4332 unsigned int max_data_bytes
)
4334 const struct loadparm_substitution
*lp_sub
=
4335 loadparm_s3_global_substitution();
4336 struct smbXsrv_connection
*xconn
= req
->xconn
;
4337 char *pdata
= *ppdata
;
4338 char *params
= *pparams
;
4339 uint16_t info_level
;
4341 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4342 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
4345 if (total_params
< 4) {
4346 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4352 info_level
= SVAL(params
,2);
4355 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
4356 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
4357 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4358 "info level (0x%x) on IPC$.\n",
4359 (unsigned int)info_level
));
4360 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4365 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4366 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
4367 DEBUG(0,("call_trans2setfsinfo: encryption required "
4368 "and info level 0x%x sent.\n",
4369 (unsigned int)info_level
));
4370 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4375 switch(info_level
) {
4376 case SMB_SET_CIFS_UNIX_INFO
:
4377 if (!lp_unix_extensions()) {
4378 DEBUG(2,("call_trans2setfsinfo: "
4379 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4380 "unix extensions off\n"));
4382 NT_STATUS_INVALID_LEVEL
);
4386 /* There should be 12 bytes of capabilities set. */
4387 if (total_data
< 12) {
4390 NT_STATUS_INVALID_PARAMETER
);
4393 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
4394 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
4395 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
4396 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
4397 /* Just print these values for now. */
4398 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4399 "major = %u, minor = %u cap_low = 0x%x, "
4401 (unsigned int)xconn
->
4402 smb1
.unix_info
.client_major
,
4403 (unsigned int)xconn
->
4404 smb1
.unix_info
.client_minor
,
4405 (unsigned int)xconn
->
4406 smb1
.unix_info
.client_cap_low
,
4407 (unsigned int)xconn
->
4408 smb1
.unix_info
.client_cap_high
));
4410 /* Here is where we must switch to posix pathname processing... */
4411 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
4412 lp_set_posix_pathnames();
4413 mangle_change_to_posix();
4416 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
4417 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
4418 /* Client that knows how to do posix locks,
4419 * but not posix open/mkdir operations. Set a
4420 * default type for read/write checks. */
4422 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
4427 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4430 size_t param_len
= 0;
4431 size_t data_len
= total_data
;
4433 if (!lp_unix_extensions()) {
4436 NT_STATUS_INVALID_LEVEL
);
4440 if (lp_server_smb_encrypt(SNUM(conn
)) ==
4441 SMB_ENCRYPTION_OFF
) {
4444 NT_STATUS_NOT_SUPPORTED
);
4448 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4449 DEBUG( 2,("call_trans2setfsinfo: "
4450 "request transport encryption disabled"
4451 "with 'fork echo handler = yes'\n"));
4454 NT_STATUS_NOT_SUPPORTED
);
4458 DEBUG( 4,("call_trans2setfsinfo: "
4459 "request transport encryption.\n"));
4461 status
= srv_request_encryption_setup(conn
,
4462 (unsigned char **)ppdata
,
4464 (unsigned char **)pparams
,
4467 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4468 !NT_STATUS_IS_OK(status
)) {
4469 reply_nterror(req
, status
);
4473 send_trans2_replies(conn
, req
,
4481 if (NT_STATUS_IS_OK(status
)) {
4482 /* Server-side transport
4483 * encryption is now *on*. */
4484 status
= srv_encryption_start(conn
);
4485 if (!NT_STATUS_IS_OK(status
)) {
4486 char *reason
= talloc_asprintf(talloc_tos(),
4487 "Failure in setting "
4488 "up encrypted transport: %s",
4490 exit_server_cleanly(reason
);
4496 case SMB_FS_QUOTA_INFORMATION
:
4500 .data
= (uint8_t *)pdata
,
4501 .length
= total_data
4503 files_struct
*fsp
= NULL
;
4504 fsp
= file_fsp(req
, SVAL(params
,0));
4506 status
= smb_set_fsquota(conn
,
4510 if (!NT_STATUS_IS_OK(status
)) {
4511 reply_nterror(req
, status
);
4517 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4519 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4525 * sending this reply works fine,
4526 * but I'm not sure it's the same
4527 * like windows do...
4530 reply_outbuf(req
, 10, 0);
4533 #if defined(HAVE_POSIX_ACLS)
4534 /****************************************************************************
4535 Utility function to count the number of entries in a POSIX acl.
4536 ****************************************************************************/
4538 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4540 unsigned int ace_count
= 0;
4541 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4542 SMB_ACL_ENTRY_T entry
;
4544 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4546 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4547 entry_id
= SMB_ACL_NEXT_ENTRY
;
4554 /****************************************************************************
4555 Utility function to marshall a POSIX acl into wire format.
4556 ****************************************************************************/
4558 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4560 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4561 SMB_ACL_ENTRY_T entry
;
4563 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4564 SMB_ACL_TAG_T tagtype
;
4565 SMB_ACL_PERMSET_T permset
;
4566 unsigned char perms
= 0;
4567 unsigned int own_grp
;
4570 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4571 entry_id
= SMB_ACL_NEXT_ENTRY
;
4574 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4575 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4579 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4580 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4584 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4585 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4586 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4588 SCVAL(pdata
,1,perms
);
4591 case SMB_ACL_USER_OBJ
:
4592 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4593 own_grp
= (unsigned int)pst
->st_ex_uid
;
4594 SIVAL(pdata
,2,own_grp
);
4599 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4601 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4604 own_grp
= (unsigned int)*puid
;
4605 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4606 SIVAL(pdata
,2,own_grp
);
4610 case SMB_ACL_GROUP_OBJ
:
4611 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4612 own_grp
= (unsigned int)pst
->st_ex_gid
;
4613 SIVAL(pdata
,2,own_grp
);
4618 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4623 own_grp
= (unsigned int)*pgid
;
4624 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4625 SIVAL(pdata
,2,own_grp
);
4630 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4631 SIVAL(pdata
,2,0xFFFFFFFF);
4632 SIVAL(pdata
,6,0xFFFFFFFF);
4635 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4636 SIVAL(pdata
,2,0xFFFFFFFF);
4637 SIVAL(pdata
,6,0xFFFFFFFF);
4640 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4643 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4650 /****************************************************************************
4651 Store the FILE_UNIX_BASIC info.
4652 ****************************************************************************/
4654 static char *store_file_unix_basic(connection_struct
*conn
,
4657 const SMB_STRUCT_STAT
*psbuf
)
4661 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4662 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4664 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4667 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4670 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4671 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4672 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4675 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4679 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4683 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4686 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4687 devno
= psbuf
->st_ex_rdev
;
4689 devno
= psbuf
->st_ex_dev
;
4692 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4696 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4700 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
4703 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4707 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4714 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4715 * the chflags(2) (or equivalent) flags.
4717 * XXX: this really should be behind the VFS interface. To do this, we would
4718 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4719 * Each VFS module could then implement its own mapping as appropriate for the
4720 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4722 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4726 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4730 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4734 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4738 { UF_HIDDEN
, EXT_HIDDEN
},
4741 /* Do not remove. We need to guarantee that this array has at least one
4742 * entry to build on HP-UX.
4748 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4749 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4753 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4754 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4755 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4756 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4761 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4762 const uint32_t smb_fflags
,
4763 const uint32_t smb_fmask
,
4766 uint32_t max_fmask
= 0;
4769 *stat_fflags
= psbuf
->st_ex_flags
;
4771 /* For each flags requested in smb_fmask, check the state of the
4772 * corresponding flag in smb_fflags and set or clear the matching
4776 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4777 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4778 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4779 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4780 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4782 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4787 /* If smb_fmask is asking to set any bits that are not supported by
4788 * our flag mappings, we should fail.
4790 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4798 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4799 * of file flags and birth (create) time.
4801 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4804 const SMB_STRUCT_STAT
*psbuf
)
4806 uint32_t file_flags
= 0;
4807 uint32_t flags_mask
= 0;
4809 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4811 /* Create (birth) time 64 bit */
4812 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
4815 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4816 SIVAL(pdata
, 0, file_flags
); /* flags */
4817 SIVAL(pdata
, 4, flags_mask
); /* mask */
4823 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4824 const struct stream_struct
*streams
,
4826 unsigned int max_data_bytes
,
4827 unsigned int *data_size
)
4830 unsigned int ofs
= 0;
4832 if (max_data_bytes
< 32) {
4833 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4836 for (i
= 0; i
< num_streams
; i
++) {
4837 unsigned int next_offset
;
4839 smb_ucs2_t
*namebuf
;
4841 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4842 streams
[i
].name
, &namelen
) ||
4845 return NT_STATUS_INVALID_PARAMETER
;
4849 * name_buf is now null-terminated, we need to marshall as not
4856 * We cannot overflow ...
4858 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4859 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4861 TALLOC_FREE(namebuf
);
4862 return STATUS_BUFFER_OVERFLOW
;
4865 SIVAL(data
, ofs
+4, namelen
);
4866 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4867 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4868 memcpy(data
+ofs
+24, namebuf
, namelen
);
4869 TALLOC_FREE(namebuf
);
4871 next_offset
= ofs
+ 24 + namelen
;
4873 if (i
== num_streams
-1) {
4874 SIVAL(data
, ofs
, 0);
4877 unsigned int align
= ndr_align_size(next_offset
, 8);
4879 if ((next_offset
+ align
) > max_data_bytes
) {
4880 DEBUG(10, ("refusing to overflow align "
4881 "reply at stream %u\n",
4883 TALLOC_FREE(namebuf
);
4884 return STATUS_BUFFER_OVERFLOW
;
4887 memset(data
+next_offset
, 0, align
);
4888 next_offset
+= align
;
4890 SIVAL(data
, ofs
, next_offset
- ofs
);
4897 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4901 return NT_STATUS_OK
;
4904 static NTSTATUS
smb_unix_read_symlink(connection_struct
*conn
,
4905 struct smb_request
*req
,
4906 struct smb_filename
*smb_fname
,
4908 unsigned int data_size_in
,
4909 unsigned int *pdata_size_out
)
4914 struct smb_filename
*parent_fname
= NULL
;
4915 struct smb_filename
*base_name
= NULL
;
4917 char *buffer
= talloc_array(talloc_tos(), char, PATH_MAX
+1);
4920 return NT_STATUS_NO_MEMORY
;
4923 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
4924 smb_fname_str_dbg(smb_fname
));
4926 if(!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
4927 TALLOC_FREE(buffer
);
4928 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4931 status
= parent_pathref(talloc_tos(),
4936 if (!NT_STATUS_IS_OK(status
)) {
4937 TALLOC_FREE(buffer
);
4941 link_len
= SMB_VFS_READLINKAT(conn
,
4947 TALLOC_FREE(parent_fname
);
4949 if (link_len
== -1) {
4950 TALLOC_FREE(buffer
);
4951 return map_nt_error_from_unix(errno
);
4954 buffer
[link_len
] = 0;
4955 status
= srvstr_push(pdata
,
4962 TALLOC_FREE(buffer
);
4963 if (!NT_STATUS_IS_OK(status
)) {
4966 *pdata_size_out
= len
;
4968 return NT_STATUS_OK
;
4971 #if defined(HAVE_POSIX_ACLS)
4972 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
4973 struct smb_request
*req
,
4975 struct smb_filename
*smb_fname
,
4977 unsigned int data_size_in
,
4978 unsigned int *pdata_size_out
)
4980 SMB_ACL_T file_acl
= NULL
;
4981 SMB_ACL_T def_acl
= NULL
;
4982 uint16_t num_file_acls
= 0;
4983 uint16_t num_def_acls
= 0;
4984 unsigned int size_needed
= 0;
4987 bool close_fsp
= false;
4990 * Ensure we always operate on a file descriptor, not just
4993 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
4994 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
4995 FILE_READ_ATTRIBUTES
|
4996 FILE_WRITE_ATTRIBUTES
;
4998 status
= get_posix_fsp(conn
,
5004 if (!NT_STATUS_IS_OK(status
)) {
5010 SMB_ASSERT(fsp
!= NULL
);
5012 status
= refuse_symlink(conn
,
5015 if (!NT_STATUS_IS_OK(status
)) {
5019 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5022 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5023 DBG_INFO("ACLs not implemented on "
5024 "filesystem containing %s\n",
5026 status
= NT_STATUS_NOT_IMPLEMENTED
;
5030 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
5032 * We can only have default POSIX ACLs on
5035 if (!fsp
->fsp_flags
.is_directory
) {
5036 DBG_INFO("Non-directory open %s\n",
5038 status
= NT_STATUS_INVALID_HANDLE
;
5041 def_acl
= SMB_VFS_SYS_ACL_GET_FILE(conn
,
5043 SMB_ACL_TYPE_DEFAULT
,
5045 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5048 num_file_acls
= count_acl_entries(conn
, file_acl
);
5049 num_def_acls
= count_acl_entries(conn
, def_acl
);
5052 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
5053 status
= NT_STATUS_INVALID_PARAMETER
;
5057 size_needed
= num_file_acls
+ num_def_acls
;
5060 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5061 * than UINT_MAX, so check by division.
5063 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
5064 status
= NT_STATUS_INVALID_PARAMETER
;
5068 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
5069 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
5070 status
= NT_STATUS_INVALID_PARAMETER
;
5073 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
5075 if ( data_size_in
< size_needed
) {
5076 DBG_INFO("data_size too small (%u) need %u\n",
5079 status
= NT_STATUS_BUFFER_TOO_SMALL
;
5083 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5084 SSVAL(pdata
,2,num_file_acls
);
5085 SSVAL(pdata
,4,num_def_acls
);
5086 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
5088 ok
= marshall_posix_acl(conn
,
5093 status
= NT_STATUS_INTERNAL_ERROR
;
5096 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
5098 ok
= marshall_posix_acl(conn
,
5103 status
= NT_STATUS_INTERNAL_ERROR
;
5107 *pdata_size_out
= size_needed
;
5108 status
= NT_STATUS_OK
;
5114 * Ensure the stat struct in smb_fname is up to
5115 * date. Structure copy.
5117 smb_fname
->st
= fsp
->fsp_name
->st
;
5118 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
5122 TALLOC_FREE(file_acl
);
5123 TALLOC_FREE(def_acl
);
5128 /****************************************************************************
5129 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5130 ****************************************************************************/
5132 static void call_trans2qpipeinfo(connection_struct
*conn
,
5133 struct smb_request
*req
,
5134 unsigned int tran_call
,
5135 char **pparams
, int total_params
,
5136 char **ppdata
, int total_data
,
5137 unsigned int max_data_bytes
)
5139 char *params
= *pparams
;
5140 char *pdata
= *ppdata
;
5141 unsigned int data_size
= 0;
5142 unsigned int param_size
= 2;
5143 uint16_t info_level
;
5147 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5151 if (total_params
< 4) {
5152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5156 fsp
= file_fsp(req
, SVAL(params
,0));
5157 if (!fsp_is_np(fsp
)) {
5158 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5162 info_level
= SVAL(params
,2);
5164 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5165 if (*pparams
== NULL
) {
5166 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5171 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5172 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5175 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5176 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5177 if (*ppdata
== NULL
) {
5178 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5183 switch (info_level
) {
5184 case SMB_FILE_STANDARD_INFORMATION
:
5186 SOFF_T(pdata
,0,4096LL);
5193 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5197 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5203 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
5204 TALLOC_CTX
*mem_ctx
,
5205 struct smb_request
*req
,
5206 uint16_t info_level
,
5208 struct smb_filename
*smb_fname
,
5209 bool delete_pending
,
5210 struct timespec write_time_ts
,
5211 struct ea_list
*ea_list
,
5212 int lock_data_count
,
5215 unsigned int max_data_bytes
,
5216 size_t *fixed_portion
,
5218 unsigned int *pdata_size
)
5220 char *pdata
= *ppdata
;
5221 char *dstart
, *dend
;
5222 unsigned int data_size
;
5223 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
5224 time_t create_time
, mtime
, atime
, c_time
;
5225 SMB_STRUCT_STAT
*psbuf
= NULL
;
5232 uint64_t file_size
= 0;
5234 uint64_t allocation_size
= 0;
5235 uint64_t file_id
= 0;
5236 uint32_t access_mask
= 0;
5239 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5240 return NT_STATUS_INVALID_LEVEL
;
5243 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5244 smb_fname_str_dbg(smb_fname
),
5246 info_level
, max_data_bytes
));
5249 * In case of querying a symlink in POSIX context,
5250 * fsp will be NULL. fdos_mode() deals with it.
5253 smb_fname
= fsp
->fsp_name
;
5255 mode
= fdos_mode(fsp
);
5256 psbuf
= &smb_fname
->st
;
5258 nlink
= psbuf
->st_ex_nlink
;
5260 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
5264 if ((nlink
> 0) && delete_pending
) {
5268 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
5269 return NT_STATUS_INVALID_PARAMETER
;
5272 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
5273 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
5274 if (*ppdata
== NULL
) {
5275 return NT_STATUS_NO_MEMORY
;
5279 dend
= dstart
+ data_size
- 1;
5281 if (!is_omit_timespec(&write_time_ts
) &&
5282 !INFO_LEVEL_IS_UNIX(info_level
))
5284 update_stat_ex_mtime(psbuf
, write_time_ts
);
5287 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
5288 mtime_ts
= psbuf
->st_ex_mtime
;
5289 atime_ts
= psbuf
->st_ex_atime
;
5290 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
5292 if (lp_dos_filetime_resolution(SNUM(conn
))) {
5293 dos_filetime_timespec(&create_time_ts
);
5294 dos_filetime_timespec(&mtime_ts
);
5295 dos_filetime_timespec(&atime_ts
);
5296 dos_filetime_timespec(&ctime_ts
);
5299 create_time
= convert_timespec_to_time_t(create_time_ts
);
5300 mtime
= convert_timespec_to_time_t(mtime_ts
);
5301 atime
= convert_timespec_to_time_t(atime_ts
);
5302 c_time
= convert_timespec_to_time_t(ctime_ts
);
5304 p
= strrchr_m(smb_fname
->base_name
,'/');
5306 base_name
= smb_fname
->base_name
;
5310 /* NT expects the name to be in an exact form of the *full*
5311 filename. See the trans2 torture test */
5312 if (ISDOT(base_name
)) {
5313 dos_fname
= talloc_strdup(mem_ctx
, "\\");
5315 return NT_STATUS_NO_MEMORY
;
5318 dos_fname
= talloc_asprintf(mem_ctx
,
5320 smb_fname
->base_name
);
5322 return NT_STATUS_NO_MEMORY
;
5324 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5325 dos_fname
= talloc_asprintf(dos_fname
, "%s",
5326 smb_fname
->stream_name
);
5328 return NT_STATUS_NO_MEMORY
;
5332 string_replace(dos_fname
, '/', '\\');
5335 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
5337 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
5338 /* Do we have this path open ? */
5340 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
5341 fsp1
= file_find_di_first(conn
->sconn
, fileid
, true);
5342 if (fsp1
&& fsp1
->initial_allocation_size
) {
5343 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
5347 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
5348 file_size
= get_file_size_stat(psbuf
);
5352 pos
= fh_get_position_information(fsp
->fh
);
5356 access_mask
= fsp
->access_mask
;
5358 /* GENERIC_EXECUTE mapping from Windows */
5359 access_mask
= 0x12019F;
5362 /* This should be an index number - looks like
5365 I think this causes us to fail the IFSKIT
5366 BasicFileInformationTest. -tpot */
5367 file_id
= SMB_VFS_FS_FILE_ID(conn
, psbuf
);
5371 switch (info_level
) {
5372 case SMB_INFO_STANDARD
:
5373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5375 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
5376 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
5377 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
5378 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
5379 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
5380 SSVAL(pdata
,l1_attrFile
,mode
);
5383 case SMB_INFO_QUERY_EA_SIZE
:
5385 unsigned int ea_size
=
5386 estimate_ea_size(smb_fname
->fsp
);
5387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5389 srv_put_dos_date2(pdata
,0,create_time
);
5390 srv_put_dos_date2(pdata
,4,atime
);
5391 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
5392 SIVAL(pdata
,12,(uint32_t)file_size
);
5393 SIVAL(pdata
,16,(uint32_t)allocation_size
);
5394 SSVAL(pdata
,20,mode
);
5395 SIVAL(pdata
,22,ea_size
);
5399 case SMB_INFO_IS_NAME_VALID
:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5402 /* os/2 needs this ? really ?*/
5403 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
5405 /* This is only reached for qpathinfo */
5409 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5411 size_t total_ea_len
= 0;
5412 struct ea_list
*ea_file_list
= NULL
;
5413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5416 get_ea_list_from_fsp(mem_ctx
,
5418 &total_ea_len
, &ea_file_list
);
5419 if (!NT_STATUS_IS_OK(status
)) {
5423 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
5425 if (!ea_list
|| (total_ea_len
> data_size
)) {
5427 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5431 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5435 case SMB_INFO_QUERY_ALL_EAS
:
5437 /* We have data_size bytes to put EA's into. */
5438 size_t total_ea_len
= 0;
5439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5441 status
= get_ea_list_from_fsp(mem_ctx
,
5443 &total_ea_len
, &ea_list
);
5444 if (!NT_STATUS_IS_OK(status
)) {
5448 if (!ea_list
|| (total_ea_len
> data_size
)) {
5450 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5454 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5458 case SMB2_FILE_FULL_EA_INFORMATION
:
5460 /* We have data_size bytes to put EA's into. */
5461 size_t total_ea_len
= 0;
5462 struct ea_list
*ea_file_list
= NULL
;
5464 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5466 /*TODO: add filtering and index handling */
5469 get_ea_list_from_fsp(mem_ctx
,
5471 &total_ea_len
, &ea_file_list
);
5472 if (!NT_STATUS_IS_OK(status
)) {
5475 if (!ea_file_list
) {
5476 return NT_STATUS_NO_EAS_ON_FILE
;
5479 status
= fill_ea_chained_buffer(mem_ctx
,
5483 conn
, ea_file_list
);
5484 if (!NT_STATUS_IS_OK(status
)) {
5490 case SMB_FILE_BASIC_INFORMATION
:
5491 case SMB_QUERY_FILE_BASIC_INFO
:
5493 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
5494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5495 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
5497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5501 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5502 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5503 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5504 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5505 SIVAL(pdata
,32,mode
);
5507 DEBUG(5,("SMB_QFBI - "));
5508 DEBUG(5,("create: %s ", ctime(&create_time
)));
5509 DEBUG(5,("access: %s ", ctime(&atime
)));
5510 DEBUG(5,("write: %s ", ctime(&mtime
)));
5511 DEBUG(5,("change: %s ", ctime(&c_time
)));
5512 DEBUG(5,("mode: %x\n", mode
));
5513 *fixed_portion
= data_size
;
5516 case SMB_FILE_STANDARD_INFORMATION
:
5517 case SMB_QUERY_FILE_STANDARD_INFO
:
5519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5521 SOFF_T(pdata
,0,allocation_size
);
5522 SOFF_T(pdata
,8,file_size
);
5523 SIVAL(pdata
,16,nlink
);
5524 SCVAL(pdata
,20,delete_pending
?1:0);
5525 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5526 SSVAL(pdata
,22,0); /* Padding. */
5527 *fixed_portion
= 24;
5530 case SMB_FILE_EA_INFORMATION
:
5531 case SMB_QUERY_FILE_EA_INFO
:
5533 unsigned int ea_size
=
5534 estimate_ea_size(smb_fname
->fsp
);
5535 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5538 SIVAL(pdata
,0,ea_size
);
5542 /* Get the 8.3 name - used if NT SMB was negotiated. */
5543 case SMB_QUERY_FILE_ALT_NAME_INFO
:
5544 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
5546 char mangled_name
[13];
5547 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5548 if (!name_to_8_3(base_name
,mangled_name
,
5549 True
,conn
->params
)) {
5550 return NT_STATUS_NO_MEMORY
;
5552 status
= srvstr_push(dstart
, flags2
,
5553 pdata
+4, mangled_name
,
5554 PTR_DIFF(dend
, pdata
+4),
5556 if (!NT_STATUS_IS_OK(status
)) {
5559 data_size
= 4 + len
;
5565 case SMB_QUERY_FILE_NAME_INFO
:
5568 this must be *exactly* right for ACLs on mapped drives to work
5570 status
= srvstr_push(dstart
, flags2
,
5572 PTR_DIFF(dend
, pdata
+4),
5574 if (!NT_STATUS_IS_OK(status
)) {
5577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5578 data_size
= 4 + len
;
5583 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
5585 char *nfname
= NULL
;
5587 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
5588 return NT_STATUS_INVALID_LEVEL
;
5591 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
5592 if (nfname
== NULL
) {
5593 return NT_STATUS_NO_MEMORY
;
5596 if (ISDOT(nfname
)) {
5599 string_replace(nfname
, '/', '\\');
5601 if (smb_fname
->stream_name
!= NULL
) {
5602 const char *s
= smb_fname
->stream_name
;
5603 const char *e
= NULL
;
5606 SMB_ASSERT(s
[0] != '\0');
5609 * smb_fname->stream_name is in form
5610 * of ':StrEam:$DATA', but we should only
5611 * append ':StrEam' here.
5614 e
= strchr(&s
[1], ':');
5620 nfname
= talloc_strndup_append(nfname
, s
, n
);
5621 if (nfname
== NULL
) {
5622 return NT_STATUS_NO_MEMORY
;
5626 status
= srvstr_push(dstart
, flags2
,
5628 PTR_DIFF(dend
, pdata
+4),
5630 if (!NT_STATUS_IS_OK(status
)) {
5633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5634 data_size
= 4 + len
;
5640 case SMB_FILE_ALLOCATION_INFORMATION
:
5641 case SMB_QUERY_FILE_ALLOCATION_INFO
:
5642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5644 SOFF_T(pdata
,0,allocation_size
);
5647 case SMB_FILE_END_OF_FILE_INFORMATION
:
5648 case SMB_QUERY_FILE_END_OF_FILEINFO
:
5649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5651 SOFF_T(pdata
,0,file_size
);
5654 case SMB_QUERY_FILE_ALL_INFO
:
5655 case SMB_FILE_ALL_INFORMATION
:
5657 unsigned int ea_size
=
5658 estimate_ea_size(smb_fname
->fsp
);
5659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5660 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5661 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5662 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5663 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5664 SIVAL(pdata
,32,mode
);
5665 SIVAL(pdata
,36,0); /* padding. */
5667 SOFF_T(pdata
,0,allocation_size
);
5668 SOFF_T(pdata
,8,file_size
);
5669 SIVAL(pdata
,16,nlink
);
5670 SCVAL(pdata
,20,delete_pending
);
5671 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5674 SIVAL(pdata
,0,ea_size
);
5675 pdata
+= 4; /* EA info */
5676 status
= srvstr_push(dstart
, flags2
,
5678 PTR_DIFF(dend
, pdata
+4),
5680 if (!NT_STATUS_IS_OK(status
)) {
5685 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5686 *fixed_portion
= 10;
5690 case SMB2_FILE_ALL_INFORMATION
:
5692 unsigned int ea_size
=
5693 estimate_ea_size(smb_fname
->fsp
);
5694 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5695 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
5696 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
5697 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
5698 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
5699 SIVAL(pdata
, 0x20, mode
);
5700 SIVAL(pdata
, 0x24, 0); /* padding. */
5701 SBVAL(pdata
, 0x28, allocation_size
);
5702 SBVAL(pdata
, 0x30, file_size
);
5703 SIVAL(pdata
, 0x38, nlink
);
5704 SCVAL(pdata
, 0x3C, delete_pending
);
5705 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5706 SSVAL(pdata
, 0x3E, 0); /* padding */
5707 SBVAL(pdata
, 0x40, file_id
);
5708 SIVAL(pdata
, 0x48, ea_size
);
5709 SIVAL(pdata
, 0x4C, access_mask
);
5710 SBVAL(pdata
, 0x50, pos
);
5711 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5712 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5716 status
= srvstr_push(dstart
, flags2
,
5718 PTR_DIFF(dend
, pdata
+4),
5720 if (!NT_STATUS_IS_OK(status
)) {
5725 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5726 *fixed_portion
= 104;
5729 case SMB_FILE_INTERNAL_INFORMATION
:
5731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5732 SBVAL(pdata
, 0, file_id
);
5737 case SMB_FILE_ACCESS_INFORMATION
:
5738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5739 SIVAL(pdata
, 0, access_mask
);
5744 case SMB_FILE_NAME_INFORMATION
:
5745 /* Pathname with leading '\'. */
5748 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5750 SIVAL(pdata
,0,byte_len
);
5751 data_size
= 4 + byte_len
;
5755 case SMB_FILE_DISPOSITION_INFORMATION
:
5756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5758 SCVAL(pdata
,0,delete_pending
);
5762 case SMB_FILE_POSITION_INFORMATION
:
5763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5765 SOFF_T(pdata
,0,pos
);
5769 case SMB_FILE_MODE_INFORMATION
:
5770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5771 SIVAL(pdata
,0,mode
);
5776 case SMB_FILE_ALIGNMENT_INFORMATION
:
5777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5778 SIVAL(pdata
,0,0); /* No alignment needed. */
5784 * NT4 server just returns "invalid query" to this - if we try
5785 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5788 /* The first statement above is false - verified using Thursby
5789 * client against NT4 -- gcolley.
5791 case SMB_QUERY_FILE_STREAM_INFO
:
5792 case SMB_FILE_STREAM_INFORMATION
: {
5793 unsigned int num_streams
= 0;
5794 struct stream_struct
*streams
= NULL
;
5796 DEBUG(10,("smbd_do_qfilepathinfo: "
5797 "SMB_FILE_STREAM_INFORMATION\n"));
5799 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5800 return NT_STATUS_INVALID_PARAMETER
;
5803 status
= vfs_streaminfo(conn
,
5810 if (!NT_STATUS_IS_OK(status
)) {
5811 DEBUG(10, ("could not get stream info: %s\n",
5812 nt_errstr(status
)));
5816 status
= marshall_stream_info(num_streams
, streams
,
5817 pdata
, max_data_bytes
,
5820 if (!NT_STATUS_IS_OK(status
)) {
5821 DEBUG(10, ("marshall_stream_info failed: %s\n",
5822 nt_errstr(status
)));
5823 TALLOC_FREE(streams
);
5827 TALLOC_FREE(streams
);
5829 *fixed_portion
= 32;
5833 case SMB_QUERY_COMPRESSION_INFO
:
5834 case SMB_FILE_COMPRESSION_INFORMATION
:
5835 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5836 SOFF_T(pdata
,0,file_size
);
5837 SIVAL(pdata
,8,0); /* ??? */
5838 SIVAL(pdata
,12,0); /* ??? */
5840 *fixed_portion
= 16;
5843 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5845 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
5846 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
5847 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
5848 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
5849 SOFF_T(pdata
,32,allocation_size
);
5850 SOFF_T(pdata
,40,file_size
);
5851 SIVAL(pdata
,48,mode
);
5852 SIVAL(pdata
,52,0); /* ??? */
5854 *fixed_portion
= 56;
5857 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5858 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5859 SIVAL(pdata
,0,mode
);
5866 * CIFS UNIX Extensions.
5869 case SMB_QUERY_FILE_UNIX_BASIC
:
5871 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5872 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5874 DEBUG(4,("smbd_do_qfilepathinfo: "
5875 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5876 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5880 case SMB_QUERY_FILE_UNIX_INFO2
:
5882 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5883 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5887 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5889 for (i
=0; i
<100; i
++)
5890 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5896 case SMB_QUERY_FILE_UNIX_LINK
:
5898 status
= smb_unix_read_symlink(conn
,
5904 if (!NT_STATUS_IS_OK(status
)) {
5910 #if defined(HAVE_POSIX_ACLS)
5911 case SMB_QUERY_POSIX_ACL
:
5913 status
= smb_query_posix_acl(conn
,
5920 if (!NT_STATUS_IS_OK(status
)) {
5928 case SMB_QUERY_POSIX_LOCK
:
5933 enum brl_type lock_type
;
5935 /* We need an open file with a real fd for this. */
5937 fsp
->fsp_flags
.is_pathref
||
5938 fsp_get_io_fd(fsp
) == -1)
5940 return NT_STATUS_INVALID_LEVEL
;
5943 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5944 return NT_STATUS_INVALID_PARAMETER
;
5947 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5948 case POSIX_LOCK_TYPE_READ
:
5949 lock_type
= READ_LOCK
;
5951 case POSIX_LOCK_TYPE_WRITE
:
5952 lock_type
= WRITE_LOCK
;
5954 case POSIX_LOCK_TYPE_UNLOCK
:
5956 /* There's no point in asking for an unlock... */
5957 return NT_STATUS_INVALID_PARAMETER
;
5960 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5961 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5962 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5964 status
= query_lock(fsp
,
5971 if (ERROR_WAS_LOCK_DENIED(status
)) {
5972 /* Here we need to report who has it locked... */
5973 data_size
= POSIX_LOCK_DATA_SIZE
;
5975 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5976 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5977 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5978 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5979 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5981 } else if (NT_STATUS_IS_OK(status
)) {
5982 /* For success we just return a copy of what we sent
5983 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5984 data_size
= POSIX_LOCK_DATA_SIZE
;
5985 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5986 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5994 return NT_STATUS_INVALID_LEVEL
;
5997 *pdata_size
= data_size
;
5998 return NT_STATUS_OK
;
6001 /****************************************************************************
6002 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6003 file name or file id).
6004 ****************************************************************************/
6006 static void call_trans2qfilepathinfo(connection_struct
*conn
,
6007 struct smb_request
*req
,
6008 unsigned int tran_call
,
6009 char **pparams
, int total_params
,
6010 char **ppdata
, int total_data
,
6011 unsigned int max_data_bytes
)
6013 char *params
= *pparams
;
6014 char *pdata
= *ppdata
;
6015 uint16_t info_level
;
6016 unsigned int data_size
= 0;
6017 unsigned int param_size
= 2;
6018 struct smb_filename
*smb_fname
= NULL
;
6019 bool delete_pending
= False
;
6020 struct timespec write_time_ts
;
6021 files_struct
*fsp
= NULL
;
6022 struct file_id fileid
;
6023 struct ea_list
*ea_list
= NULL
;
6024 int lock_data_count
= 0;
6025 char *lock_data
= NULL
;
6026 size_t fixed_portion
;
6027 NTSTATUS status
= NT_STATUS_OK
;
6030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6034 ZERO_STRUCT(write_time_ts
);
6036 if (tran_call
== TRANSACT2_QFILEINFO
) {
6037 if (total_params
< 4) {
6038 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6043 call_trans2qpipeinfo(conn
, req
, tran_call
,
6044 pparams
, total_params
,
6050 fsp
= file_fsp(req
, SVAL(params
,0));
6051 info_level
= SVAL(params
,2);
6053 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
6055 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
6056 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6060 /* Initial check for valid fsp ptr. */
6061 if (!check_fsp_open(conn
, req
, fsp
)) {
6065 smb_fname
= fsp
->fsp_name
;
6067 if(fsp
->fake_file_handle
) {
6069 * This is actually for the QUOTA_FAKE_FILE --metze
6072 /* We know this name is ok, it's already passed the checks. */
6074 } else if(fsp_get_pathref_fd(fsp
) == -1) {
6076 * This is actually a QFILEINFO on a directory
6077 * handle (returned from an NT SMB). NT5.0 seems
6078 * to do this call. JRA.
6081 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6082 /* Always do lstat for UNIX calls. */
6083 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
6084 DEBUG(3,("call_trans2qfilepathinfo: "
6085 "SMB_VFS_LSTAT of %s failed "
6087 smb_fname_str_dbg(smb_fname
),
6090 map_nt_error_from_unix(errno
));
6093 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
6094 DEBUG(3,("call_trans2qfilepathinfo: "
6095 "SMB_VFS_STAT of %s failed (%s)\n",
6096 smb_fname_str_dbg(smb_fname
),
6099 map_nt_error_from_unix(errno
));
6103 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6104 fileid
= vfs_file_id_from_sbuf(
6105 conn
, &smb_fname
->st
);
6106 get_file_infos(fileid
, fsp
->name_hash
,
6112 * Original code - this is an open file.
6114 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
6115 DEBUG(3, ("fstat of %s failed (%s)\n",
6116 fsp_fnum_dbg(fsp
), strerror(errno
)));
6118 map_nt_error_from_unix(errno
));
6121 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6122 fileid
= vfs_file_id_from_sbuf(
6123 conn
, &smb_fname
->st
);
6124 get_file_infos(fileid
, fsp
->name_hash
,
6133 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6136 if (total_params
< 7) {
6137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6141 info_level
= SVAL(params
,0);
6143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
6145 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6146 if (!lp_unix_extensions()) {
6147 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6152 if (req
->posix_pathnames
) {
6153 srvstr_get_path_posix(req
,
6162 srvstr_get_path(req
,
6171 if (!NT_STATUS_IS_OK(status
)) {
6172 reply_nterror(req
, status
);
6176 status
= filename_convert(req
,
6182 if (!NT_STATUS_IS_OK(status
)) {
6183 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6184 reply_botherror(req
,
6185 NT_STATUS_PATH_NOT_COVERED
,
6186 ERRSRV
, ERRbadpath
);
6189 reply_nterror(req
, status
);
6194 * smb_fname->fsp may be NULL if smb_fname points at a symlink
6195 * and we're in POSIX context, so be careful when using fsp
6196 * below, it can still be NULL.
6198 fsp
= smb_fname
->fsp
;
6200 /* If this is a stream, check if there is a delete_pending. */
6201 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
6202 && is_ntfs_stream_smb_fname(smb_fname
)) {
6203 struct smb_filename
*smb_fname_base
;
6205 /* Create an smb_filename with stream_name == NULL. */
6206 smb_fname_base
= synthetic_smb_fname(
6208 smb_fname
->base_name
,
6213 if (smb_fname_base
== NULL
) {
6214 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6218 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6219 /* Always do lstat for UNIX calls. */
6220 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
6221 DEBUG(3,("call_trans2qfilepathinfo: "
6222 "SMB_VFS_LSTAT of %s failed "
6224 smb_fname_str_dbg(smb_fname_base
),
6226 TALLOC_FREE(smb_fname_base
);
6228 map_nt_error_from_unix(errno
));
6232 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
6233 DEBUG(3,("call_trans2qfilepathinfo: "
6234 "fileinfo of %s failed "
6236 smb_fname_str_dbg(smb_fname_base
),
6238 TALLOC_FREE(smb_fname_base
);
6240 map_nt_error_from_unix(errno
));
6245 status
= file_name_hash(conn
,
6246 smb_fname_str_dbg(smb_fname_base
),
6248 if (!NT_STATUS_IS_OK(status
)) {
6249 TALLOC_FREE(smb_fname_base
);
6250 reply_nterror(req
, status
);
6254 fileid
= vfs_file_id_from_sbuf(conn
,
6255 &smb_fname_base
->st
);
6256 TALLOC_FREE(smb_fname_base
);
6257 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
6258 if (delete_pending
) {
6259 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6264 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
6265 /* Always do lstat for UNIX calls. */
6266 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
6267 DEBUG(3,("call_trans2qfilepathinfo: "
6268 "SMB_VFS_LSTAT of %s failed (%s)\n",
6269 smb_fname_str_dbg(smb_fname
),
6272 map_nt_error_from_unix(errno
));
6277 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
6278 DEBUG(3,("call_trans2qfilepathinfo: "
6279 "SMB_VFS_STAT of %s failed (%s)\n",
6280 smb_fname_str_dbg(smb_fname
),
6283 map_nt_error_from_unix(errno
));
6288 status
= file_name_hash(conn
,
6289 smb_fname_str_dbg(smb_fname
),
6291 if (!NT_STATUS_IS_OK(status
)) {
6292 reply_nterror(req
, status
);
6296 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn
))) {
6297 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
6298 get_file_infos(fileid
, name_hash
, &delete_pending
,
6302 if (delete_pending
) {
6303 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
6308 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6309 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
6311 info_level
,tran_call
,total_data
));
6313 /* Pull out any data sent here before we realloc. */
6314 switch (info_level
) {
6315 case SMB_INFO_QUERY_EAS_FROM_LIST
:
6317 /* Pull any EA list from the data portion. */
6320 if (total_data
< 4) {
6322 req
, NT_STATUS_INVALID_PARAMETER
);
6325 ea_size
= IVAL(pdata
,0);
6327 if (total_data
> 0 && ea_size
!= total_data
) {
6328 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6329 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
6331 req
, NT_STATUS_INVALID_PARAMETER
);
6335 if (!lp_ea_support(SNUM(conn
))) {
6336 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
6340 /* Pull out the list of names. */
6341 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
6344 req
, NT_STATUS_INVALID_PARAMETER
);
6350 case SMB_QUERY_POSIX_LOCK
:
6353 fsp
->fsp_flags
.is_pathref
||
6354 fsp_get_io_fd(fsp
) == -1)
6356 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6360 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6362 req
, NT_STATUS_INVALID_PARAMETER
);
6366 /* Copy the lock range data. */
6367 lock_data
= (char *)talloc_memdup(
6368 req
, pdata
, total_data
);
6370 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6373 lock_data_count
= total_data
;
6380 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6381 if (*pparams
== NULL
) {
6382 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6389 * draft-leach-cifs-v1-spec-02.txt
6390 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6393 * The requested information is placed in the Data portion of the
6394 * transaction response. For the information levels greater than 0x100,
6395 * the transaction response has 1 parameter word which should be
6396 * ignored by the client.
6398 * However Windows only follows this rule for the IS_NAME_VALID call.
6400 switch (info_level
) {
6401 case SMB_INFO_IS_NAME_VALID
:
6406 if ((info_level
& SMB2_INFO_SPECIAL
) == SMB2_INFO_SPECIAL
) {
6408 * We use levels that start with 0xFF00
6409 * internally to represent SMB2 specific levels
6411 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6415 status
= smbd_do_qfilepathinfo(conn
, req
, req
, info_level
,
6417 delete_pending
, write_time_ts
,
6419 lock_data_count
, lock_data
,
6420 req
->flags2
, max_data_bytes
,
6422 ppdata
, &data_size
);
6423 if (!NT_STATUS_IS_OK(status
)) {
6424 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6425 /* We have re-scheduled this call. */
6428 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6429 bool ok
= defer_smb1_sharing_violation(req
);
6434 reply_nterror(req
, status
);
6437 if (fixed_portion
> max_data_bytes
) {
6438 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
6442 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
6448 /****************************************************************************
6449 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6451 ****************************************************************************/
6453 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
6454 connection_struct
*conn
,
6455 struct smb_request
*req
,
6456 bool overwrite_if_exists
,
6457 const struct smb_filename
*smb_fname_old
,
6458 struct smb_filename
*smb_fname_new
)
6460 NTSTATUS status
= NT_STATUS_OK
;
6463 struct smb_filename
*parent_fname_old
= NULL
;
6464 struct smb_filename
*base_name_old
= NULL
;
6465 struct smb_filename
*parent_fname_new
= NULL
;
6466 struct smb_filename
*base_name_new
= NULL
;
6468 /* source must already exist. */
6469 if (!VALID_STAT(smb_fname_old
->st
)) {
6470 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6474 /* No links from a directory. */
6475 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
6476 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
6480 /* Setting a hardlink to/from a stream isn't currently supported. */
6481 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
6483 DBG_DEBUG("Old name has streams\n");
6484 status
= NT_STATUS_INVALID_PARAMETER
;
6487 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
6489 DBG_DEBUG("New name has streams\n");
6490 status
= NT_STATUS_INVALID_PARAMETER
;
6494 status
= parent_pathref(talloc_tos(),
6499 if (!NT_STATUS_IS_OK(status
)) {
6503 status
= parent_pathref(talloc_tos(),
6508 if (!NT_STATUS_IS_OK(status
)) {
6512 if (VALID_STAT(smb_fname_new
->st
)) {
6513 if (overwrite_if_exists
) {
6514 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
6515 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
6518 status
= unlink_internals(conn
,
6520 FILE_ATTRIBUTE_NORMAL
,
6523 if (!NT_STATUS_IS_OK(status
)) {
6527 /* Disallow if newname already exists. */
6528 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6533 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6534 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
6536 ret
= SMB_VFS_LINKAT(conn
,
6537 parent_fname_old
->fsp
,
6539 parent_fname_new
->fsp
,
6544 status
= map_nt_error_from_unix(errno
);
6545 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6546 nt_errstr(status
), smb_fname_old
->base_name
,
6547 smb_fname_new
->base_name
));
6552 TALLOC_FREE(parent_fname_old
);
6553 TALLOC_FREE(parent_fname_new
);
6557 /****************************************************************************
6558 Deal with setting the time from any of the setfilepathinfo functions.
6559 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6560 calling this function.
6561 ****************************************************************************/
6563 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
6565 struct smb_filename
*smb_fname
,
6566 struct smb_file_time
*ft
,
6567 bool setting_write_time
)
6569 struct files_struct
*set_fsp
= NULL
;
6570 struct timeval_buf tbuf
[4];
6572 FILE_NOTIFY_CHANGE_LAST_ACCESS
6573 |FILE_NOTIFY_CHANGE_LAST_WRITE
6574 |FILE_NOTIFY_CHANGE_CREATION
;
6577 if (!VALID_STAT(smb_fname
->st
)) {
6578 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6583 return NT_STATUS_OK
;
6586 set_fsp
= fsp
->base_fsp
== NULL
? fsp
: fsp
->base_fsp
;
6588 /* get some defaults (no modifications) if any info is zero or -1. */
6589 if (is_omit_timespec(&ft
->create_time
)) {
6590 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
6593 if (is_omit_timespec(&ft
->atime
)) {
6594 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
6597 if (is_omit_timespec(&ft
->mtime
)) {
6598 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6601 if (!setting_write_time
) {
6602 /* ft->mtime comes from change time, not write time. */
6603 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6606 /* Ensure the resolution is the correct for
6607 * what we can store on this filesystem. */
6609 round_timespec(conn
->ts_res
, &ft
->create_time
);
6610 round_timespec(conn
->ts_res
, &ft
->ctime
);
6611 round_timespec(conn
->ts_res
, &ft
->atime
);
6612 round_timespec(conn
->ts_res
, &ft
->mtime
);
6614 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6615 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
6616 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6617 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
6618 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6619 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
6620 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6621 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
6623 if (setting_write_time
) {
6625 * This was a Windows setfileinfo on an open file.
6626 * NT does this a lot. We also need to
6627 * set the time here, as it can be read by
6628 * FindFirst/FindNext and with the patch for bug #2045
6629 * in smbd/fileio.c it ensures that this timestamp is
6630 * kept sticky even after a write. We save the request
6631 * away and will set it on file close and after a write. JRA.
6634 DBG_DEBUG("setting pending modtime to %s\n",
6635 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
6637 if (set_fsp
!= NULL
) {
6638 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
6640 set_sticky_write_time_path(
6641 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
6646 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6648 ret
= file_ntimes(conn
, set_fsp
->fsp_name
, ft
);
6650 return map_nt_error_from_unix(errno
);
6653 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
6654 smb_fname
->base_name
);
6655 return NT_STATUS_OK
;
6658 /****************************************************************************
6659 Deal with setting the dosmode from any of the setfilepathinfo functions.
6660 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6661 done before calling this function.
6662 ****************************************************************************/
6664 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
6665 struct files_struct
*fsp
,
6666 struct smb_filename
*smb_fname
,
6669 struct smb_filename
*smb_fname_base
;
6672 if (!VALID_STAT(smb_fname
->st
)) {
6673 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6676 /* Always operate on the base_name, even if a stream was passed in. */
6677 smb_fname_base
= synthetic_smb_fname(talloc_tos(),
6678 smb_fname
->base_name
,
6683 if (smb_fname_base
== NULL
) {
6684 return NT_STATUS_NO_MEMORY
;
6688 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6689 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6691 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6695 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6697 /* check the mode isn't different, before changing it */
6698 if ((dosmode
!= 0) && (dosmode
!= fdos_mode(fsp
))) {
6699 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6700 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6701 (unsigned int)dosmode
));
6703 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6705 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6707 smb_fname_str_dbg(smb_fname_base
),
6709 status
= map_nt_error_from_unix(errno
);
6713 status
= NT_STATUS_OK
;
6715 TALLOC_FREE(smb_fname_base
);
6719 /****************************************************************************
6720 Deal with setting the size from any of the setfilepathinfo functions.
6721 ****************************************************************************/
6723 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6724 struct smb_request
*req
,
6726 struct smb_filename
*smb_fname
,
6727 const SMB_STRUCT_STAT
*psbuf
,
6729 bool fail_after_createfile
)
6731 NTSTATUS status
= NT_STATUS_OK
;
6732 files_struct
*new_fsp
= NULL
;
6734 if (!VALID_STAT(*psbuf
)) {
6735 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6738 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
6740 get_file_size_stat(psbuf
));
6742 if (size
== get_file_size_stat(psbuf
)) {
6744 return NT_STATUS_OK
;
6746 if (!fsp
->fsp_flags
.modified
) {
6747 return NT_STATUS_OK
;
6749 trigger_write_time_update_immediate(fsp
);
6750 return NT_STATUS_OK
;
6753 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6754 smb_fname_str_dbg(smb_fname
), (double)size
));
6757 !fsp
->fsp_flags
.is_pathref
&&
6758 fsp_get_io_fd(fsp
) != -1)
6760 /* Handle based call. */
6761 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6762 return NT_STATUS_ACCESS_DENIED
;
6765 if (vfs_set_filelen(fsp
, size
) == -1) {
6766 return map_nt_error_from_unix(errno
);
6768 trigger_write_time_update_immediate(fsp
);
6769 return NT_STATUS_OK
;
6772 status
= SMB_VFS_CREATE_FILE(
6775 smb_fname
, /* fname */
6776 FILE_WRITE_DATA
, /* access_mask */
6777 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6779 FILE_OPEN
, /* create_disposition*/
6780 0, /* create_options */
6781 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6782 0, /* oplock_request */
6784 0, /* allocation_size */
6785 0, /* private_flags */
6788 &new_fsp
, /* result */
6790 NULL
, NULL
); /* create context */
6792 if (!NT_STATUS_IS_OK(status
)) {
6793 /* NB. We check for open_was_deferred in the caller. */
6797 /* See RAW-SFILEINFO-END-OF-FILE */
6798 if (fail_after_createfile
) {
6799 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6800 return NT_STATUS_INVALID_LEVEL
;
6803 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6804 status
= map_nt_error_from_unix(errno
);
6805 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6809 trigger_write_time_update_immediate(new_fsp
);
6810 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6811 return NT_STATUS_OK
;
6814 /****************************************************************************
6815 Deal with SMB_INFO_SET_EA.
6816 ****************************************************************************/
6818 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6822 struct smb_filename
*smb_fname
)
6824 struct ea_list
*ea_list
= NULL
;
6825 TALLOC_CTX
*ctx
= NULL
;
6826 NTSTATUS status
= NT_STATUS_OK
;
6828 if (total_data
< 10) {
6830 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6831 length. They seem to have no effect. Bug #3212. JRA */
6833 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6834 /* We're done. We only get EA info in this call. */
6835 return NT_STATUS_OK
;
6838 return NT_STATUS_INVALID_PARAMETER
;
6841 if (IVAL(pdata
,0) > total_data
) {
6842 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6843 IVAL(pdata
,0), (unsigned int)total_data
));
6844 return NT_STATUS_INVALID_PARAMETER
;
6848 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6850 return NT_STATUS_INVALID_PARAMETER
;
6855 * The only way fsp can be NULL here is if
6856 * smb_fname points at a symlink and
6857 * and we're in POSIX context.
6858 * Ensure this is the case.
6860 * There is still a race condition in that
6861 * the symlink could be changed after we
6862 * checked it, so ensure we only operate
6863 * EA setting on a file handle.
6865 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
6866 if (!(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
)) {
6867 return NT_STATUS_ACCESS_DENIED
;
6869 status
= refuse_symlink(conn
, NULL
, smb_fname
);
6870 SMB_ASSERT(NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
));
6871 return NT_STATUS_ACCESS_DENIED
;
6874 status
= set_ea(conn
, fsp
, ea_list
);
6879 /****************************************************************************
6880 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6881 ****************************************************************************/
6883 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6888 struct ea_list
*ea_list
= NULL
;
6892 return NT_STATUS_INVALID_HANDLE
;
6895 if (!lp_ea_support(SNUM(conn
))) {
6896 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6897 "EA's not supported.\n",
6898 (unsigned int)total_data
));
6899 return NT_STATUS_EAS_NOT_SUPPORTED
;
6902 if (total_data
< 10) {
6903 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6905 (unsigned int)total_data
));
6906 return NT_STATUS_INVALID_PARAMETER
;
6909 ea_list
= read_nttrans_ea_list(talloc_tos(),
6914 return NT_STATUS_INVALID_PARAMETER
;
6917 status
= set_ea(conn
, fsp
, ea_list
);
6919 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6920 smb_fname_str_dbg(fsp
->fsp_name
),
6921 nt_errstr(status
) ));
6927 /****************************************************************************
6928 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6929 ****************************************************************************/
6931 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6935 struct smb_filename
*smb_fname
)
6937 NTSTATUS status
= NT_STATUS_OK
;
6938 bool delete_on_close
;
6939 uint32_t dosmode
= 0;
6941 if (total_data
< 1) {
6942 return NT_STATUS_INVALID_PARAMETER
;
6946 return NT_STATUS_INVALID_HANDLE
;
6949 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6950 dosmode
= fdos_mode(fsp
);
6952 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6953 "delete_on_close = %u\n",
6954 smb_fname_str_dbg(smb_fname
),
6955 (unsigned int)dosmode
,
6956 (unsigned int)delete_on_close
));
6958 if (delete_on_close
) {
6959 status
= can_set_delete_on_close(fsp
, dosmode
);
6960 if (!NT_STATUS_IS_OK(status
)) {
6965 /* The set is across all open files on this dev/inode pair. */
6966 if (!set_delete_on_close(fsp
, delete_on_close
,
6967 conn
->session_info
->security_token
,
6968 conn
->session_info
->unix_token
)) {
6969 return NT_STATUS_ACCESS_DENIED
;
6971 return NT_STATUS_OK
;
6974 /****************************************************************************
6975 Deal with SMB_FILE_POSITION_INFORMATION.
6976 ****************************************************************************/
6978 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6983 uint64_t position_information
;
6985 if (total_data
< 8) {
6986 return NT_STATUS_INVALID_PARAMETER
;
6990 /* Ignore on pathname based set. */
6991 return NT_STATUS_OK
;
6994 position_information
= (uint64_t)IVAL(pdata
,0);
6995 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6997 DEBUG(10,("smb_file_position_information: Set file position "
6998 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6999 (double)position_information
));
7000 fh_set_position_information(fsp
->fh
, position_information
);
7001 return NT_STATUS_OK
;
7004 /****************************************************************************
7005 Deal with SMB_FILE_MODE_INFORMATION.
7006 ****************************************************************************/
7008 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
7014 if (total_data
< 4) {
7015 return NT_STATUS_INVALID_PARAMETER
;
7017 mode
= IVAL(pdata
,0);
7018 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
7019 return NT_STATUS_INVALID_PARAMETER
;
7021 return NT_STATUS_OK
;
7024 /****************************************************************************
7025 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
7026 ****************************************************************************/
7028 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
7029 struct smb_request
*req
,
7032 struct smb_filename
*new_smb_fname
)
7034 char *link_target
= NULL
;
7035 struct smb_filename target_fname
;
7036 TALLOC_CTX
*ctx
= talloc_tos();
7039 struct smb_filename
*parent_fname
= NULL
;
7040 struct smb_filename
*base_name
= NULL
;
7042 /* Set a symbolic link. */
7043 /* Don't allow this if follow links is false. */
7045 if (total_data
== 0) {
7046 return NT_STATUS_INVALID_PARAMETER
;
7049 if (!lp_follow_symlinks(SNUM(conn
))) {
7050 return NT_STATUS_ACCESS_DENIED
;
7053 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
7054 total_data
, STR_TERMINATE
);
7057 return NT_STATUS_INVALID_PARAMETER
;
7060 target_fname
= (struct smb_filename
) {
7061 .base_name
= link_target
,
7064 /* Removes @GMT tokens if any */
7065 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
7066 if (!NT_STATUS_IS_OK(status
)) {
7070 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7071 new_smb_fname
->base_name
, link_target
));
7073 status
= parent_pathref(talloc_tos(),
7078 if (!NT_STATUS_IS_OK(status
)) {
7082 ret
= SMB_VFS_SYMLINKAT(conn
,
7087 TALLOC_FREE(parent_fname
);
7088 return map_nt_error_from_unix(errno
);
7091 TALLOC_FREE(parent_fname
);
7092 return NT_STATUS_OK
;
7095 /****************************************************************************
7096 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7097 ****************************************************************************/
7099 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
7100 struct smb_request
*req
,
7101 const char *pdata
, int total_data
,
7102 struct smb_filename
*smb_fname_new
)
7104 char *oldname
= NULL
;
7105 struct smb_filename
*smb_fname_old
= NULL
;
7106 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7107 TALLOC_CTX
*ctx
= talloc_tos();
7108 NTSTATUS status
= NT_STATUS_OK
;
7110 /* Set a hard link. */
7111 if (total_data
== 0) {
7112 return NT_STATUS_INVALID_PARAMETER
;
7115 if (req
->posix_pathnames
) {
7116 srvstr_get_path_posix(ctx
,
7125 srvstr_get_path(ctx
,
7134 if (!NT_STATUS_IS_OK(status
)) {
7138 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7139 smb_fname_str_dbg(smb_fname_new
), oldname
));
7141 status
= filename_convert(ctx
,
7147 if (!NT_STATUS_IS_OK(status
)) {
7151 return hardlink_internals(ctx
, conn
, req
, false,
7152 smb_fname_old
, smb_fname_new
);
7155 /****************************************************************************
7156 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7157 ****************************************************************************/
7159 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
7160 struct smb_request
*req
,
7164 struct smb_filename
*smb_fname_src
)
7168 char *newname
= NULL
;
7169 struct smb_filename
*smb_fname_dst
= NULL
;
7170 const char *dst_original_lcomp
= NULL
;
7171 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7172 NTSTATUS status
= NT_STATUS_OK
;
7173 TALLOC_CTX
*ctx
= talloc_tos();
7176 return NT_STATUS_INVALID_HANDLE
;
7179 if (total_data
< 20) {
7180 return NT_STATUS_INVALID_PARAMETER
;
7183 overwrite
= (CVAL(pdata
,0) ? True
: False
);
7184 len
= IVAL(pdata
,16);
7186 if (len
> (total_data
- 20) || (len
== 0)) {
7187 return NT_STATUS_INVALID_PARAMETER
;
7190 if (req
->posix_pathnames
) {
7191 srvstr_get_path_posix(ctx
,
7200 srvstr_get_path(ctx
,
7209 if (!NT_STATUS_IS_OK(status
)) {
7213 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7216 status
= filename_convert(ctx
,
7222 if (!NT_STATUS_IS_OK(status
)) {
7226 if (fsp
->base_fsp
) {
7227 /* newname must be a stream name. */
7228 if (newname
[0] != ':') {
7229 return NT_STATUS_NOT_SUPPORTED
;
7232 /* Create an smb_fname to call rename_internals_fsp() with. */
7233 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7234 fsp
->base_fsp
->fsp_name
->base_name
,
7237 fsp
->base_fsp
->fsp_name
->twrp
,
7238 fsp
->base_fsp
->fsp_name
->flags
);
7239 if (smb_fname_dst
== NULL
) {
7240 status
= NT_STATUS_NO_MEMORY
;
7246 * Set the original last component, since
7247 * rename_internals_fsp() requires it.
7249 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7253 if (dst_original_lcomp
== NULL
) {
7254 status
= NT_STATUS_NO_MEMORY
;
7258 DEBUG(10,("smb2_file_rename_information: "
7259 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7260 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7261 smb_fname_str_dbg(smb_fname_dst
)));
7262 status
= rename_internals_fsp(conn
,
7266 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
7270 TALLOC_FREE(smb_fname_dst
);
7274 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
7275 struct smb_request
*req
,
7279 struct smb_filename
*smb_fname_src
)
7283 char *newname
= NULL
;
7284 struct smb_filename
*smb_fname_dst
= NULL
;
7285 NTSTATUS status
= NT_STATUS_OK
;
7286 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7287 TALLOC_CTX
*ctx
= talloc_tos();
7290 return NT_STATUS_INVALID_HANDLE
;
7293 if (total_data
< 20) {
7294 return NT_STATUS_INVALID_PARAMETER
;
7297 overwrite
= (CVAL(pdata
,0) ? true : false);
7298 len
= IVAL(pdata
,16);
7300 if (len
> (total_data
- 20) || (len
== 0)) {
7301 return NT_STATUS_INVALID_PARAMETER
;
7304 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
7305 srvstr_get_path_posix(ctx
,
7313 ucf_flags
|= UCF_POSIX_PATHNAMES
;
7315 srvstr_get_path(ctx
,
7324 if (!NT_STATUS_IS_OK(status
)) {
7328 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7331 status
= filename_convert(ctx
,
7337 if (!NT_STATUS_IS_OK(status
)) {
7341 if (fsp
->base_fsp
) {
7342 /* No stream names. */
7343 return NT_STATUS_NOT_SUPPORTED
;
7346 DEBUG(10,("smb_file_link_information: "
7347 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7348 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7349 smb_fname_str_dbg(smb_fname_dst
)));
7350 status
= hardlink_internals(ctx
,
7357 TALLOC_FREE(smb_fname_dst
);
7361 /****************************************************************************
7362 Deal with SMB_FILE_RENAME_INFORMATION.
7363 ****************************************************************************/
7365 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
7366 struct smb_request
*req
,
7370 struct smb_filename
*smb_fname_src
)
7375 char *newname
= NULL
;
7376 struct smb_filename
*smb_fname_dst
= NULL
;
7377 const char *dst_original_lcomp
= NULL
;
7378 NTSTATUS status
= NT_STATUS_OK
;
7380 TALLOC_CTX
*ctx
= talloc_tos();
7382 if (total_data
< 13) {
7383 return NT_STATUS_INVALID_PARAMETER
;
7386 overwrite
= (CVAL(pdata
,0) ? True
: False
);
7387 root_fid
= IVAL(pdata
,4);
7388 len
= IVAL(pdata
,8);
7390 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
7391 return NT_STATUS_INVALID_PARAMETER
;
7394 if (req
->posix_pathnames
) {
7395 srvstr_get_path_posix(ctx
,
7404 srvstr_get_path(ctx
,
7413 if (!NT_STATUS_IS_OK(status
)) {
7417 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7420 /* Check the new name has no '/' characters. */
7421 if (strchr_m(newname
, '/')) {
7422 return NT_STATUS_NOT_SUPPORTED
;
7425 if (fsp
&& fsp
->base_fsp
) {
7426 /* newname must be a stream name. */
7427 if (newname
[0] != ':') {
7428 return NT_STATUS_NOT_SUPPORTED
;
7431 /* Create an smb_fname to call rename_internals_fsp() with. */
7432 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
7433 fsp
->base_fsp
->fsp_name
->base_name
,
7436 fsp
->base_fsp
->fsp_name
->twrp
,
7437 fsp
->base_fsp
->fsp_name
->flags
);
7438 if (smb_fname_dst
== NULL
) {
7439 status
= NT_STATUS_NO_MEMORY
;
7444 * Get the original last component, since
7445 * rename_internals_fsp() requires it.
7447 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7451 if (dst_original_lcomp
== NULL
) {
7452 status
= NT_STATUS_NO_MEMORY
;
7458 * Build up an smb_fname_dst based on the filename passed in.
7459 * We basically just strip off the last component, and put on
7460 * the newname instead.
7462 char *base_name
= NULL
;
7463 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
7464 ucf_flags_from_smb_request(req
);
7466 /* newname must *not* be a stream name. */
7467 if (newname
[0] == ':') {
7468 return NT_STATUS_NOT_SUPPORTED
;
7472 * Strip off the last component (filename) of the path passed
7475 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
7477 return NT_STATUS_NO_MEMORY
;
7479 p
= strrchr_m(base_name
, '/');
7483 base_name
= talloc_strdup(ctx
, "");
7485 return NT_STATUS_NO_MEMORY
;
7488 /* Append the new name. */
7489 base_name
= talloc_asprintf_append(base_name
,
7493 return NT_STATUS_NO_MEMORY
;
7496 status
= filename_convert(ctx
,
7503 /* If an error we expect this to be
7504 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7506 if (!NT_STATUS_IS_OK(status
)) {
7507 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
7511 /* Create an smb_fname to call rename_internals_fsp() */
7512 smb_fname_dst
= synthetic_smb_fname(ctx
,
7516 smb_fname_src
->twrp
,
7517 smb_fname_src
->flags
);
7518 if (smb_fname_dst
== NULL
) {
7519 status
= NT_STATUS_NO_MEMORY
;
7523 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
7527 if (dst_original_lcomp
== NULL
) {
7528 status
= NT_STATUS_NO_MEMORY
;
7533 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
7534 DEBUG(10,("smb_file_rename_information: "
7535 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7536 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7537 smb_fname_str_dbg(smb_fname_dst
)));
7538 status
= rename_internals_fsp(conn
,
7545 DEBUG(10,("smb_file_rename_information: "
7546 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7547 smb_fname_str_dbg(smb_fname_src
),
7548 smb_fname_str_dbg(smb_fname_dst
)));
7549 status
= rename_internals(ctx
,
7558 FILE_WRITE_ATTRIBUTES
);
7561 TALLOC_FREE(smb_fname_dst
);
7565 /****************************************************************************
7566 Deal with SMB_SET_POSIX_ACL.
7567 ****************************************************************************/
7569 #if defined(HAVE_POSIX_ACLS)
7570 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
7571 struct smb_request
*req
,
7575 struct smb_filename
*smb_fname
)
7577 uint16_t posix_acl_version
;
7578 uint16_t num_file_acls
;
7579 uint16_t num_def_acls
;
7580 bool valid_file_acls
= true;
7581 bool valid_def_acls
= true;
7583 unsigned int size_needed
;
7584 unsigned int total_data
;
7585 bool close_fsp
= false;
7587 if (total_data_in
< 0) {
7588 status
= NT_STATUS_INVALID_PARAMETER
;
7592 total_data
= total_data_in
;
7594 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
7595 status
= NT_STATUS_INVALID_PARAMETER
;
7598 posix_acl_version
= SVAL(pdata
,0);
7599 num_file_acls
= SVAL(pdata
,2);
7600 num_def_acls
= SVAL(pdata
,4);
7602 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7603 valid_file_acls
= false;
7607 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7608 valid_def_acls
= false;
7612 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
7613 status
= NT_STATUS_INVALID_PARAMETER
;
7618 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
7619 status
= NT_STATUS_INVALID_PARAMETER
;
7623 size_needed
= num_file_acls
+ num_def_acls
;
7626 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7627 * than UINT_MAX, so check by division.
7629 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
7630 status
= NT_STATUS_INVALID_PARAMETER
;
7634 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
7635 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
7636 status
= NT_STATUS_INVALID_PARAMETER
;
7639 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
7641 if (total_data
< size_needed
) {
7642 status
= NT_STATUS_INVALID_PARAMETER
;
7647 * Ensure we always operate on a file descriptor, not just
7650 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
7651 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
7653 SEC_STD_READ_CONTROL
|
7654 FILE_READ_ATTRIBUTES
|
7655 FILE_WRITE_ATTRIBUTES
;
7657 status
= get_posix_fsp(conn
,
7663 if (!NT_STATUS_IS_OK(status
)) {
7669 /* Here we know fsp != NULL */
7670 SMB_ASSERT(fsp
!= NULL
);
7672 status
= refuse_symlink(conn
, fsp
, fsp
->fsp_name
);
7673 if (!NT_STATUS_IS_OK(status
)) {
7677 /* If we have a default acl, this *must* be a directory. */
7678 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
7679 DBG_INFO("Can't set default acls on "
7680 "non-directory %s\n",
7682 return NT_STATUS_INVALID_HANDLE
;
7685 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
7686 "num_def_acls = %"PRIu16
"\n",
7691 /* Move pdata to the start of the file ACL entries. */
7692 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
7694 if (valid_file_acls
) {
7695 status
= set_unix_posix_acl(conn
,
7699 if (!NT_STATUS_IS_OK(status
)) {
7704 /* Move pdata to the start of the default ACL entries. */
7705 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
7707 if (valid_def_acls
) {
7708 status
= set_unix_posix_default_acl(conn
,
7712 if (!NT_STATUS_IS_OK(status
)) {
7717 status
= NT_STATUS_OK
;
7722 (void)close_file(req
, fsp
, NORMAL_CLOSE
);
7729 /****************************************************************************
7730 Deal with SMB_SET_POSIX_LOCK.
7731 ****************************************************************************/
7733 static void smb_set_posix_lock_done(struct tevent_req
*subreq
);
7735 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
7736 struct smb_request
*req
,
7741 struct tevent_req
*subreq
= NULL
;
7742 struct smbd_lock_element
*lck
= NULL
;
7746 bool blocking_lock
= False
;
7747 enum brl_type lock_type
;
7749 NTSTATUS status
= NT_STATUS_OK
;
7752 fsp
->fsp_flags
.is_pathref
||
7753 fsp_get_io_fd(fsp
) == -1)
7755 return NT_STATUS_INVALID_HANDLE
;
7758 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
7759 return NT_STATUS_INVALID_PARAMETER
;
7762 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
7763 case POSIX_LOCK_TYPE_READ
:
7764 lock_type
= READ_LOCK
;
7766 case POSIX_LOCK_TYPE_WRITE
:
7767 /* Return the right POSIX-mappable error code for files opened read-only. */
7768 if (!fsp
->fsp_flags
.can_write
) {
7769 return NT_STATUS_INVALID_HANDLE
;
7771 lock_type
= WRITE_LOCK
;
7773 case POSIX_LOCK_TYPE_UNLOCK
:
7774 lock_type
= UNLOCK_LOCK
;
7777 return NT_STATUS_INVALID_PARAMETER
;
7780 switch (SVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
)) {
7781 case POSIX_LOCK_FLAG_NOWAIT
:
7782 blocking_lock
= false;
7784 case POSIX_LOCK_FLAG_WAIT
:
7785 blocking_lock
= true;
7788 return NT_STATUS_INVALID_PARAMETER
;
7791 if (!lp_blocking_locks(SNUM(conn
))) {
7792 blocking_lock
= False
;
7795 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
7796 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
7797 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
7798 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
7799 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
7801 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64
", "
7802 "count = %"PRIu64
", offset = %"PRIu64
"\n",
7804 (unsigned int)lock_type
,
7809 if (lock_type
== UNLOCK_LOCK
) {
7810 struct smbd_lock_element l
= {
7811 .req_guid
= smbd_request_guid(req
, 0),
7813 .brltype
= UNLOCK_LOCK
,
7817 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, POSIX_LOCK
);
7821 lck
= talloc(req
, struct smbd_lock_element
);
7823 return NT_STATUS_NO_MEMORY
;
7826 *lck
= (struct smbd_lock_element
) {
7827 .req_guid
= smbd_request_guid(req
, 0),
7829 .brltype
= lock_type
,
7834 subreq
= smbd_smb1_do_locks_send(
7839 blocking_lock
? UINT32_MAX
: 0,
7840 true, /* large_offset */
7844 if (subreq
== NULL
) {
7846 return NT_STATUS_NO_MEMORY
;
7848 tevent_req_set_callback(subreq
, smb_set_posix_lock_done
, req
);
7849 return NT_STATUS_EVENT_PENDING
;
7852 static void smb_set_posix_lock_done(struct tevent_req
*subreq
)
7854 struct smb_request
*req
= NULL
;
7858 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
7861 status
= smbd_smb1_do_locks_recv(subreq
);
7862 TALLOC_FREE(subreq
);
7864 if (NT_STATUS_IS_OK(status
)) {
7865 char params
[2] = {0};
7866 /* Fake up max_data_bytes here - we know it fits. */
7867 send_trans2_replies(
7877 reply_nterror(req
, status
);
7880 (char *)req
->outbuf
,
7883 IS_CONN_ENCRYPTED(req
->conn
),
7886 exit_server_cleanly("smb_set_posix_lock_done: "
7887 "srv_send_smb failed.");
7895 /****************************************************************************
7896 Deal with SMB_SET_FILE_BASIC_INFO.
7897 ****************************************************************************/
7899 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
7903 struct smb_filename
*smb_fname
)
7905 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7906 struct smb_file_time ft
;
7907 uint32_t dosmode
= 0;
7908 NTSTATUS status
= NT_STATUS_OK
;
7910 init_smb_file_time(&ft
);
7912 if (total_data
< 36) {
7913 return NT_STATUS_INVALID_PARAMETER
;
7916 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
7917 if (!NT_STATUS_IS_OK(status
)) {
7921 /* Set the attributes */
7922 dosmode
= IVAL(pdata
,32);
7923 status
= smb_set_file_dosmode(conn
, fsp
, smb_fname
, dosmode
);
7924 if (!NT_STATUS_IS_OK(status
)) {
7929 ft
.create_time
= pull_long_date_full_timespec(pdata
);
7932 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
7935 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
7938 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
7940 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7941 smb_fname_str_dbg(smb_fname
)));
7943 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
7944 if (!NT_STATUS_IS_OK(status
)) {
7948 if (fsp
!= NULL
&& fsp
->fsp_flags
.modified
) {
7949 trigger_write_time_update_immediate(fsp
);
7951 return NT_STATUS_OK
;
7954 /****************************************************************************
7955 Deal with SMB_INFO_STANDARD.
7956 ****************************************************************************/
7958 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
7962 struct smb_filename
*smb_fname
)
7965 struct smb_file_time ft
;
7967 init_smb_file_time(&ft
);
7969 if (total_data
< 12) {
7970 return NT_STATUS_INVALID_PARAMETER
;
7974 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
7976 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
7978 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
7980 DEBUG(10,("smb_set_info_standard: file %s\n",
7981 smb_fname_str_dbg(smb_fname
)));
7983 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
7984 if (!NT_STATUS_IS_OK(status
)) {
7988 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
7989 if (!NT_STATUS_IS_OK(status
)) {
7993 if (fsp
!= NULL
&& fsp
->fsp_flags
.modified
) {
7994 trigger_write_time_update_immediate(fsp
);
7996 return NT_STATUS_OK
;
7999 /****************************************************************************
8000 Deal with SMB_SET_FILE_ALLOCATION_INFO.
8001 ****************************************************************************/
8003 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
8004 struct smb_request
*req
,
8008 struct smb_filename
*smb_fname
)
8010 uint64_t allocation_size
= 0;
8011 NTSTATUS status
= NT_STATUS_OK
;
8012 files_struct
*new_fsp
= NULL
;
8014 if (!VALID_STAT(smb_fname
->st
)) {
8015 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8018 if (total_data
< 8) {
8019 return NT_STATUS_INVALID_PARAMETER
;
8022 allocation_size
= (uint64_t)IVAL(pdata
,0);
8023 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
8024 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
8025 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
8026 (double)allocation_size
));
8028 if (allocation_size
) {
8029 allocation_size
= smb_roundup(conn
, allocation_size
);
8032 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
8033 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
8034 (double)allocation_size
));
8037 !fsp
->fsp_flags
.is_pathref
&&
8038 fsp_get_io_fd(fsp
) != -1)
8040 /* Open file handle. */
8041 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
8042 return NT_STATUS_ACCESS_DENIED
;
8045 /* Only change if needed. */
8046 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
8047 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
8048 return map_nt_error_from_unix(errno
);
8051 /* But always update the time. */
8053 * This is equivalent to a write. Ensure it's seen immediately
8054 * if there are no pending writes.
8056 trigger_write_time_update_immediate(fsp
);
8057 return NT_STATUS_OK
;
8060 /* Pathname or stat or directory file. */
8061 status
= SMB_VFS_CREATE_FILE(
8064 smb_fname
, /* fname */
8065 FILE_WRITE_DATA
, /* access_mask */
8066 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8068 FILE_OPEN
, /* create_disposition*/
8069 0, /* create_options */
8070 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
8071 0, /* oplock_request */
8073 0, /* allocation_size */
8074 0, /* private_flags */
8077 &new_fsp
, /* result */
8079 NULL
, NULL
); /* create context */
8081 if (!NT_STATUS_IS_OK(status
)) {
8082 /* NB. We check for open_was_deferred in the caller. */
8086 /* Only change if needed. */
8087 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
8088 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
8089 status
= map_nt_error_from_unix(errno
);
8090 close_file(req
, new_fsp
, NORMAL_CLOSE
);
8095 /* Changing the allocation size should set the last mod time. */
8097 * This is equivalent to a write. Ensure it's seen immediately
8098 * if there are no pending writes.
8100 trigger_write_time_update_immediate(new_fsp
);
8101 close_file(req
, new_fsp
, NORMAL_CLOSE
);
8102 return NT_STATUS_OK
;
8105 /****************************************************************************
8106 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8107 ****************************************************************************/
8109 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
8110 struct smb_request
*req
,
8114 struct smb_filename
*smb_fname
,
8115 bool fail_after_createfile
)
8119 if (total_data
< 8) {
8120 return NT_STATUS_INVALID_PARAMETER
;
8123 size
= IVAL(pdata
,0);
8124 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
8125 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8126 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
8129 return smb_set_file_size(conn
, req
,
8134 fail_after_createfile
);
8137 /****************************************************************************
8138 Allow a UNIX info mknod.
8139 ****************************************************************************/
8141 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
8144 const struct smb_filename
*smb_fname
)
8146 uint32_t file_type
= IVAL(pdata
,56);
8147 #if defined(HAVE_MAKEDEV)
8148 uint32_t dev_major
= IVAL(pdata
,60);
8149 uint32_t dev_minor
= IVAL(pdata
,68);
8151 SMB_DEV_T dev
= (SMB_DEV_T
)0;
8152 uint32_t raw_unixmode
= IVAL(pdata
,84);
8156 struct smb_filename
*parent_fname
= NULL
;
8157 struct smb_filename
*base_name
= NULL
;
8159 if (total_data
< 100) {
8160 return NT_STATUS_INVALID_PARAMETER
;
8163 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8164 PERM_NEW_FILE
, &unixmode
);
8165 if (!NT_STATUS_IS_OK(status
)) {
8169 #if defined(HAVE_MAKEDEV)
8170 dev
= makedev(dev_major
, dev_minor
);
8173 switch (file_type
) {
8174 /* We can't create other objects here. */
8175 case UNIX_TYPE_FILE
:
8177 case UNIX_TYPE_SYMLINK
:
8178 return NT_STATUS_ACCESS_DENIED
;
8179 #if defined(S_IFIFO)
8180 case UNIX_TYPE_FIFO
:
8181 unixmode
|= S_IFIFO
;
8184 #if defined(S_IFSOCK)
8185 case UNIX_TYPE_SOCKET
:
8186 unixmode
|= S_IFSOCK
;
8189 #if defined(S_IFCHR)
8190 case UNIX_TYPE_CHARDEV
:
8191 /* This is only allowed for root. */
8192 if (get_current_uid(conn
) != sec_initial_uid()) {
8193 return NT_STATUS_ACCESS_DENIED
;
8195 unixmode
|= S_IFCHR
;
8198 #if defined(S_IFBLK)
8199 case UNIX_TYPE_BLKDEV
:
8200 if (get_current_uid(conn
) != sec_initial_uid()) {
8201 return NT_STATUS_ACCESS_DENIED
;
8203 unixmode
|= S_IFBLK
;
8207 return NT_STATUS_INVALID_PARAMETER
;
8210 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8211 "%.0f mode 0%o for file %s\n", (double)dev
,
8212 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
8214 status
= parent_pathref(talloc_tos(),
8219 if (!NT_STATUS_IS_OK(status
)) {
8223 /* Ok - do the mknod. */
8224 ret
= SMB_VFS_MKNODAT(conn
,
8231 TALLOC_FREE(parent_fname
);
8232 return map_nt_error_from_unix(errno
);
8235 /* If any of the other "set" calls fail we
8236 * don't want to end up with a half-constructed mknod.
8239 if (lp_inherit_permissions(SNUM(conn
))) {
8240 inherit_access_posix_acl(conn
,
8245 TALLOC_FREE(parent_fname
);
8247 return NT_STATUS_OK
;
8250 /****************************************************************************
8251 Deal with SMB_SET_FILE_UNIX_BASIC.
8252 ****************************************************************************/
8254 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
8255 struct smb_request
*req
,
8259 struct smb_filename
*smb_fname
)
8261 struct smb_file_time ft
;
8262 uint32_t raw_unixmode
;
8265 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
8266 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
8267 NTSTATUS status
= NT_STATUS_OK
;
8268 enum perm_type ptype
;
8269 files_struct
*all_fsps
= NULL
;
8270 bool modify_mtime
= true;
8272 SMB_STRUCT_STAT sbuf
;
8274 init_smb_file_time(&ft
);
8276 if (total_data
< 100) {
8277 return NT_STATUS_INVALID_PARAMETER
;
8280 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
8281 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
8282 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
8283 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
8286 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
8287 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
8288 set_owner
= (uid_t
)IVAL(pdata
,40);
8289 set_grp
= (gid_t
)IVAL(pdata
,48);
8290 raw_unixmode
= IVAL(pdata
,84);
8292 if (VALID_STAT(smb_fname
->st
)) {
8293 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
8294 ptype
= PERM_EXISTING_DIR
;
8296 ptype
= PERM_EXISTING_FILE
;
8299 ptype
= PERM_NEW_FILE
;
8302 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8304 if (!NT_STATUS_IS_OK(status
)) {
8308 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8309 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8310 smb_fname_str_dbg(smb_fname
), (double)size
,
8311 (unsigned int)set_owner
, (unsigned int)set_grp
,
8312 (int)raw_unixmode
));
8314 sbuf
= smb_fname
->st
;
8316 if (!VALID_STAT(sbuf
)) {
8318 * The only valid use of this is to create character and block
8319 * devices, and named pipes. This is deprecated (IMHO) and
8320 * a new info level should be used for mknod. JRA.
8323 return smb_unix_mknod(conn
,
8330 /* Horrible backwards compatibility hack as an old server bug
8331 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8335 size
= get_file_size_stat(&sbuf
);
8340 * Deal with the UNIX specific mode set.
8343 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
8346 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8347 "setting mode 0%o for file %s\n",
8348 (unsigned int)unixmode
,
8349 smb_fname_str_dbg(smb_fname
)));
8351 !fsp
->fsp_flags
.is_pathref
&&
8352 fsp_get_io_fd(fsp
) != -1)
8354 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
8356 ret
= SMB_VFS_CHMOD(conn
, smb_fname
, unixmode
);
8359 return map_nt_error_from_unix(errno
);
8364 * Deal with the UNIX specific uid set.
8367 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
8368 (sbuf
.st_ex_uid
!= set_owner
)) {
8371 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8372 "changing owner %u for path %s\n",
8373 (unsigned int)set_owner
,
8374 smb_fname_str_dbg(smb_fname
)));
8377 !fsp
->fsp_flags
.is_pathref
&&
8378 fsp_get_io_fd(fsp
) != -1)
8380 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
8383 * UNIX extensions calls must always operate
8386 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
8387 set_owner
, (gid_t
)-1);
8391 status
= map_nt_error_from_unix(errno
);
8397 * Deal with the UNIX specific gid set.
8400 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
8401 (sbuf
.st_ex_gid
!= set_grp
)) {
8404 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8405 "changing group %u for file %s\n",
8406 (unsigned int)set_grp
,
8407 smb_fname_str_dbg(smb_fname
)));
8409 !fsp
->fsp_flags
.is_pathref
&&
8410 fsp_get_io_fd(fsp
) != -1)
8412 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
8415 * UNIX extensions calls must always operate
8418 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
8422 status
= map_nt_error_from_unix(errno
);
8427 /* Deal with any size changes. */
8429 if (S_ISREG(sbuf
.st_ex_mode
)) {
8430 status
= smb_set_file_size(conn
, req
,
8436 if (!NT_STATUS_IS_OK(status
)) {
8441 /* Deal with any time changes. */
8442 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
8443 /* No change, don't cancel anything. */
8447 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
8448 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
8449 all_fsps
= file_find_di_next(all_fsps
, true)) {
8451 * We're setting the time explicitly for UNIX.
8452 * Cancel any pending changes over all handles.
8454 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
8455 TALLOC_FREE(all_fsps
->update_write_time_event
);
8459 * Override the "setting_write_time"
8460 * parameter here as it almost does what
8461 * we need. Just remember if we modified
8462 * mtime and send the notify ourselves.
8464 if (is_omit_timespec(&ft
.mtime
)) {
8465 modify_mtime
= false;
8468 status
= smb_set_file_time(conn
,
8474 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
8475 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
8480 /****************************************************************************
8481 Deal with SMB_SET_FILE_UNIX_INFO2.
8482 ****************************************************************************/
8484 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
8485 struct smb_request
*req
,
8489 struct smb_filename
*smb_fname
)
8492 uint32_t smb_fflags
;
8495 if (total_data
< 116) {
8496 return NT_STATUS_INVALID_PARAMETER
;
8499 /* Start by setting all the fields that are common between UNIX_BASIC
8502 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
8504 if (!NT_STATUS_IS_OK(status
)) {
8508 smb_fflags
= IVAL(pdata
, 108);
8509 smb_fmask
= IVAL(pdata
, 112);
8511 /* NB: We should only attempt to alter the file flags if the client
8512 * sends a non-zero mask.
8514 if (smb_fmask
!= 0) {
8515 int stat_fflags
= 0;
8517 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
8518 smb_fmask
, &stat_fflags
)) {
8519 /* Client asked to alter a flag we don't understand. */
8520 return NT_STATUS_INVALID_PARAMETER
;
8524 !fsp
->fsp_flags
.is_pathref
&&
8525 fsp_get_io_fd(fsp
) != -1)
8527 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8528 return NT_STATUS_NOT_SUPPORTED
;
8530 if (SMB_VFS_CHFLAGS(conn
, smb_fname
,
8531 stat_fflags
) != 0) {
8532 return map_nt_error_from_unix(errno
);
8537 /* XXX: need to add support for changing the create_time here. You
8538 * can do this for paths on Darwin with setattrlist(2). The right way
8539 * to hook this up is probably by extending the VFS utimes interface.
8542 return NT_STATUS_OK
;
8545 /****************************************************************************
8546 Create a directory with POSIX semantics.
8547 ****************************************************************************/
8549 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
8550 struct smb_request
*req
,
8553 struct smb_filename
*smb_fname
,
8554 int *pdata_return_size
)
8556 NTSTATUS status
= NT_STATUS_OK
;
8557 uint32_t raw_unixmode
= 0;
8558 mode_t unixmode
= (mode_t
)0;
8559 files_struct
*fsp
= NULL
;
8560 uint16_t info_level_return
= 0;
8562 char *pdata
= *ppdata
;
8563 struct smb2_create_blobs
*posx
= NULL
;
8565 if (total_data
< 18) {
8566 return NT_STATUS_INVALID_PARAMETER
;
8569 raw_unixmode
= IVAL(pdata
,8);
8570 /* Next 4 bytes are not yet defined. */
8572 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8573 PERM_NEW_DIR
, &unixmode
);
8574 if (!NT_STATUS_IS_OK(status
)) {
8578 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
8579 if (!NT_STATUS_IS_OK(status
)) {
8580 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8585 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8586 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
8588 status
= SMB_VFS_CREATE_FILE(
8591 smb_fname
, /* fname */
8592 FILE_READ_ATTRIBUTES
, /* access_mask */
8593 FILE_SHARE_NONE
, /* share_access */
8594 FILE_CREATE
, /* create_disposition*/
8595 FILE_DIRECTORY_FILE
, /* create_options */
8596 0, /* file_attributes */
8597 0, /* oplock_request */
8599 0, /* allocation_size */
8600 0, /* private_flags */
8605 posx
, /* in_context_blobs */
8606 NULL
); /* out_context_blobs */
8610 if (NT_STATUS_IS_OK(status
)) {
8611 close_file(req
, fsp
, NORMAL_CLOSE
);
8614 info_level_return
= SVAL(pdata
,16);
8616 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8617 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8618 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8619 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8621 *pdata_return_size
= 12;
8624 /* Realloc the data size */
8625 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8626 if (*ppdata
== NULL
) {
8627 *pdata_return_size
= 0;
8628 return NT_STATUS_NO_MEMORY
;
8632 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8633 SSVAL(pdata
,2,0); /* No fnum. */
8634 SIVAL(pdata
,4,info
); /* Was directory created. */
8636 switch (info_level_return
) {
8637 case SMB_QUERY_FILE_UNIX_BASIC
:
8638 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8639 SSVAL(pdata
,10,0); /* Padding. */
8640 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8643 case SMB_QUERY_FILE_UNIX_INFO2
:
8644 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8645 SSVAL(pdata
,10,0); /* Padding. */
8646 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8650 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8651 SSVAL(pdata
,10,0); /* Padding. */
8658 /****************************************************************************
8659 Open/Create a file with POSIX semantics.
8660 ****************************************************************************/
8662 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8663 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8665 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
8666 struct smb_request
*req
,
8669 struct smb_filename
*smb_fname
,
8670 int *pdata_return_size
)
8672 bool extended_oplock_granted
= False
;
8673 char *pdata
= *ppdata
;
8675 uint32_t wire_open_mode
= 0;
8676 uint32_t raw_unixmode
= 0;
8677 uint32_t attributes
= 0;
8678 uint32_t create_disp
= 0;
8679 uint32_t access_mask
= 0;
8680 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
8681 NTSTATUS status
= NT_STATUS_OK
;
8682 mode_t unixmode
= (mode_t
)0;
8683 files_struct
*fsp
= NULL
;
8684 int oplock_request
= 0;
8686 uint16_t info_level_return
= 0;
8687 struct smb2_create_blobs
*posx
= NULL
;
8689 if (total_data
< 18) {
8690 return NT_STATUS_INVALID_PARAMETER
;
8693 flags
= IVAL(pdata
,0);
8694 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
8695 if (oplock_request
) {
8696 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
8699 wire_open_mode
= IVAL(pdata
,4);
8701 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
8702 return smb_posix_mkdir(conn
, req
,
8709 switch (wire_open_mode
& SMB_ACCMODE
) {
8711 access_mask
= SMB_O_RDONLY_MAPPING
;
8714 access_mask
= SMB_O_WRONLY_MAPPING
;
8717 access_mask
= (SMB_O_RDONLY_MAPPING
|
8718 SMB_O_WRONLY_MAPPING
);
8721 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8722 (unsigned int)wire_open_mode
));
8723 return NT_STATUS_INVALID_PARAMETER
;
8726 wire_open_mode
&= ~SMB_ACCMODE
;
8728 /* First take care of O_CREAT|O_EXCL interactions. */
8729 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
8730 case (SMB_O_CREAT
| SMB_O_EXCL
):
8731 /* File exists fail. File not exist create. */
8732 create_disp
= FILE_CREATE
;
8735 /* File exists open. File not exist create. */
8736 create_disp
= FILE_OPEN_IF
;
8739 /* O_EXCL on its own without O_CREAT is undefined.
8740 We deliberately ignore it as some versions of
8741 Linux CIFSFS can send a bare O_EXCL on the
8742 wire which other filesystems in the kernel
8743 ignore. See bug 9519 for details. */
8748 /* File exists open. File not exist fail. */
8749 create_disp
= FILE_OPEN
;
8752 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8753 (unsigned int)wire_open_mode
));
8754 return NT_STATUS_INVALID_PARAMETER
;
8757 /* Next factor in the effects of O_TRUNC. */
8758 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
8760 if (wire_open_mode
& SMB_O_TRUNC
) {
8761 switch (create_disp
) {
8763 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8764 /* Leave create_disp alone as
8765 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8767 /* File exists fail. File not exist create. */
8770 /* SMB_O_CREAT | SMB_O_TRUNC */
8771 /* File exists overwrite. File not exist create. */
8772 create_disp
= FILE_OVERWRITE_IF
;
8776 /* File exists overwrite. File not exist fail. */
8777 create_disp
= FILE_OVERWRITE
;
8780 /* Cannot get here. */
8781 smb_panic("smb_posix_open: logic error");
8782 return NT_STATUS_INVALID_PARAMETER
;
8786 raw_unixmode
= IVAL(pdata
,8);
8787 /* Next 4 bytes are not yet defined. */
8789 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8790 (VALID_STAT(smb_fname
->st
) ?
8791 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
8794 if (!NT_STATUS_IS_OK(status
)) {
8798 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
8799 if (!NT_STATUS_IS_OK(status
)) {
8800 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8805 if (wire_open_mode
& SMB_O_SYNC
) {
8806 create_options
|= FILE_WRITE_THROUGH
;
8808 if (wire_open_mode
& SMB_O_APPEND
) {
8809 access_mask
|= FILE_APPEND_DATA
;
8811 if (wire_open_mode
& SMB_O_DIRECT
) {
8812 attributes
|= FILE_FLAG_NO_BUFFERING
;
8815 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
8816 VALID_STAT_OF_DIR(smb_fname
->st
)) {
8817 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
8818 return NT_STATUS_FILE_IS_A_DIRECTORY
;
8820 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
8821 create_options
|= FILE_DIRECTORY_FILE
;
8824 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8825 smb_fname_str_dbg(smb_fname
),
8826 (unsigned int)wire_open_mode
,
8827 (unsigned int)unixmode
));
8829 status
= SMB_VFS_CREATE_FILE(
8832 smb_fname
, /* fname */
8833 access_mask
, /* access_mask */
8834 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8836 create_disp
, /* create_disposition*/
8837 create_options
, /* create_options */
8838 attributes
, /* file_attributes */
8839 oplock_request
, /* oplock_request */
8841 0, /* allocation_size */
8842 0, /* private_flags */
8847 posx
, /* in_context_blobs */
8848 NULL
); /* out_context_blobs */
8852 if (!NT_STATUS_IS_OK(status
)) {
8856 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
8857 extended_oplock_granted
= True
;
8860 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
8861 extended_oplock_granted
= True
;
8864 info_level_return
= SVAL(pdata
,16);
8866 /* Allocate the correct return size. */
8868 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8869 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8870 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8871 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8873 *pdata_return_size
= 12;
8876 /* Realloc the data size */
8877 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8878 if (*ppdata
== NULL
) {
8879 close_file(req
, fsp
, ERROR_CLOSE
);
8880 *pdata_return_size
= 0;
8881 return NT_STATUS_NO_MEMORY
;
8885 if (extended_oplock_granted
) {
8886 if (flags
& REQUEST_BATCH_OPLOCK
) {
8887 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
8889 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
8891 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
8892 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
8894 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8897 SSVAL(pdata
,2,fsp
->fnum
);
8898 SIVAL(pdata
,4,info
); /* Was file created etc. */
8900 switch (info_level_return
) {
8901 case SMB_QUERY_FILE_UNIX_BASIC
:
8902 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8903 SSVAL(pdata
,10,0); /* padding. */
8904 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8907 case SMB_QUERY_FILE_UNIX_INFO2
:
8908 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8909 SSVAL(pdata
,10,0); /* padding. */
8910 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8914 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8915 SSVAL(pdata
,10,0); /* padding. */
8918 return NT_STATUS_OK
;
8921 /****************************************************************************
8922 Delete a file with POSIX semantics.
8923 ****************************************************************************/
8925 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
8926 struct smb_request
*req
,
8929 struct smb_filename
*smb_fname
)
8931 NTSTATUS status
= NT_STATUS_OK
;
8932 files_struct
*fsp
= NULL
;
8936 int create_options
= 0;
8937 struct share_mode_lock
*lck
= NULL
;
8938 bool other_nonposix_opens
;
8939 struct smb2_create_blobs
*posx
= NULL
;
8941 if (total_data
< 2) {
8942 return NT_STATUS_INVALID_PARAMETER
;
8945 flags
= SVAL(pdata
,0);
8947 if (!VALID_STAT(smb_fname
->st
)) {
8948 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8951 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
8952 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
8953 return NT_STATUS_NOT_A_DIRECTORY
;
8956 DEBUG(10,("smb_posix_unlink: %s %s\n",
8957 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
8958 smb_fname_str_dbg(smb_fname
)));
8960 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
8961 create_options
|= FILE_DIRECTORY_FILE
;
8964 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
8965 if (!NT_STATUS_IS_OK(status
)) {
8966 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8971 status
= SMB_VFS_CREATE_FILE(
8974 smb_fname
, /* fname */
8975 DELETE_ACCESS
, /* access_mask */
8976 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8978 FILE_OPEN
, /* create_disposition*/
8979 create_options
, /* create_options */
8980 0, /* file_attributes */
8981 0, /* oplock_request */
8983 0, /* allocation_size */
8984 0, /* private_flags */
8989 posx
, /* in_context_blobs */
8990 NULL
); /* out_context_blobs */
8994 if (!NT_STATUS_IS_OK(status
)) {
8999 * Don't lie to client. If we can't really delete due to
9000 * non-POSIX opens return SHARING_VIOLATION.
9003 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
9005 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
9006 "lock for file %s\n", fsp_str_dbg(fsp
)));
9007 close_file(req
, fsp
, NORMAL_CLOSE
);
9008 return NT_STATUS_INVALID_PARAMETER
;
9011 other_nonposix_opens
= has_other_nonposix_opens(lck
, fsp
);
9012 if (other_nonposix_opens
) {
9013 /* Fail with sharing violation. */
9015 close_file(req
, fsp
, NORMAL_CLOSE
);
9016 return NT_STATUS_SHARING_VIOLATION
;
9020 * Set the delete on close.
9022 status
= smb_set_file_disposition_info(conn
,
9030 if (!NT_STATUS_IS_OK(status
)) {
9031 close_file(req
, fsp
, NORMAL_CLOSE
);
9034 return close_file(req
, fsp
, NORMAL_CLOSE
);
9037 static NTSTATUS
smbd_do_posix_setfilepathinfo(struct connection_struct
*conn
,
9038 struct smb_request
*req
,
9039 TALLOC_CTX
*mem_ctx
,
9040 uint16_t info_level
,
9041 struct smb_filename
*smb_fname
,
9047 char *pdata
= *ppdata
;
9048 NTSTATUS status
= NT_STATUS_OK
;
9049 int data_return_size
= 0;
9053 if (!CAN_WRITE(conn
)) {
9054 /* Allow POSIX opens. The open path will deny
9055 * any non-readonly opens. */
9056 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
9057 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
9061 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
9062 smb_fname_str_dbg(smb_fname
),
9067 switch (info_level
) {
9068 case SMB_SET_FILE_UNIX_BASIC
:
9070 status
= smb_set_file_unix_basic(conn
, req
,
9078 case SMB_SET_FILE_UNIX_INFO2
:
9080 status
= smb_set_file_unix_info2(conn
, req
,
9088 case SMB_SET_FILE_UNIX_LINK
:
9090 if (smb_fname
== NULL
) {
9091 /* We must have a pathname for this. */
9092 return NT_STATUS_INVALID_LEVEL
;
9094 status
= smb_set_file_unix_link(conn
, req
, pdata
,
9095 total_data
, smb_fname
);
9099 case SMB_SET_FILE_UNIX_HLINK
:
9101 if (smb_fname
== NULL
) {
9102 /* We must have a pathname for this. */
9103 return NT_STATUS_INVALID_LEVEL
;
9105 status
= smb_set_file_unix_hlink(conn
, req
,
9111 #if defined(HAVE_POSIX_ACLS)
9112 case SMB_SET_POSIX_ACL
:
9114 status
= smb_set_posix_acl(conn
,
9124 case SMB_SET_POSIX_LOCK
:
9127 return NT_STATUS_INVALID_LEVEL
;
9129 status
= smb_set_posix_lock(conn
, req
,
9130 pdata
, total_data
, fsp
);
9134 case SMB_POSIX_PATH_OPEN
:
9136 if (smb_fname
== NULL
) {
9137 /* We must have a pathname for this. */
9138 return NT_STATUS_INVALID_LEVEL
;
9141 status
= smb_posix_open(conn
, req
,
9149 case SMB_POSIX_PATH_UNLINK
:
9151 if (smb_fname
== NULL
) {
9152 /* We must have a pathname for this. */
9153 return NT_STATUS_INVALID_LEVEL
;
9156 status
= smb_posix_unlink(conn
, req
,
9164 return NT_STATUS_INVALID_LEVEL
;
9167 if (!NT_STATUS_IS_OK(status
)) {
9171 *ret_data_size
= data_return_size
;
9172 return NT_STATUS_OK
;
9175 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
9176 struct smb_request
*req
,
9177 TALLOC_CTX
*mem_ctx
,
9178 uint16_t info_level
,
9180 struct smb_filename
*smb_fname
,
9181 char **ppdata
, int total_data
,
9184 char *pdata
= *ppdata
;
9185 NTSTATUS status
= NT_STATUS_OK
;
9186 int data_return_size
= 0;
9188 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9189 if (!lp_unix_extensions()) {
9190 return NT_STATUS_INVALID_LEVEL
;
9193 status
= smbd_do_posix_setfilepathinfo(conn
,
9202 if (!NT_STATUS_IS_OK(status
)) {
9205 *ret_data_size
= data_return_size
;
9206 return NT_STATUS_OK
;
9211 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9212 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
9214 info_level
, total_data
));
9216 switch (info_level
) {
9218 case SMB_INFO_STANDARD
:
9220 status
= smb_set_info_standard(conn
,
9228 case SMB_INFO_SET_EA
:
9230 status
= smb_info_set_ea(conn
,
9238 case SMB_SET_FILE_BASIC_INFO
:
9239 case SMB_FILE_BASIC_INFORMATION
:
9241 status
= smb_set_file_basic_info(conn
,
9249 case SMB_FILE_ALLOCATION_INFORMATION
:
9250 case SMB_SET_FILE_ALLOCATION_INFO
:
9252 status
= smb_set_file_allocation_info(conn
, req
,
9260 case SMB_FILE_END_OF_FILE_INFORMATION
:
9261 case SMB_SET_FILE_END_OF_FILE_INFO
:
9264 * XP/Win7 both fail after the createfile with
9265 * SMB_SET_FILE_END_OF_FILE_INFO but not
9266 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9267 * The level is known here, so pass it down
9271 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
9273 status
= smb_set_file_end_of_file_info(conn
, req
,
9282 case SMB_FILE_DISPOSITION_INFORMATION
:
9283 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
9286 /* JRA - We used to just ignore this on a path ?
9287 * Shouldn't this be invalid level on a pathname
9290 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
9291 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
9294 status
= smb_set_file_disposition_info(conn
,
9302 case SMB_FILE_POSITION_INFORMATION
:
9304 status
= smb_file_position_information(conn
,
9311 case SMB_FILE_FULL_EA_INFORMATION
:
9313 status
= smb_set_file_full_ea_info(conn
,
9320 /* From tridge Samba4 :
9321 * MODE_INFORMATION in setfileinfo (I have no
9322 * idea what "mode information" on a file is - it takes a value of 0,
9323 * 2, 4 or 6. What could it be?).
9326 case SMB_FILE_MODE_INFORMATION
:
9328 status
= smb_file_mode_information(conn
,
9334 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9335 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
9336 case SMB_FILE_SHORT_NAME_INFORMATION
:
9337 return NT_STATUS_NOT_SUPPORTED
;
9339 case SMB_FILE_RENAME_INFORMATION
:
9341 status
= smb_file_rename_information(conn
, req
,
9347 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
9349 /* SMB2 rename information. */
9350 status
= smb2_file_rename_information(conn
, req
,
9356 case SMB_FILE_LINK_INFORMATION
:
9358 status
= smb_file_link_information(conn
, req
,
9365 return NT_STATUS_INVALID_LEVEL
;
9368 if (!NT_STATUS_IS_OK(status
)) {
9372 *ret_data_size
= data_return_size
;
9373 return NT_STATUS_OK
;
9376 /****************************************************************************
9377 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9378 ****************************************************************************/
9380 static void call_trans2setfilepathinfo(connection_struct
*conn
,
9381 struct smb_request
*req
,
9382 unsigned int tran_call
,
9383 char **pparams
, int total_params
,
9384 char **ppdata
, int total_data
,
9385 unsigned int max_data_bytes
)
9387 char *params
= *pparams
;
9388 char *pdata
= *ppdata
;
9389 uint16_t info_level
;
9390 struct smb_filename
*smb_fname
= NULL
;
9391 files_struct
*fsp
= NULL
;
9392 NTSTATUS status
= NT_STATUS_OK
;
9393 int data_return_size
= 0;
9396 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9400 if (tran_call
== TRANSACT2_SETFILEINFO
) {
9401 if (total_params
< 4) {
9402 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9406 fsp
= file_fsp(req
, SVAL(params
,0));
9407 /* Basic check for non-null fsp. */
9408 if (!check_fsp_open(conn
, req
, fsp
)) {
9411 info_level
= SVAL(params
,2);
9413 smb_fname
= fsp
->fsp_name
;
9415 if (fsp_get_pathref_fd(fsp
) == -1) {
9417 * This is actually a SETFILEINFO on a directory
9418 * handle (returned from an NT SMB). NT5.0 seems
9419 * to do this call. JRA.
9421 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9422 /* Always do lstat for UNIX calls. */
9423 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
9424 DEBUG(3,("call_trans2setfilepathinfo: "
9425 "SMB_VFS_LSTAT of %s failed "
9427 smb_fname_str_dbg(smb_fname
),
9429 reply_nterror(req
, map_nt_error_from_unix(errno
));
9433 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
9434 DEBUG(3,("call_trans2setfilepathinfo: "
9435 "fileinfo of %s failed (%s)\n",
9436 smb_fname_str_dbg(smb_fname
),
9438 reply_nterror(req
, map_nt_error_from_unix(errno
));
9442 } else if (fsp
->print_file
) {
9444 * Doing a DELETE_ON_CLOSE should cancel a print job.
9446 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
9447 uint32_t new_private_options
=
9448 fh_get_private_options(fsp
->fh
);
9449 new_private_options
|=
9450 NTCREATEX_FLAG_DELETE_ON_CLOSE
;
9451 fh_set_private_options(fsp
->fh
,
9452 new_private_options
);
9454 DEBUG(3,("call_trans2setfilepathinfo: "
9455 "Cancelling print job (%s)\n",
9459 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
9465 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
9470 * Original code - this is an open file.
9472 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
9473 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9474 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
9476 reply_nterror(req
, map_nt_error_from_unix(errno
));
9482 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9485 if (total_params
< 7) {
9486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9490 info_level
= SVAL(params
,0);
9491 if (req
->posix_pathnames
) {
9492 srvstr_get_path_posix(req
,
9501 srvstr_get_path(req
,
9510 if (!NT_STATUS_IS_OK(status
)) {
9511 reply_nterror(req
, status
);
9515 status
= filename_convert(req
, conn
,
9520 if (!NT_STATUS_IS_OK(status
)) {
9521 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9522 reply_botherror(req
,
9523 NT_STATUS_PATH_NOT_COVERED
,
9524 ERRSRV
, ERRbadpath
);
9527 reply_nterror(req
, status
);
9532 * smb_fname->fsp may be NULL if smb_fname points at a symlink
9533 * and we're in POSIX context, so be careful when using fsp
9534 * below, it can still be NULL.
9536 fsp
= smb_fname
->fsp
;
9538 if (INFO_LEVEL_IS_UNIX(info_level
)) {
9540 * For CIFS UNIX extensions the target name may not exist.
9543 /* Always do lstat for UNIX calls. */
9544 SMB_VFS_LSTAT(conn
, smb_fname
);
9546 } else if (!VALID_STAT(smb_fname
->st
) &&
9547 SMB_VFS_STAT(conn
, smb_fname
)) {
9548 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9550 smb_fname_str_dbg(smb_fname
),
9552 reply_nterror(req
, map_nt_error_from_unix(errno
));
9557 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9558 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
9560 info_level
,total_data
));
9562 /* Realloc the parameter size */
9563 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9564 if (*pparams
== NULL
) {
9565 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9572 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
9578 if (!NT_STATUS_IS_OK(status
)) {
9579 if (open_was_deferred(req
->xconn
, req
->mid
)) {
9580 /* We have re-scheduled this call. */
9583 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
9584 bool ok
= defer_smb1_sharing_violation(req
);
9589 if (NT_STATUS_EQUAL(status
, NT_STATUS_EVENT_PENDING
)) {
9590 /* We have re-scheduled this call. */
9593 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9594 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
9595 ERRSRV
, ERRbadpath
);
9598 if (info_level
== SMB_POSIX_PATH_OPEN
) {
9599 reply_openerror(req
, status
);
9604 * Invalid EA name needs to return 2 param bytes,
9605 * not a zero-length error packet.
9607 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
9608 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
9611 reply_nterror(req
, status
);
9616 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
9622 /****************************************************************************
9623 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9624 ****************************************************************************/
9626 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
9627 char **pparams
, int total_params
,
9628 char **ppdata
, int total_data
,
9629 unsigned int max_data_bytes
)
9631 struct files_struct
*fsp
= NULL
;
9632 struct smb_filename
*smb_dname
= NULL
;
9633 char *params
= *pparams
;
9634 char *pdata
= *ppdata
;
9635 char *directory
= NULL
;
9636 NTSTATUS status
= NT_STATUS_OK
;
9637 struct ea_list
*ea_list
= NULL
;
9638 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
9639 TALLOC_CTX
*ctx
= talloc_tos();
9641 if (!CAN_WRITE(conn
)) {
9642 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9646 if (total_params
< 5) {
9647 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9651 if (req
->posix_pathnames
) {
9652 srvstr_get_path_posix(ctx
,
9661 srvstr_get_path(ctx
,
9670 if (!NT_STATUS_IS_OK(status
)) {
9671 reply_nterror(req
, status
);
9675 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
9677 status
= filename_convert(ctx
,
9684 if (!NT_STATUS_IS_OK(status
)) {
9685 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
9686 reply_botherror(req
,
9687 NT_STATUS_PATH_NOT_COVERED
,
9688 ERRSRV
, ERRbadpath
);
9691 reply_nterror(req
, status
);
9696 * OS/2 workplace shell seems to send SET_EA requests of "null"
9697 * length (4 bytes containing IVAL 4).
9698 * They seem to have no effect. Bug #3212. JRA.
9701 if (total_data
&& (total_data
!= 4)) {
9702 /* Any data in this call is an EA list. */
9703 if (total_data
< 10) {
9704 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9708 if (IVAL(pdata
,0) > total_data
) {
9709 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9710 IVAL(pdata
,0), (unsigned int)total_data
));
9711 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9715 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
9718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9722 if (!lp_ea_support(SNUM(conn
))) {
9723 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
9727 /* If total_data == 4 Windows doesn't care what values
9728 * are placed in that field, it just ignores them.
9729 * The System i QNTC IBM SMB client puts bad values here,
9730 * so ignore them. */
9732 status
= SMB_VFS_CREATE_FILE(
9735 smb_dname
, /* fname */
9736 MAXIMUM_ALLOWED_ACCESS
, /* access_mask */
9737 FILE_SHARE_NONE
, /* share_access */
9738 FILE_CREATE
, /* create_disposition*/
9739 FILE_DIRECTORY_FILE
, /* create_options */
9740 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
9741 0, /* oplock_request */
9743 0, /* allocation_size */
9744 0, /* private_flags */
9749 NULL
, NULL
); /* create context */
9750 if (!NT_STATUS_IS_OK(status
)) {
9751 reply_nterror(req
, status
);
9755 /* Try and set any given EA. */
9757 status
= set_ea(conn
, fsp
, ea_list
);
9758 if (!NT_STATUS_IS_OK(status
)) {
9759 reply_nterror(req
, status
);
9764 /* Realloc the parameter and data sizes */
9765 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9766 if(*pparams
== NULL
) {
9767 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9774 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
9778 close_file(NULL
, fsp
, NORMAL_CLOSE
);
9781 TALLOC_FREE(smb_dname
);
9785 /****************************************************************************
9786 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9787 We don't actually do this - we just send a null response.
9788 ****************************************************************************/
9790 static void call_trans2findnotifyfirst(connection_struct
*conn
,
9791 struct smb_request
*req
,
9792 char **pparams
, int total_params
,
9793 char **ppdata
, int total_data
,
9794 unsigned int max_data_bytes
)
9796 char *params
= *pparams
;
9797 uint16_t info_level
;
9799 if (total_params
< 6) {
9800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9804 info_level
= SVAL(params
,4);
9805 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
9807 switch (info_level
) {
9812 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
9816 /* Realloc the parameter and data sizes */
9817 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
9818 if (*pparams
== NULL
) {
9819 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9824 SSVAL(params
,0,fnf_handle
);
9825 SSVAL(params
,2,0); /* No changes */
9826 SSVAL(params
,4,0); /* No EA errors */
9833 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
9838 /****************************************************************************
9839 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9840 changes). Currently this does nothing.
9841 ****************************************************************************/
9843 static void call_trans2findnotifynext(connection_struct
*conn
,
9844 struct smb_request
*req
,
9845 char **pparams
, int total_params
,
9846 char **ppdata
, int total_data
,
9847 unsigned int max_data_bytes
)
9849 char *params
= *pparams
;
9851 DEBUG(3,("call_trans2findnotifynext\n"));
9853 /* Realloc the parameter and data sizes */
9854 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
9855 if (*pparams
== NULL
) {
9856 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9861 SSVAL(params
,0,0); /* No changes */
9862 SSVAL(params
,2,0); /* No EA errors */
9864 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
9869 /****************************************************************************
9870 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9871 ****************************************************************************/
9873 static void call_trans2getdfsreferral(connection_struct
*conn
,
9874 struct smb_request
*req
,
9875 char **pparams
, int total_params
,
9876 char **ppdata
, int total_data
,
9877 unsigned int max_data_bytes
)
9879 char *params
= *pparams
;
9880 char *pathname
= NULL
;
9882 int max_referral_level
;
9883 NTSTATUS status
= NT_STATUS_OK
;
9884 TALLOC_CTX
*ctx
= talloc_tos();
9886 DEBUG(10,("call_trans2getdfsreferral\n"));
9888 if (total_params
< 3) {
9889 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9893 max_referral_level
= SVAL(params
,0);
9895 if(!lp_host_msdfs()) {
9896 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9900 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
9901 total_params
- 2, STR_TERMINATE
);
9903 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
9906 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
9907 ppdata
,&status
)) < 0) {
9908 reply_nterror(req
, status
);
9912 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
9913 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
9914 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
9919 #define LMCAT_SPL 0x53
9920 #define LMFUNC_GETJOBID 0x60
9922 /****************************************************************************
9923 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9924 ****************************************************************************/
9926 static void call_trans2ioctl(connection_struct
*conn
,
9927 struct smb_request
*req
,
9928 char **pparams
, int total_params
,
9929 char **ppdata
, int total_data
,
9930 unsigned int max_data_bytes
)
9932 const struct loadparm_substitution
*lp_sub
=
9933 loadparm_s3_global_substitution();
9934 char *pdata
= *ppdata
;
9935 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
9939 /* check for an invalid fid before proceeding */
9942 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9946 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9947 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9948 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
9949 if (*ppdata
== NULL
) {
9950 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9955 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9956 CAN ACCEPT THIS IN UNICODE. JRA. */
9959 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
9961 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
9962 lp_netbios_name(), 15,
9963 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
9964 if (!NT_STATUS_IS_OK(status
)) {
9965 reply_nterror(req
, status
);
9968 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
9969 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)), 13,
9970 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
9971 if (!NT_STATUS_IS_OK(status
)) {
9972 reply_nterror(req
, status
);
9975 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
9980 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9981 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9984 /****************************************************************************
9985 Reply to a SMBfindclose (stop trans2 directory search).
9986 ****************************************************************************/
9988 void reply_findclose(struct smb_request
*req
)
9991 struct smbd_server_connection
*sconn
= req
->sconn
;
9992 files_struct
*fsp
= NULL
;
9994 START_PROFILE(SMBfindclose
);
9997 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9998 END_PROFILE(SMBfindclose
);
10002 dptr_num
= SVALS(req
->vwv
+0, 0);
10004 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
10007 * OS/2 seems to use -1 to indicate "close all directories"
10008 * This has to mean on this specific connection struct.
10010 if (dptr_num
== -1) {
10011 dptr_closecnum(req
->conn
);
10013 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
10016 close_file(NULL
, fsp
, NORMAL_CLOSE
);
10021 reply_outbuf(req
, 0, 0);
10023 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
10025 END_PROFILE(SMBfindclose
);
10029 /****************************************************************************
10030 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
10031 ****************************************************************************/
10033 void reply_findnclose(struct smb_request
*req
)
10037 START_PROFILE(SMBfindnclose
);
10039 if (req
->wct
< 1) {
10040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10041 END_PROFILE(SMBfindnclose
);
10045 dptr_num
= SVAL(req
->vwv
+0, 0);
10047 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
10049 /* We never give out valid handles for a
10050 findnotifyfirst - so any dptr_num is ok here.
10053 reply_outbuf(req
, 0, 0);
10055 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
10057 END_PROFILE(SMBfindnclose
);
10061 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
10062 struct trans_state
*state
)
10064 if (get_Protocol() >= PROTOCOL_NT1
) {
10065 req
->flags2
|= 0x40; /* IS_LONG_NAME */
10066 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
10069 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
10070 if (state
->call
!= TRANSACT2_QFSINFO
&&
10071 state
->call
!= TRANSACT2_SETFSINFO
) {
10072 DEBUG(0,("handle_trans2: encryption required "
10073 "with call 0x%x\n",
10074 (unsigned int)state
->call
));
10075 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
10080 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
10082 /* Now we must call the relevant TRANS2 function */
10083 switch(state
->call
) {
10084 case TRANSACT2_OPEN
:
10086 START_PROFILE(Trans2_open
);
10087 call_trans2open(conn
, req
,
10088 &state
->param
, state
->total_param
,
10089 &state
->data
, state
->total_data
,
10090 state
->max_data_return
);
10091 END_PROFILE(Trans2_open
);
10095 case TRANSACT2_FINDFIRST
:
10097 START_PROFILE(Trans2_findfirst
);
10098 call_trans2findfirst(conn
, req
,
10099 &state
->param
, state
->total_param
,
10100 &state
->data
, state
->total_data
,
10101 state
->max_data_return
);
10102 END_PROFILE(Trans2_findfirst
);
10106 case TRANSACT2_FINDNEXT
:
10108 START_PROFILE(Trans2_findnext
);
10109 call_trans2findnext(conn
, req
,
10110 &state
->param
, state
->total_param
,
10111 &state
->data
, state
->total_data
,
10112 state
->max_data_return
);
10113 END_PROFILE(Trans2_findnext
);
10117 case TRANSACT2_QFSINFO
:
10119 START_PROFILE(Trans2_qfsinfo
);
10120 call_trans2qfsinfo(conn
, req
,
10121 &state
->param
, state
->total_param
,
10122 &state
->data
, state
->total_data
,
10123 state
->max_data_return
);
10124 END_PROFILE(Trans2_qfsinfo
);
10128 case TRANSACT2_SETFSINFO
:
10130 START_PROFILE(Trans2_setfsinfo
);
10131 call_trans2setfsinfo(conn
, req
,
10132 &state
->param
, state
->total_param
,
10133 &state
->data
, state
->total_data
,
10134 state
->max_data_return
);
10135 END_PROFILE(Trans2_setfsinfo
);
10139 case TRANSACT2_QPATHINFO
:
10140 case TRANSACT2_QFILEINFO
:
10142 START_PROFILE(Trans2_qpathinfo
);
10143 call_trans2qfilepathinfo(conn
, req
, state
->call
,
10144 &state
->param
, state
->total_param
,
10145 &state
->data
, state
->total_data
,
10146 state
->max_data_return
);
10147 END_PROFILE(Trans2_qpathinfo
);
10151 case TRANSACT2_SETPATHINFO
:
10152 case TRANSACT2_SETFILEINFO
:
10154 START_PROFILE(Trans2_setpathinfo
);
10155 call_trans2setfilepathinfo(conn
, req
, state
->call
,
10156 &state
->param
, state
->total_param
,
10157 &state
->data
, state
->total_data
,
10158 state
->max_data_return
);
10159 END_PROFILE(Trans2_setpathinfo
);
10163 case TRANSACT2_FINDNOTIFYFIRST
:
10165 START_PROFILE(Trans2_findnotifyfirst
);
10166 call_trans2findnotifyfirst(conn
, req
,
10167 &state
->param
, state
->total_param
,
10168 &state
->data
, state
->total_data
,
10169 state
->max_data_return
);
10170 END_PROFILE(Trans2_findnotifyfirst
);
10174 case TRANSACT2_FINDNOTIFYNEXT
:
10176 START_PROFILE(Trans2_findnotifynext
);
10177 call_trans2findnotifynext(conn
, req
,
10178 &state
->param
, state
->total_param
,
10179 &state
->data
, state
->total_data
,
10180 state
->max_data_return
);
10181 END_PROFILE(Trans2_findnotifynext
);
10185 case TRANSACT2_MKDIR
:
10187 START_PROFILE(Trans2_mkdir
);
10188 call_trans2mkdir(conn
, req
,
10189 &state
->param
, state
->total_param
,
10190 &state
->data
, state
->total_data
,
10191 state
->max_data_return
);
10192 END_PROFILE(Trans2_mkdir
);
10196 case TRANSACT2_GET_DFS_REFERRAL
:
10198 START_PROFILE(Trans2_get_dfs_referral
);
10199 call_trans2getdfsreferral(conn
, req
,
10200 &state
->param
, state
->total_param
,
10201 &state
->data
, state
->total_data
,
10202 state
->max_data_return
);
10203 END_PROFILE(Trans2_get_dfs_referral
);
10207 case TRANSACT2_IOCTL
:
10209 START_PROFILE(Trans2_ioctl
);
10210 call_trans2ioctl(conn
, req
,
10211 &state
->param
, state
->total_param
,
10212 &state
->data
, state
->total_data
,
10213 state
->max_data_return
);
10214 END_PROFILE(Trans2_ioctl
);
10219 /* Error in request */
10220 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
10221 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
10225 /****************************************************************************
10226 Reply to a SMBtrans2.
10227 ****************************************************************************/
10229 void reply_trans2(struct smb_request
*req
)
10231 connection_struct
*conn
= req
->conn
;
10232 unsigned int dsoff
;
10233 unsigned int dscnt
;
10234 unsigned int psoff
;
10235 unsigned int pscnt
;
10236 unsigned int tran_call
;
10237 struct trans_state
*state
;
10240 START_PROFILE(SMBtrans2
);
10242 if (req
->wct
< 14) {
10243 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10244 END_PROFILE(SMBtrans2
);
10248 dsoff
= SVAL(req
->vwv
+12, 0);
10249 dscnt
= SVAL(req
->vwv
+11, 0);
10250 psoff
= SVAL(req
->vwv
+10, 0);
10251 pscnt
= SVAL(req
->vwv
+9, 0);
10252 tran_call
= SVAL(req
->vwv
+14, 0);
10254 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
10255 if (!NT_STATUS_IS_OK(result
)) {
10256 DEBUG(2, ("Got invalid trans2 request: %s\n",
10257 nt_errstr(result
)));
10258 reply_nterror(req
, result
);
10259 END_PROFILE(SMBtrans2
);
10263 if (IS_IPC(conn
)) {
10264 switch (tran_call
) {
10265 /* List the allowed trans2 calls on IPC$ */
10266 case TRANSACT2_OPEN
:
10267 case TRANSACT2_GET_DFS_REFERRAL
:
10268 case TRANSACT2_QFILEINFO
:
10269 case TRANSACT2_QFSINFO
:
10270 case TRANSACT2_SETFSINFO
:
10273 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
10274 END_PROFILE(SMBtrans2
);
10279 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
10280 DEBUG(0, ("talloc failed\n"));
10281 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10282 END_PROFILE(SMBtrans2
);
10286 state
->cmd
= SMBtrans2
;
10288 state
->mid
= req
->mid
;
10289 state
->vuid
= req
->vuid
;
10290 state
->setup_count
= SVAL(req
->vwv
+13, 0);
10291 state
->setup
= NULL
;
10292 state
->total_param
= SVAL(req
->vwv
+0, 0);
10293 state
->param
= NULL
;
10294 state
->total_data
= SVAL(req
->vwv
+1, 0);
10295 state
->data
= NULL
;
10296 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
10297 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
10298 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
10299 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
10300 state
->one_way
= BITSETW(req
->vwv
+5, 1);
10302 state
->call
= tran_call
;
10304 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10305 is so as a sanity check */
10306 if (state
->setup_count
!= 1) {
10308 * Need to have rc=0 for ioctl to get job id for OS/2.
10309 * Network printing will fail if function is not successful.
10310 * Similar function in reply.c will be used if protocol
10311 * is LANMAN1.0 instead of LM1.2X002.
10312 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10313 * outbuf doesn't have to be set(only job id is used).
10315 if ( (state
->setup_count
== 4)
10316 && (tran_call
== TRANSACT2_IOCTL
)
10317 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
10318 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
10319 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10321 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
10322 DEBUG(2,("Transaction is %d\n",tran_call
));
10323 TALLOC_FREE(state
);
10324 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10325 END_PROFILE(SMBtrans2
);
10330 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
10333 if (state
->total_data
) {
10335 if (trans_oob(state
->total_data
, 0, dscnt
)
10336 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
10340 /* Can't use talloc here, the core routines do realloc on the
10341 * params and data. */
10342 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
10343 if (state
->data
== NULL
) {
10344 DEBUG(0,("reply_trans2: data malloc fail for %u "
10345 "bytes !\n", (unsigned int)state
->total_data
));
10346 TALLOC_FREE(state
);
10347 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10348 END_PROFILE(SMBtrans2
);
10352 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
10355 if (state
->total_param
) {
10357 if (trans_oob(state
->total_param
, 0, pscnt
)
10358 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
10362 /* Can't use talloc here, the core routines do realloc on the
10363 * params and data. */
10364 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
10365 if (state
->param
== NULL
) {
10366 DEBUG(0,("reply_trans: param malloc fail for %u "
10367 "bytes !\n", (unsigned int)state
->total_param
));
10368 SAFE_FREE(state
->data
);
10369 TALLOC_FREE(state
);
10370 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
10371 END_PROFILE(SMBtrans2
);
10375 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
10378 state
->received_data
= dscnt
;
10379 state
->received_param
= pscnt
;
10381 if ((state
->received_param
== state
->total_param
) &&
10382 (state
->received_data
== state
->total_data
)) {
10384 handle_trans2(conn
, req
, state
);
10386 SAFE_FREE(state
->data
);
10387 SAFE_FREE(state
->param
);
10388 TALLOC_FREE(state
);
10389 END_PROFILE(SMBtrans2
);
10393 DLIST_ADD(conn
->pending_trans
, state
);
10395 /* We need to send an interim response then receive the rest
10396 of the parameter/data bytes */
10397 reply_outbuf(req
, 0, 0);
10398 show_msg((char *)req
->outbuf
);
10399 END_PROFILE(SMBtrans2
);
10404 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10405 SAFE_FREE(state
->data
);
10406 SAFE_FREE(state
->param
);
10407 TALLOC_FREE(state
);
10408 END_PROFILE(SMBtrans2
);
10409 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10413 /****************************************************************************
10414 Reply to a SMBtranss2
10415 ****************************************************************************/
10417 void reply_transs2(struct smb_request
*req
)
10419 connection_struct
*conn
= req
->conn
;
10420 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
10421 struct trans_state
*state
;
10423 START_PROFILE(SMBtranss2
);
10425 show_msg((const char *)req
->inbuf
);
10427 /* Windows clients expect all replies to
10428 a transact secondary (SMBtranss2 0x33)
10429 to have a command code of transact
10430 (SMBtrans2 0x32). See bug #8989
10431 and also [MS-CIFS] section 2.2.4.47.2
10434 req
->cmd
= SMBtrans2
;
10436 if (req
->wct
< 8) {
10437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10438 END_PROFILE(SMBtranss2
);
10442 for (state
= conn
->pending_trans
; state
!= NULL
;
10443 state
= state
->next
) {
10444 if (state
->mid
== req
->mid
) {
10449 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
10450 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10451 END_PROFILE(SMBtranss2
);
10455 /* Revise state->total_param and state->total_data in case they have
10456 changed downwards */
10458 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
10459 state
->total_param
= SVAL(req
->vwv
+0, 0);
10460 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
10461 state
->total_data
= SVAL(req
->vwv
+1, 0);
10463 pcnt
= SVAL(req
->vwv
+2, 0);
10464 poff
= SVAL(req
->vwv
+3, 0);
10465 pdisp
= SVAL(req
->vwv
+4, 0);
10467 dcnt
= SVAL(req
->vwv
+5, 0);
10468 doff
= SVAL(req
->vwv
+6, 0);
10469 ddisp
= SVAL(req
->vwv
+7, 0);
10471 state
->received_param
+= pcnt
;
10472 state
->received_data
+= dcnt
;
10474 if ((state
->received_data
> state
->total_data
) ||
10475 (state
->received_param
> state
->total_param
))
10479 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
10480 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
10483 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
10487 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
10488 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
10491 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
10494 if ((state
->received_param
< state
->total_param
) ||
10495 (state
->received_data
< state
->total_data
)) {
10496 END_PROFILE(SMBtranss2
);
10500 handle_trans2(conn
, req
, state
);
10502 DLIST_REMOVE(conn
->pending_trans
, state
);
10503 SAFE_FREE(state
->data
);
10504 SAFE_FREE(state
->param
);
10505 TALLOC_FREE(state
);
10507 END_PROFILE(SMBtranss2
);
10512 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10513 DLIST_REMOVE(conn
->pending_trans
, state
);
10514 SAFE_FREE(state
->data
);
10515 SAFE_FREE(state
->param
);
10516 TALLOC_FREE(state
);
10517 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
10518 END_PROFILE(SMBtranss2
);