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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS
check_access(connection_struct
*conn
,
60 const struct smb_filename
*smb_fname
,
64 if (!(fsp
->access_mask
& access_mask
)) {
65 return NT_STATUS_ACCESS_DENIED
;
68 NTSTATUS status
= smbd_check_access_rights(conn
,
72 if (!NT_STATUS_IS_OK(status
)) {
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
86 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type
= get_remote_arch();
90 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
91 val
= SMB_ROUNDUP(val
,rval
);
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
105 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
106 return (uint64_t)psbuf
->st_ex_ino
;
108 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
109 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name
)
123 static const char * const prohibited_ea_names
[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME
,
125 SAMBA_XATTR_DOS_ATTRIB
,
133 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
134 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
137 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
149 files_struct
*fsp
, const char *fname
,
150 const char *ea_name
, struct ea_struct
*pea
)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size
= 256;
159 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
161 return NT_STATUS_NO_MEMORY
;
164 if (fsp
&& fsp
->fh
->fd
!= -1) {
165 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
167 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
170 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
176 return map_nt_error_from_unix(errno
);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
180 dump_data(10, (uint8
*)val
, sizeret
);
183 if (strnequal(ea_name
, "user.", 5)) {
184 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
186 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
188 if (pea
->name
== NULL
) {
190 return NT_STATUS_NO_MEMORY
;
192 pea
->value
.data
= (unsigned char *)val
;
193 pea
->value
.length
= (size_t)sizeret
;
197 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
198 files_struct
*fsp
, const char *fname
,
199 char ***pnames
, size_t *pnum_names
)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size
= 1024;
203 char *ea_namelist
= NULL
;
208 ssize_t sizeret
= -1;
210 if (!lp_ea_support(SNUM(conn
))) {
219 * TALLOC the result early to get the talloc hierarchy right.
222 names
= talloc_array(mem_ctx
, char *, 1);
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY
;
228 while (ea_namelist_size
<= 65536) {
230 ea_namelist
= talloc_realloc(
231 names
, ea_namelist
, char, ea_namelist_size
);
232 if (ea_namelist
== NULL
) {
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY
;
238 if (fsp
&& fsp
->fh
->fd
!= -1) {
239 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
242 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
246 if ((sizeret
== -1) && (errno
== ERANGE
)) {
247 ea_namelist_size
*= 2;
256 return map_nt_error_from_unix(errno
);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret
));
272 * Ensure the result is 0-terminated
275 if (ea_namelist
[sizeret
-1] != '\0') {
277 return NT_STATUS_INTERNAL_ERROR
;
285 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
289 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
291 DEBUG(0, ("talloc failed\n"));
293 return NT_STATUS_NO_MEMORY
;
299 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
300 names
[num_names
++] = p
;
308 *pnum_names
= num_names
;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
317 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
319 /* Get a list of all xattrs. Max namesize is 64k. */
322 struct ea_list
*ea_list_head
= NULL
;
328 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
331 if (!NT_STATUS_IS_OK(status
)) {
335 if (num_names
== 0) {
340 for (i
=0; i
<num_names
; i
++) {
341 struct ea_list
*listp
;
344 if (strnequal(names
[i
], "system.", 7)
345 || samba_private_attr_name(names
[i
]))
349 * Filter out any underlying POSIX EA names
350 * that a Windows client can't handle.
352 if (!lp_posix_pathnames() &&
353 is_invalid_windows_ea_name(names
[i
])) {
357 listp
= talloc(mem_ctx
, struct ea_list
);
359 return NT_STATUS_NO_MEMORY
;
362 status
= get_ea_value(listp
, conn
, fsp
,
366 if (!NT_STATUS_IS_OK(status
)) {
371 if (listp
->ea
.value
.length
== 0) {
373 * We can never return a zero length EA.
374 * Windows reports the EA's as corrupted.
380 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
383 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
385 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
386 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
387 (unsigned int)listp
->ea
.value
.length
));
389 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
393 /* Add on 4 for total length. */
394 if (*pea_total_len
) {
398 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
399 (unsigned int)*pea_total_len
));
401 *ea_list
= ea_list_head
;
405 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
406 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
411 if (!lp_ea_support(SNUM(conn
))) {
415 if (is_ntfs_stream_smb_fname(smb_fname
)) {
416 return NT_STATUS_INVALID_PARAMETER
;
419 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
422 /****************************************************************************
423 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
425 ****************************************************************************/
427 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
428 connection_struct
*conn
, struct ea_list
*ea_list
)
430 unsigned int ret_data_size
= 4;
433 SMB_ASSERT(total_data_size
>= 4);
435 if (!lp_ea_support(SNUM(conn
))) {
440 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
443 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
444 dos_namelen
= strlen(dos_ea_name
);
445 if (dos_namelen
> 255 || dos_namelen
== 0) {
448 if (ea_list
->ea
.value
.length
> 65535) {
451 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
455 /* We know we have room. */
456 SCVAL(p
,0,ea_list
->ea
.flags
);
457 SCVAL(p
,1,dos_namelen
);
458 SSVAL(p
,2,ea_list
->ea
.value
.length
);
459 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
460 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
462 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
463 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
466 ret_data_size
= PTR_DIFF(p
, pdata
);
467 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
468 SIVAL(pdata
,0,ret_data_size
);
469 return ret_data_size
;
472 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
474 unsigned int total_data_size
,
475 unsigned int *ret_data_size
,
476 connection_struct
*conn
,
477 struct ea_list
*ea_list
)
479 uint8_t *p
= (uint8_t *)pdata
;
480 uint8_t *last_start
= NULL
;
481 bool do_store_data
= (pdata
!= NULL
);
485 if (!lp_ea_support(SNUM(conn
))) {
486 return NT_STATUS_NO_EAS_ON_FILE
;
489 for (; ea_list
; ea_list
= ea_list
->next
) {
495 if (last_start
!= NULL
&& do_store_data
) {
496 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
500 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
501 dos_namelen
= strlen(dos_ea_name
);
502 if (dos_namelen
> 255 || dos_namelen
== 0) {
503 return NT_STATUS_INTERNAL_ERROR
;
505 if (ea_list
->ea
.value
.length
> 65535) {
506 return NT_STATUS_INTERNAL_ERROR
;
509 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
512 pad
= (4 - (this_size
% 4)) % 4;
517 if (this_size
> total_data_size
) {
518 return NT_STATUS_INFO_LENGTH_MISMATCH
;
521 /* We know we have room. */
522 SIVAL(p
, 0x00, 0); /* next offset */
523 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
524 SCVAL(p
, 0x05, dos_namelen
);
525 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
526 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
527 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
529 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
533 total_data_size
-= this_size
;
539 *ret_data_size
= PTR_DIFF(p
, pdata
);
540 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
544 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
546 size_t total_ea_len
= 0;
548 struct ea_list
*ea_list
= NULL
;
550 if (!lp_ea_support(SNUM(conn
))) {
553 mem_ctx
= talloc_stackframe();
555 /* If this is a stream fsp, then we need to instead find the
556 * estimated ea len from the main file, not the stream
557 * (streams cannot have EAs), but the estimate isn't just 0 in
559 if (is_ntfs_stream_smb_fname(smb_fname
)) {
562 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
563 if(conn
->sconn
->using_smb2
) {
565 unsigned int ret_data_size
;
567 * We're going to be using fill_ea_chained_buffer() to
568 * marshall EA's - this size is significantly larger
569 * than the SMB1 buffer. Re-calculate the size without
572 status
= fill_ea_chained_buffer(mem_ctx
,
578 if (!NT_STATUS_IS_OK(status
)) {
581 total_ea_len
= ret_data_size
;
583 TALLOC_FREE(mem_ctx
);
587 /****************************************************************************
588 Ensure the EA name is case insensitive by matching any existing EA name.
589 ****************************************************************************/
591 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
594 TALLOC_CTX
*mem_ctx
= talloc_tos();
595 struct ea_list
*ea_list
;
596 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
597 if (!NT_STATUS_IS_OK(status
)) {
601 for (; ea_list
; ea_list
= ea_list
->next
) {
602 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
603 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
604 &unix_ea_name
[5], ea_list
->ea
.name
));
605 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
611 /****************************************************************************
612 Set or delete an extended attribute.
613 ****************************************************************************/
615 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
616 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
621 if (!lp_ea_support(SNUM(conn
))) {
622 return NT_STATUS_EAS_NOT_SUPPORTED
;
625 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
626 if (!NT_STATUS_IS_OK(status
)) {
630 /* Setting EAs on streams isn't supported. */
631 if (is_ntfs_stream_smb_fname(smb_fname
)) {
632 return NT_STATUS_INVALID_PARAMETER
;
636 * Filter out invalid Windows EA names - before
637 * we set *any* of them.
640 if (ea_list_has_invalid_name(ea_list
)) {
641 return STATUS_INVALID_EA_NAME
;
644 fname
= smb_fname
->base_name
;
646 for (;ea_list
; ea_list
= ea_list
->next
) {
648 fstring unix_ea_name
;
650 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
651 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
653 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
655 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
657 if (samba_private_attr_name(unix_ea_name
)) {
658 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
659 return NT_STATUS_ACCESS_DENIED
;
662 if (ea_list
->ea
.value
.length
== 0) {
663 /* Remove the attribute. */
664 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
665 DEBUG(10,("set_ea: deleting ea name %s on "
666 "file %s by file descriptor.\n",
667 unix_ea_name
, fsp_str_dbg(fsp
)));
668 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
670 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
671 unix_ea_name
, fname
));
672 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
675 /* Removing a non existent attribute always succeeds. */
676 if (ret
== -1 && errno
== ENOATTR
) {
677 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
683 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
684 DEBUG(10,("set_ea: setting ea name %s on file "
685 "%s by file descriptor.\n",
686 unix_ea_name
, fsp_str_dbg(fsp
)));
687 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
688 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
690 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
691 unix_ea_name
, fname
));
692 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
693 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
699 if (errno
== ENOTSUP
) {
700 return NT_STATUS_EAS_NOT_SUPPORTED
;
703 return map_nt_error_from_unix(errno
);
709 /****************************************************************************
710 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
711 ****************************************************************************/
713 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
715 struct ea_list
*ea_list_head
= NULL
;
716 size_t converted_size
, offset
= 0;
718 while (offset
+ 2 < data_size
) {
719 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
720 unsigned int namelen
= CVAL(pdata
,offset
);
722 offset
++; /* Go past the namelen byte. */
724 /* integer wrap paranioa. */
725 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
726 (offset
> data_size
) || (namelen
> data_size
) ||
727 (offset
+ namelen
>= data_size
)) {
730 /* Ensure the name is null terminated. */
731 if (pdata
[offset
+ namelen
] != '\0') {
734 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
736 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
737 "failed: %s", strerror(errno
)));
743 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
744 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
745 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
751 /****************************************************************************
752 Read one EA list entry from the buffer.
753 ****************************************************************************/
755 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
757 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
759 unsigned int namelen
;
760 size_t converted_size
;
770 eal
->ea
.flags
= CVAL(pdata
,0);
771 namelen
= CVAL(pdata
,1);
772 val_len
= SVAL(pdata
,2);
774 if (4 + namelen
+ 1 + val_len
> data_size
) {
778 /* Ensure the name is null terminated. */
779 if (pdata
[namelen
+ 4] != '\0') {
782 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
783 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
790 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
791 if (!eal
->ea
.value
.data
) {
795 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
797 /* Ensure we're null terminated just in case we print the value. */
798 eal
->ea
.value
.data
[val_len
] = '\0';
799 /* But don't count the null. */
800 eal
->ea
.value
.length
--;
803 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
806 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
807 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
818 struct ea_list
*ea_list_head
= NULL
;
820 size_t bytes_used
= 0;
822 while (offset
< data_size
) {
823 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
829 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
830 offset
+= bytes_used
;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list
*ealist
)
843 struct ea_list
*listp
;
846 for (listp
= ealist
; listp
; listp
= listp
->next
) {
847 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
848 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
850 /* Add on 4 for total length. */
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
866 struct ea_list
*nlistp
, *flistp
;
868 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
869 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
870 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
876 /* Copy the data from this entry. */
877 nlistp
->ea
.flags
= flistp
->ea
.flags
;
878 nlistp
->ea
.value
= flistp
->ea
.value
;
881 nlistp
->ea
.flags
= 0;
882 ZERO_STRUCT(nlistp
->ea
.value
);
886 *total_ea_len
= ea_list_size(name_list
);
890 /****************************************************************************
891 Send the required number of replies back.
892 We assume all fields other than the data fields are
893 set correctly for the type of call.
894 HACK ! Always assumes smb_setup field is zero.
895 ****************************************************************************/
897 void send_trans2_replies(connection_struct
*conn
,
898 struct smb_request
*req
,
906 /* As we are using a protocol > LANMAN1 then the max_send
907 variable must have been set in the sessetupX call.
908 This takes precedence over the max_xmit field in the
909 global struct. These different max_xmit variables should
910 be merged as this is now too confusing */
912 int data_to_send
= datasize
;
913 int params_to_send
= paramsize
;
915 const char *pp
= params
;
916 const char *pd
= pdata
;
917 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
918 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
919 int data_alignment_offset
= 0;
920 bool overflow
= False
;
921 struct smbd_server_connection
*sconn
= req
->sconn
;
922 int max_send
= sconn
->smb1
.sessions
.max_send
;
924 /* Modify the data_to_send and datasize and set the error if
925 we're trying to send more than max_data_bytes. We still send
926 the part of the packet(s) that fit. Strange, but needed
929 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
930 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
931 max_data_bytes
, datasize
));
932 datasize
= data_to_send
= max_data_bytes
;
936 /* If there genuinely are no parameters or data to send just send the empty packet */
938 if(params_to_send
== 0 && data_to_send
== 0) {
939 reply_outbuf(req
, 10, 0);
940 if (NT_STATUS_V(status
)) {
943 ntstatus_to_dos(status
, &eclass
, &ecode
);
944 error_packet_set((char *)req
->outbuf
,
945 eclass
, ecode
, status
,
948 show_msg((char *)req
->outbuf
);
949 if (!srv_send_smb(sconn
,
952 IS_CONN_ENCRYPTED(conn
),
954 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
956 TALLOC_FREE(req
->outbuf
);
960 /* When sending params and data ensure that both are nicely aligned */
961 /* Only do this alignment when there is also data to send - else
962 can cause NT redirector problems. */
964 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
965 data_alignment_offset
= 4 - (params_to_send
% 4);
967 /* Space is bufsize minus Netbios over TCP header minus SMB header */
968 /* The alignment_offset is to align the param bytes on an even byte
969 boundary. NT 4.0 Beta needs this to work correctly. */
971 useable_space
= max_send
- (smb_size
974 + data_alignment_offset
);
976 if (useable_space
< 0) {
977 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
978 "= %d!!!", useable_space
));
979 exit_server_cleanly("send_trans2_replies: Not enough space");
982 while (params_to_send
|| data_to_send
) {
983 /* Calculate whether we will totally or partially fill this packet */
985 total_sent_thistime
= params_to_send
+ data_to_send
;
987 /* We can never send more than useable_space */
989 * Note that 'useable_space' does not include the alignment offsets,
990 * but we must include the alignment offsets in the calculation of
991 * the length of the data we send over the wire, as the alignment offsets
992 * are sent here. Fix from Marc_Jacobsen@hp.com.
995 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
997 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
998 + data_alignment_offset
);
1000 /* Set total params and data to be sent */
1001 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1002 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1004 /* Calculate how many parameters and data we can fit into
1005 * this packet. Parameters get precedence
1008 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1009 data_sent_thistime
= useable_space
- params_sent_thistime
;
1010 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1012 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1014 /* smb_proff is the offset from the start of the SMB header to the
1015 parameter bytes, however the first 4 bytes of outbuf are
1016 the Netbios over TCP header. Thus use smb_base() to subtract
1017 them from the calculation */
1019 SSVAL(req
->outbuf
,smb_proff
,
1020 ((smb_buf(req
->outbuf
)+alignment_offset
)
1021 - smb_base(req
->outbuf
)));
1023 if(params_sent_thistime
== 0)
1024 SSVAL(req
->outbuf
,smb_prdisp
,0);
1026 /* Absolute displacement of param bytes sent in this packet */
1027 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1029 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1030 if(data_sent_thistime
== 0) {
1031 SSVAL(req
->outbuf
,smb_droff
,0);
1032 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1034 /* The offset of the data bytes is the offset of the
1035 parameter bytes plus the number of parameters being sent this time */
1036 SSVAL(req
->outbuf
, smb_droff
,
1037 ((smb_buf(req
->outbuf
)+alignment_offset
)
1038 - smb_base(req
->outbuf
))
1039 + params_sent_thistime
+ data_alignment_offset
);
1040 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1043 /* Initialize the padding for alignment */
1045 if (alignment_offset
!= 0) {
1046 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1049 /* Copy the param bytes into the packet */
1051 if(params_sent_thistime
) {
1052 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1053 params_sent_thistime
);
1056 /* Copy in the data bytes */
1057 if(data_sent_thistime
) {
1058 if (data_alignment_offset
!= 0) {
1059 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1060 params_sent_thistime
), 0,
1061 data_alignment_offset
);
1063 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1064 +params_sent_thistime
+data_alignment_offset
,
1065 pd
,data_sent_thistime
);
1068 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1069 params_sent_thistime
, data_sent_thistime
, useable_space
));
1070 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1071 params_to_send
, data_to_send
, paramsize
, datasize
));
1074 error_packet_set((char *)req
->outbuf
,
1075 ERRDOS
,ERRbufferoverflow
,
1076 STATUS_BUFFER_OVERFLOW
,
1078 } else if (NT_STATUS_V(status
)) {
1081 ntstatus_to_dos(status
, &eclass
, &ecode
);
1082 error_packet_set((char *)req
->outbuf
,
1083 eclass
, ecode
, status
,
1087 /* Send the packet */
1088 show_msg((char *)req
->outbuf
);
1089 if (!srv_send_smb(sconn
,
1090 (char *)req
->outbuf
,
1091 true, req
->seqnum
+1,
1092 IS_CONN_ENCRYPTED(conn
),
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req
->outbuf
);
1098 pp
+= params_sent_thistime
;
1099 pd
+= data_sent_thistime
;
1101 params_to_send
-= params_sent_thistime
;
1102 data_to_send
-= data_sent_thistime
;
1105 if(params_to_send
< 0 || data_to_send
< 0) {
1106 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1107 params_to_send
, data_to_send
));
1115 /****************************************************************************
1116 Reply to a TRANSACT2_OPEN.
1117 ****************************************************************************/
1119 static void call_trans2open(connection_struct
*conn
,
1120 struct smb_request
*req
,
1121 char **pparams
, int total_params
,
1122 char **ppdata
, int total_data
,
1123 unsigned int max_data_bytes
)
1125 struct smb_filename
*smb_fname
= NULL
;
1126 char *params
= *pparams
;
1127 char *pdata
= *ppdata
;
1130 bool oplock_request
;
1132 bool return_additional_info
;
1141 int fattr
=0,mtime
=0;
1142 SMB_INO_T inode
= 0;
1145 struct ea_list
*ea_list
= NULL
;
1150 uint32 create_disposition
;
1151 uint32 create_options
= 0;
1152 uint32_t private_flags
= 0;
1153 TALLOC_CTX
*ctx
= talloc_tos();
1156 * Ensure we have enough parameters to perform the operation.
1159 if (total_params
< 29) {
1160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1164 flags
= SVAL(params
, 0);
1165 deny_mode
= SVAL(params
, 2);
1166 open_attr
= SVAL(params
,6);
1167 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1168 if (oplock_request
) {
1169 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1173 return_additional_info
= BITSETW(params
,0);
1174 open_sattr
= SVAL(params
, 4);
1175 open_time
= make_unix_date3(params
+8);
1177 open_ofun
= SVAL(params
,12);
1178 open_size
= IVAL(params
,14);
1179 pname
= ¶ms
[28];
1182 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1186 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1187 total_params
- 28, STR_TERMINATE
,
1189 if (!NT_STATUS_IS_OK(status
)) {
1190 reply_nterror(req
, status
);
1194 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1195 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1196 (unsigned int)open_ofun
, open_size
));
1198 status
= filename_convert(ctx
,
1200 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1205 if (!NT_STATUS_IS_OK(status
)) {
1206 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1207 reply_botherror(req
,
1208 NT_STATUS_PATH_NOT_COVERED
,
1209 ERRSRV
, ERRbadpath
);
1212 reply_nterror(req
, status
);
1216 if (open_ofun
== 0) {
1217 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1221 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1223 &access_mask
, &share_mode
,
1224 &create_disposition
,
1227 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1231 /* Any data in this call is an EA list. */
1232 if (total_data
&& (total_data
!= 4)) {
1233 if (total_data
< 10) {
1234 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1238 if (IVAL(pdata
,0) > total_data
) {
1239 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1240 IVAL(pdata
,0), (unsigned int)total_data
));
1241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1245 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1252 if (!lp_ea_support(SNUM(conn
))) {
1253 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1257 if (ea_list_has_invalid_name(ea_list
)) {
1259 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1260 if(*pparams
== NULL
) {
1261 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1265 memset(params
, '\0', param_len
);
1266 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1267 params
, param_len
, NULL
, 0, max_data_bytes
);
1272 status
= SMB_VFS_CREATE_FILE(
1275 0, /* root_dir_fid */
1276 smb_fname
, /* fname */
1277 access_mask
, /* access_mask */
1278 share_mode
, /* share_access */
1279 create_disposition
, /* create_disposition*/
1280 create_options
, /* create_options */
1281 open_attr
, /* file_attributes */
1282 oplock_request
, /* oplock_request */
1283 open_size
, /* allocation_size */
1286 ea_list
, /* ea_list */
1288 &smb_action
); /* psbuf */
1290 if (!NT_STATUS_IS_OK(status
)) {
1291 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1292 /* We have re-scheduled this call. */
1295 reply_openerror(req
, status
);
1299 size
= get_file_size_stat(&smb_fname
->st
);
1300 fattr
= dos_mode(conn
, smb_fname
);
1301 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1302 inode
= smb_fname
->st
.st_ex_ino
;
1303 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1304 close_file(req
, fsp
, ERROR_CLOSE
);
1305 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1309 /* Realloc the size of parameters and data we will return */
1310 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1311 if(*pparams
== NULL
) {
1312 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1317 SSVAL(params
,0,fsp
->fnum
);
1318 SSVAL(params
,2,fattr
);
1319 srv_put_dos_date2(params
,4, mtime
);
1320 SIVAL(params
,8, (uint32
)size
);
1321 SSVAL(params
,12,deny_mode
);
1322 SSVAL(params
,14,0); /* open_type - file or directory. */
1323 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1325 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1326 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1329 SSVAL(params
,18,smb_action
);
1332 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1334 SIVAL(params
,20,inode
);
1335 SSVAL(params
,24,0); /* Padding. */
1337 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1339 SIVAL(params
, 26, ea_size
);
1341 SIVAL(params
, 26, 0);
1344 /* Send the required number of replies */
1345 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1347 TALLOC_FREE(smb_fname
);
1350 /*********************************************************
1351 Routine to check if a given string matches exactly.
1352 as a special case a mask of "." does NOT match. That
1353 is required for correct wildcard semantics
1354 Case can be significant or not.
1355 **********************************************************/
1357 static bool exact_match(bool has_wild
,
1358 bool case_sensitive
,
1362 if (mask
[0] == '.' && mask
[1] == 0) {
1370 if (case_sensitive
) {
1371 return strcmp(str
,mask
)==0;
1373 return strcasecmp_m(str
,mask
) == 0;
1377 /****************************************************************************
1378 Return the filetype for UNIX extensions.
1379 ****************************************************************************/
1381 static uint32
unix_filetype(mode_t mode
)
1384 return UNIX_TYPE_FILE
;
1385 else if(S_ISDIR(mode
))
1386 return UNIX_TYPE_DIR
;
1388 else if(S_ISLNK(mode
))
1389 return UNIX_TYPE_SYMLINK
;
1392 else if(S_ISCHR(mode
))
1393 return UNIX_TYPE_CHARDEV
;
1396 else if(S_ISBLK(mode
))
1397 return UNIX_TYPE_BLKDEV
;
1400 else if(S_ISFIFO(mode
))
1401 return UNIX_TYPE_FIFO
;
1404 else if(S_ISSOCK(mode
))
1405 return UNIX_TYPE_SOCKET
;
1408 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1409 return UNIX_TYPE_UNKNOWN
;
1412 /****************************************************************************
1413 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1414 ****************************************************************************/
1416 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1418 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1419 const SMB_STRUCT_STAT
*psbuf
,
1421 enum perm_type ptype
,
1426 if (perms
== SMB_MODE_NO_CHANGE
) {
1427 if (!VALID_STAT(*psbuf
)) {
1428 return NT_STATUS_INVALID_PARAMETER
;
1430 *ret_perms
= psbuf
->st_ex_mode
;
1431 return NT_STATUS_OK
;
1435 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1436 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1437 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1438 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1439 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1440 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1441 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1442 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1443 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1445 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1448 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1451 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1456 case PERM_EXISTING_FILE
:
1457 /* Apply mode mask */
1458 ret
&= lp_create_mask(SNUM(conn
));
1459 /* Add in force bits */
1460 ret
|= lp_force_create_mode(SNUM(conn
));
1463 case PERM_EXISTING_DIR
:
1464 ret
&= lp_dir_mask(SNUM(conn
));
1465 /* Add in force bits */
1466 ret
|= lp_force_dir_mode(SNUM(conn
));
1471 return NT_STATUS_OK
;
1474 /****************************************************************************
1475 Needed to show the msdfs symlinks as directories. Modifies psbuf
1476 to be a directory if it's a msdfs link.
1477 ****************************************************************************/
1479 static bool check_msdfs_link(connection_struct
*conn
,
1480 const char *pathname
,
1481 SMB_STRUCT_STAT
*psbuf
)
1483 int saved_errno
= errno
;
1484 if(lp_host_msdfs() &&
1485 lp_msdfs_root(SNUM(conn
)) &&
1486 is_msdfs_link(conn
, pathname
, psbuf
)) {
1488 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1491 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1492 errno
= saved_errno
;
1495 errno
= saved_errno
;
1500 /****************************************************************************
1501 Get a level dependent lanman2 dir entry.
1502 ****************************************************************************/
1504 struct smbd_dirptr_lanman2_state
{
1505 connection_struct
*conn
;
1506 uint32_t info_level
;
1507 bool check_mangled_names
;
1509 bool got_exact_match
;
1512 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1518 struct smbd_dirptr_lanman2_state
*state
=
1519 (struct smbd_dirptr_lanman2_state
*)private_data
;
1521 char mangled_name
[13]; /* mangled 8.3 name. */
1525 /* Mangle fname if it's an illegal name. */
1526 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1527 ok
= name_to_8_3(dname
, mangled_name
,
1528 true, state
->conn
->params
);
1532 fname
= mangled_name
;
1537 got_match
= exact_match(state
->has_wild
,
1538 state
->conn
->case_sensitive
,
1540 state
->got_exact_match
= got_match
;
1542 got_match
= mask_match(fname
, mask
,
1543 state
->conn
->case_sensitive
);
1546 if(!got_match
&& state
->check_mangled_names
&&
1547 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1549 * It turns out that NT matches wildcards against
1550 * both long *and* short names. This may explain some
1551 * of the wildcard wierdness from old DOS clients
1552 * that some people have been seeing.... JRA.
1554 /* Force the mangling into 8.3. */
1555 ok
= name_to_8_3(fname
, mangled_name
,
1556 false, state
->conn
->params
);
1561 got_match
= exact_match(state
->has_wild
,
1562 state
->conn
->case_sensitive
,
1563 mangled_name
, mask
);
1564 state
->got_exact_match
= got_match
;
1566 got_match
= mask_match(mangled_name
, mask
,
1567 state
->conn
->case_sensitive
);
1575 *_fname
= talloc_strdup(ctx
, fname
);
1576 if (*_fname
== NULL
) {
1583 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1585 struct smb_filename
*smb_fname
,
1588 struct smbd_dirptr_lanman2_state
*state
=
1589 (struct smbd_dirptr_lanman2_state
*)private_data
;
1590 bool ms_dfs_link
= false;
1593 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1594 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1595 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1596 "Couldn't lstat [%s] (%s)\n",
1597 smb_fname_str_dbg(smb_fname
),
1601 } else if (!VALID_STAT(smb_fname
->st
) &&
1602 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1603 /* Needed to show the msdfs symlinks as
1606 ms_dfs_link
= check_msdfs_link(state
->conn
,
1607 smb_fname
->base_name
,
1610 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1611 "Couldn't stat [%s] (%s)\n",
1612 smb_fname_str_dbg(smb_fname
),
1619 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1621 mode
= dos_mode(state
->conn
, smb_fname
);
1628 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1629 connection_struct
*conn
,
1631 uint32_t info_level
,
1632 struct ea_list
*name_list
,
1633 bool check_mangled_names
,
1634 bool requires_resume_key
,
1637 const struct smb_filename
*smb_fname
,
1638 int space_remaining
,
1645 uint64_t *last_entry_off
)
1647 char *p
, *q
, *pdata
= *ppdata
;
1649 uint64_t file_size
= 0;
1650 uint64_t allocation_size
= 0;
1651 uint64_t file_index
= 0;
1653 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1654 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1656 char *last_entry_ptr
;
1661 *out_of_space
= false;
1663 ZERO_STRUCT(mdate_ts
);
1664 ZERO_STRUCT(adate_ts
);
1665 ZERO_STRUCT(create_date_ts
);
1666 ZERO_STRUCT(cdate_ts
);
1668 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1669 file_size
= get_file_size_stat(&smb_fname
->st
);
1671 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1673 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1675 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1676 adate_ts
= smb_fname
->st
.st_ex_atime
;
1677 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1678 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1680 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1681 dos_filetime_timespec(&create_date_ts
);
1682 dos_filetime_timespec(&mdate_ts
);
1683 dos_filetime_timespec(&adate_ts
);
1684 dos_filetime_timespec(&cdate_ts
);
1687 create_date
= convert_timespec_to_time_t(create_date_ts
);
1688 mdate
= convert_timespec_to_time_t(mdate_ts
);
1689 adate
= convert_timespec_to_time_t(adate_ts
);
1691 /* align the record */
1692 SMB_ASSERT(align
>= 1);
1694 off
= (int)PTR_DIFF(pdata
, base_data
);
1695 pad
= (off
+ (align
-1)) & ~(align
-1);
1698 if (pad
&& pad
> space_remaining
) {
1699 *out_of_space
= true;
1700 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1701 "for padding (wanted %u, had %d)\n",
1704 return false; /* Not finished - just out of space */
1708 /* initialize padding to 0 */
1710 memset(pdata
, 0, pad
);
1712 space_remaining
-= pad
;
1714 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1724 switch (info_level
) {
1725 case SMB_FIND_INFO_STANDARD
:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1727 if(requires_resume_key
) {
1731 srv_put_dos_date2(p
,0,create_date
);
1732 srv_put_dos_date2(p
,4,adate
);
1733 srv_put_dos_date2(p
,8,mdate
);
1734 SIVAL(p
,12,(uint32
)file_size
);
1735 SIVAL(p
,16,(uint32
)allocation_size
);
1739 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1740 p
+= ucs2_align(base_data
, p
, 0);
1742 len
= srvstr_push(base_data
, flags2
, p
,
1743 fname
, PTR_DIFF(end_data
, p
),
1745 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1747 SCVAL(nameptr
, -1, len
- 2);
1749 SCVAL(nameptr
, -1, 0);
1753 SCVAL(nameptr
, -1, len
- 1);
1755 SCVAL(nameptr
, -1, 0);
1761 case SMB_FIND_EA_SIZE
:
1762 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1763 if (requires_resume_key
) {
1767 srv_put_dos_date2(p
,0,create_date
);
1768 srv_put_dos_date2(p
,4,adate
);
1769 srv_put_dos_date2(p
,8,mdate
);
1770 SIVAL(p
,12,(uint32
)file_size
);
1771 SIVAL(p
,16,(uint32
)allocation_size
);
1774 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1776 SIVAL(p
,22,ea_size
); /* Extended attributes */
1780 len
= srvstr_push(base_data
, flags2
,
1781 p
, fname
, PTR_DIFF(end_data
, p
),
1782 STR_TERMINATE
| STR_NOALIGN
);
1783 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1796 SCVAL(nameptr
,0,len
);
1798 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1801 case SMB_FIND_EA_LIST
:
1803 struct ea_list
*file_list
= NULL
;
1807 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1811 if (requires_resume_key
) {
1815 srv_put_dos_date2(p
,0,create_date
);
1816 srv_put_dos_date2(p
,4,adate
);
1817 srv_put_dos_date2(p
,8,mdate
);
1818 SIVAL(p
,12,(uint32
)file_size
);
1819 SIVAL(p
,16,(uint32
)allocation_size
);
1821 p
+= 22; /* p now points to the EA area. */
1823 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1825 &ea_len
, &file_list
);
1826 if (!NT_STATUS_IS_OK(status
)) {
1829 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1831 /* We need to determine if this entry will fit in the space available. */
1832 /* Max string size is 255 bytes. */
1833 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1834 *out_of_space
= true;
1835 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1836 "(wanted %u, had %d)\n",
1837 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1839 return False
; /* Not finished - just out of space */
1842 /* Push the ea_data followed by the name. */
1843 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1845 len
= srvstr_push(base_data
, flags2
,
1846 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1847 STR_TERMINATE
| STR_NOALIGN
);
1848 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1861 SCVAL(nameptr
,0,len
);
1863 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1867 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1868 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1869 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1871 SIVAL(p
,0,reskey
); p
+= 4;
1872 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1873 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1874 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1876 SOFF_T(p
,0,file_size
); p
+= 8;
1877 SOFF_T(p
,0,allocation_size
); p
+= 8;
1878 SIVAL(p
,0,mode
); p
+= 4;
1879 q
= p
; p
+= 4; /* q is placeholder for name length. */
1881 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1883 SIVAL(p
,0,ea_size
); /* Extended attributes */
1886 /* Clear the short name buffer. This is
1887 * IMPORTANT as not doing so will trigger
1888 * a Win2k client bug. JRA.
1890 if (!was_8_3
&& check_mangled_names
) {
1891 char mangled_name
[13]; /* mangled 8.3 name. */
1892 if (!name_to_8_3(fname
,mangled_name
,True
,
1894 /* Error - mangle failed ! */
1895 memset(mangled_name
,'\0',12);
1897 mangled_name
[12] = 0;
1898 len
= srvstr_push(base_data
, flags2
,
1899 p
+2, mangled_name
, 24,
1900 STR_UPPER
|STR_UNICODE
);
1902 memset(p
+ 2 + len
,'\0',24 - len
);
1909 len
= srvstr_push(base_data
, flags2
, p
,
1910 fname
, PTR_DIFF(end_data
, p
),
1911 STR_TERMINATE_ASCII
);
1915 len
= PTR_DIFF(p
, pdata
);
1916 pad
= (len
+ (align
-1)) & ~(align
-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1924 * set padding to zero
1927 memset(p
, 0, pad
- len
);
1934 case SMB_FIND_FILE_DIRECTORY_INFO
:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1937 SIVAL(p
,0,reskey
); p
+= 4;
1938 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1939 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1940 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1941 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1942 SOFF_T(p
,0,file_size
); p
+= 8;
1943 SOFF_T(p
,0,allocation_size
); p
+= 8;
1944 SIVAL(p
,0,mode
); p
+= 4;
1945 len
= srvstr_push(base_data
, flags2
,
1946 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1947 STR_TERMINATE_ASCII
);
1951 len
= PTR_DIFF(p
, pdata
);
1952 pad
= (len
+ (align
-1)) & ~(align
-1);
1954 * offset to the next entry, the caller
1955 * will overwrite it for the last entry
1956 * that's why we always include the padding
1960 * set padding to zero
1963 memset(p
, 0, pad
- len
);
1970 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1971 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1973 SIVAL(p
,0,reskey
); p
+= 4;
1974 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1975 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1976 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1977 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1978 SOFF_T(p
,0,file_size
); p
+= 8;
1979 SOFF_T(p
,0,allocation_size
); p
+= 8;
1980 SIVAL(p
,0,mode
); p
+= 4;
1981 q
= p
; p
+= 4; /* q is placeholder for name length. */
1983 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1985 SIVAL(p
,0,ea_size
); /* Extended attributes */
1988 len
= srvstr_push(base_data
, flags2
, p
,
1989 fname
, PTR_DIFF(end_data
, p
),
1990 STR_TERMINATE_ASCII
);
1994 len
= PTR_DIFF(p
, pdata
);
1995 pad
= (len
+ (align
-1)) & ~(align
-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2003 * set padding to zero
2006 memset(p
, 0, pad
- len
);
2013 case SMB_FIND_FILE_NAMES_INFO
:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2016 SIVAL(p
,0,reskey
); p
+= 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 len
= srvstr_push(base_data
, flags2
, p
,
2021 fname
, PTR_DIFF(end_data
, p
),
2022 STR_TERMINATE_ASCII
);
2026 len
= PTR_DIFF(p
, pdata
);
2027 pad
= (len
+ (align
-1)) & ~(align
-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2035 * set padding to zero
2038 memset(p
, 0, pad
- len
);
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2048 SIVAL(p
,0,reskey
); p
+= 4;
2049 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2050 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2051 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2052 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2053 SOFF_T(p
,0,file_size
); p
+= 8;
2054 SOFF_T(p
,0,allocation_size
); p
+= 8;
2055 SIVAL(p
,0,mode
); p
+= 4;
2056 q
= p
; p
+= 4; /* q is placeholder for name length. */
2058 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2060 SIVAL(p
,0,ea_size
); /* Extended attributes */
2063 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2064 SBVAL(p
,0,file_index
); p
+= 8;
2065 len
= srvstr_push(base_data
, flags2
, p
,
2066 fname
, PTR_DIFF(end_data
, p
),
2067 STR_TERMINATE_ASCII
);
2071 len
= PTR_DIFF(p
, pdata
);
2072 pad
= (len
+ (align
-1)) & ~(align
-1);
2074 * offset to the next entry, the caller
2075 * will overwrite it for the last entry
2076 * that's why we always include the padding
2080 * set padding to zero
2083 memset(p
, 0, pad
- len
);
2090 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2092 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2094 SIVAL(p
,0,reskey
); p
+= 4;
2095 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2096 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2097 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2098 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2099 SOFF_T(p
,0,file_size
); p
+= 8;
2100 SOFF_T(p
,0,allocation_size
); p
+= 8;
2101 SIVAL(p
,0,mode
); p
+= 4;
2102 q
= p
; p
+= 4; /* q is placeholder for name length */
2104 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2106 SIVAL(p
,0,ea_size
); /* Extended attributes */
2109 /* Clear the short name buffer. This is
2110 * IMPORTANT as not doing so will trigger
2111 * a Win2k client bug. JRA.
2113 if (!was_8_3
&& check_mangled_names
) {
2114 char mangled_name
[13]; /* mangled 8.3 name. */
2115 if (!name_to_8_3(fname
,mangled_name
,True
,
2117 /* Error - mangle failed ! */
2118 memset(mangled_name
,'\0',12);
2120 mangled_name
[12] = 0;
2121 len
= srvstr_push(base_data
, flags2
,
2122 p
+2, mangled_name
, 24,
2123 STR_UPPER
|STR_UNICODE
);
2126 memset(p
+ 2 + len
,'\0',24 - len
);
2133 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2134 SBVAL(p
,0,file_index
); p
+= 8;
2135 len
= srvstr_push(base_data
, flags2
, p
,
2136 fname
, PTR_DIFF(end_data
, p
),
2137 STR_TERMINATE_ASCII
);
2141 len
= PTR_DIFF(p
, pdata
);
2142 pad
= (len
+ (align
-1)) & ~(align
-1);
2144 * offset to the next entry, the caller
2145 * will overwrite it for the last entry
2146 * that's why we always include the padding
2150 * set padding to zero
2153 memset(p
, 0, pad
- len
);
2160 /* CIFS UNIX Extension. */
2162 case SMB_FIND_FILE_UNIX
:
2163 case SMB_FIND_FILE_UNIX_INFO2
:
2165 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2167 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2169 if (info_level
== SMB_FIND_FILE_UNIX
) {
2170 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2171 p
= store_file_unix_basic(conn
, p
,
2172 NULL
, &smb_fname
->st
);
2173 len
= srvstr_push(base_data
, flags2
, p
,
2174 fname
, PTR_DIFF(end_data
, p
),
2177 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2178 p
= store_file_unix_basic_info2(conn
, p
,
2179 NULL
, &smb_fname
->st
);
2182 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2183 PTR_DIFF(end_data
, p
), 0);
2184 SIVAL(nameptr
, 0, len
);
2189 len
= PTR_DIFF(p
, pdata
);
2190 pad
= (len
+ (align
-1)) & ~(align
-1);
2192 * offset to the next entry, the caller
2193 * will overwrite it for the last entry
2194 * that's why we always include the padding
2198 * set padding to zero
2201 memset(p
, 0, pad
- len
);
2206 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2214 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2215 *out_of_space
= true;
2216 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2217 "(wanted %u, had %d)\n",
2218 (unsigned int)PTR_DIFF(p
,pdata
),
2220 return false; /* Not finished - just out of space */
2223 /* Setup the last entry pointer, as an offset from base_data */
2224 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2225 /* Advance the data pointer to the next slot */
2231 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2232 connection_struct
*conn
,
2233 struct dptr_struct
*dirptr
,
2235 const char *path_mask
,
2238 int requires_resume_key
,
2246 int space_remaining
,
2248 bool *got_exact_match
,
2249 int *_last_entry_off
,
2250 struct ea_list
*name_list
)
2253 const char *mask
= NULL
;
2254 long prev_dirpos
= 0;
2257 struct smb_filename
*smb_fname
= NULL
;
2258 struct smbd_dirptr_lanman2_state state
;
2260 uint64_t last_entry_off
= 0;
2264 state
.info_level
= info_level
;
2265 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2266 state
.has_wild
= dptr_has_wild(dirptr
);
2267 state
.got_exact_match
= false;
2269 *out_of_space
= false;
2270 *got_exact_match
= false;
2272 p
= strrchr_m(path_mask
,'/');
2283 ok
= smbd_dirptr_get_entry(ctx
,
2289 smbd_dirptr_lanman2_match_fn
,
2290 smbd_dirptr_lanman2_mode_fn
,
2300 *got_exact_match
= state
.got_exact_match
;
2302 ok
= smbd_marshall_dir_entry(ctx
,
2307 state
.check_mangled_names
,
2308 requires_resume_key
,
2321 TALLOC_FREE(smb_fname
);
2322 if (*out_of_space
) {
2323 dptr_SeekDir(dirptr
, prev_dirpos
);
2330 *_last_entry_off
= last_entry_off
;
2334 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2335 connection_struct
*conn
,
2336 struct dptr_struct
*dirptr
,
2338 const char *path_mask
,
2341 bool requires_resume_key
,
2347 int space_remaining
,
2349 bool *got_exact_match
,
2350 int *last_entry_off
,
2351 struct ea_list
*name_list
)
2354 const bool do_pad
= true;
2356 if (info_level
>= 1 && info_level
<= 3) {
2357 /* No alignment on earlier info levels. */
2361 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2362 path_mask
, dirtype
, info_level
,
2363 requires_resume_key
, dont_descend
, ask_sharemode
,
2365 ppdata
, base_data
, end_data
,
2367 out_of_space
, got_exact_match
,
2368 last_entry_off
, name_list
);
2371 /****************************************************************************
2372 Reply to a TRANS2_FINDFIRST.
2373 ****************************************************************************/
2375 static void call_trans2findfirst(connection_struct
*conn
,
2376 struct smb_request
*req
,
2377 char **pparams
, int total_params
,
2378 char **ppdata
, int total_data
,
2379 unsigned int max_data_bytes
)
2381 /* We must be careful here that we don't return more than the
2382 allowed number of data bytes. If this means returning fewer than
2383 maxentries then so be it. We assume that the redirector has
2384 enough room for the fixed number of parameter bytes it has
2386 struct smb_filename
*smb_dname
= NULL
;
2387 char *params
= *pparams
;
2388 char *pdata
= *ppdata
;
2392 uint16 findfirst_flags
;
2393 bool close_after_first
;
2395 bool requires_resume_key
;
2397 char *directory
= NULL
;
2400 int last_entry_off
=0;
2404 bool finished
= False
;
2405 bool dont_descend
= False
;
2406 bool out_of_space
= False
;
2407 int space_remaining
;
2408 bool mask_contains_wcard
= False
;
2409 struct ea_list
*ea_list
= NULL
;
2410 NTSTATUS ntstatus
= NT_STATUS_OK
;
2411 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2412 TALLOC_CTX
*ctx
= talloc_tos();
2413 struct dptr_struct
*dirptr
= NULL
;
2414 struct smbd_server_connection
*sconn
= req
->sconn
;
2415 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2416 bool backup_priv
= false;
2418 if (total_params
< 13) {
2419 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2423 dirtype
= SVAL(params
,0);
2424 maxentries
= SVAL(params
,2);
2425 findfirst_flags
= SVAL(params
,4);
2426 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2427 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2428 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2429 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2430 security_token_has_privilege(get_current_nttok(conn
),
2433 info_level
= SVAL(params
,6);
2435 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2436 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2437 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2439 info_level
, max_data_bytes
));
2442 /* W2K3 seems to treat zero as 1. */
2446 switch (info_level
) {
2447 case SMB_FIND_INFO_STANDARD
:
2448 case SMB_FIND_EA_SIZE
:
2449 case SMB_FIND_EA_LIST
:
2450 case SMB_FIND_FILE_DIRECTORY_INFO
:
2451 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2452 case SMB_FIND_FILE_NAMES_INFO
:
2453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2454 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2455 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2457 case SMB_FIND_FILE_UNIX
:
2458 case SMB_FIND_FILE_UNIX_INFO2
:
2459 /* Always use filesystem for UNIX mtime query. */
2460 ask_sharemode
= false;
2461 if (!lp_unix_extensions()) {
2462 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2465 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2468 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2472 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2473 params
+12, total_params
- 12,
2474 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2475 if (!NT_STATUS_IS_OK(ntstatus
)) {
2476 reply_nterror(req
, ntstatus
);
2482 ntstatus
= filename_convert_with_privilege(ctx
,
2487 &mask_contains_wcard
,
2490 ntstatus
= filename_convert(ctx
, conn
,
2491 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2494 &mask_contains_wcard
,
2498 if (!NT_STATUS_IS_OK(ntstatus
)) {
2499 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2500 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2501 ERRSRV
, ERRbadpath
);
2504 reply_nterror(req
, ntstatus
);
2508 mask
= smb_dname
->original_lcomp
;
2510 directory
= smb_dname
->base_name
;
2512 p
= strrchr_m(directory
,'/');
2514 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2515 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2516 mask
= talloc_strdup(ctx
,"*");
2518 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2521 mask_contains_wcard
= True
;
2527 if (p
== NULL
|| p
== directory
) {
2528 /* Ensure we don't have a directory name of "". */
2529 directory
= talloc_strdup(talloc_tos(), ".");
2531 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2536 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2538 if (info_level
== SMB_FIND_EA_LIST
) {
2541 if (total_data
< 4) {
2542 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2546 ea_size
= IVAL(pdata
,0);
2547 if (ea_size
!= total_data
) {
2548 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2549 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2550 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2554 if (!lp_ea_support(SNUM(conn
))) {
2555 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2559 /* Pull out the list of names. */
2560 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2567 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2568 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2572 *ppdata
= (char *)SMB_REALLOC(
2573 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2574 if(*ppdata
== NULL
) {
2575 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2579 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2581 /* Realloc the params space */
2582 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2583 if (*pparams
== NULL
) {
2584 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2589 /* Save the wildcard match and attribs we are using on this directory -
2590 needed as lanman2 assumes these are being saved between calls */
2592 ntstatus
= dptr_create(conn
,
2600 mask_contains_wcard
,
2604 if (!NT_STATUS_IS_OK(ntstatus
)) {
2605 reply_nterror(req
, ntstatus
);
2610 /* Remember this in case we have
2611 to do a findnext. */
2612 dptr_set_priv(dirptr
);
2615 dptr_num
= dptr_dnum(dirptr
);
2616 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2618 /* Initialize per TRANS2_FIND_FIRST operation data */
2619 dptr_init_search_op(dirptr
);
2621 /* We don't need to check for VOL here as this is returned by
2622 a different TRANS2 call. */
2624 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2625 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2626 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2627 dont_descend
= True
;
2630 space_remaining
= max_data_bytes
;
2631 out_of_space
= False
;
2633 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2634 bool got_exact_match
= False
;
2636 /* this is a heuristic to avoid seeking the dirptr except when
2637 absolutely necessary. It allows for a filename of about 40 chars */
2638 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2639 out_of_space
= True
;
2642 finished
= !get_lanman2_dir_entry(ctx
,
2646 mask
,dirtype
,info_level
,
2647 requires_resume_key
,dont_descend
,
2650 space_remaining
, &out_of_space
,
2652 &last_entry_off
, ea_list
);
2655 if (finished
&& out_of_space
)
2658 if (!finished
&& !out_of_space
)
2662 * As an optimisation if we know we aren't looking
2663 * for a wildcard name (ie. the name matches the wildcard exactly)
2664 * then we can finish on any (first) match.
2665 * This speeds up large directory searches. JRA.
2671 /* Ensure space_remaining never goes -ve. */
2672 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2673 space_remaining
= 0;
2674 out_of_space
= true;
2676 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2680 /* Check if we can close the dirptr */
2681 if(close_after_first
|| (finished
&& close_if_end
)) {
2682 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2683 dptr_close(sconn
, &dptr_num
);
2687 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2688 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2689 * the protocol level is less than NT1. Tested with smbclient. JRA.
2690 * This should fix the OS/2 client bug #2335.
2693 if(numentries
== 0) {
2694 dptr_close(sconn
, &dptr_num
);
2695 if (get_Protocol() < PROTOCOL_NT1
) {
2696 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2699 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2700 ERRDOS
, ERRbadfile
);
2705 /* At this point pdata points to numentries directory entries. */
2707 /* Set up the return parameter block */
2708 SSVAL(params
,0,dptr_num
);
2709 SSVAL(params
,2,numentries
);
2710 SSVAL(params
,4,finished
);
2711 SSVAL(params
,6,0); /* Never an EA error */
2712 SSVAL(params
,8,last_entry_off
);
2714 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2717 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2718 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2720 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2724 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2725 smb_fn_name(req
->cmd
),
2726 mask
, directory
, dirtype
, numentries
) );
2729 * Force a name mangle here to ensure that the
2730 * mask as an 8.3 name is top of the mangled cache.
2731 * The reasons for this are subtle. Don't remove
2732 * this code unless you know what you are doing
2733 * (see PR#13758). JRA.
2736 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2737 char mangled_name
[13];
2738 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2746 TALLOC_FREE(smb_dname
);
2750 /****************************************************************************
2751 Reply to a TRANS2_FINDNEXT.
2752 ****************************************************************************/
2754 static void call_trans2findnext(connection_struct
*conn
,
2755 struct smb_request
*req
,
2756 char **pparams
, int total_params
,
2757 char **ppdata
, int total_data
,
2758 unsigned int max_data_bytes
)
2760 /* We must be careful here that we don't return more than the
2761 allowed number of data bytes. If this means returning fewer than
2762 maxentries then so be it. We assume that the redirector has
2763 enough room for the fixed number of parameter bytes it has
2765 char *params
= *pparams
;
2766 char *pdata
= *ppdata
;
2772 uint16 findnext_flags
;
2773 bool close_after_request
;
2775 bool requires_resume_key
;
2777 bool mask_contains_wcard
= False
;
2778 char *resume_name
= NULL
;
2779 const char *mask
= NULL
;
2780 const char *directory
= NULL
;
2784 int i
, last_entry_off
=0;
2785 bool finished
= False
;
2786 bool dont_descend
= False
;
2787 bool out_of_space
= False
;
2788 int space_remaining
;
2789 struct ea_list
*ea_list
= NULL
;
2790 NTSTATUS ntstatus
= NT_STATUS_OK
;
2791 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2792 TALLOC_CTX
*ctx
= talloc_tos();
2793 struct dptr_struct
*dirptr
;
2794 struct smbd_server_connection
*sconn
= req
->sconn
;
2795 bool backup_priv
= false;
2797 if (total_params
< 13) {
2798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2802 dptr_num
= SVAL(params
,0);
2803 maxentries
= SVAL(params
,2);
2804 info_level
= SVAL(params
,4);
2805 resume_key
= IVAL(params
,6);
2806 findnext_flags
= SVAL(params
,10);
2807 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2808 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2809 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2810 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2812 if (!continue_bit
) {
2813 /* We only need resume_name if continue_bit is zero. */
2814 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2816 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2817 &mask_contains_wcard
);
2818 if (!NT_STATUS_IS_OK(ntstatus
)) {
2819 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2820 complain (it thinks we're asking for the directory above the shared
2821 path or an invalid name). Catch this as the resume name is only compared, never used in
2822 a file access. JRA. */
2823 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2824 &resume_name
, params
+12,
2828 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2829 reply_nterror(req
, ntstatus
);
2835 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2836 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2837 resume_key = %d resume name = %s continue=%d level = %d\n",
2838 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2839 requires_resume_key
, resume_key
,
2840 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2843 /* W2K3 seems to treat zero as 1. */
2847 switch (info_level
) {
2848 case SMB_FIND_INFO_STANDARD
:
2849 case SMB_FIND_EA_SIZE
:
2850 case SMB_FIND_EA_LIST
:
2851 case SMB_FIND_FILE_DIRECTORY_INFO
:
2852 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2853 case SMB_FIND_FILE_NAMES_INFO
:
2854 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2855 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2856 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2858 case SMB_FIND_FILE_UNIX
:
2859 case SMB_FIND_FILE_UNIX_INFO2
:
2860 /* Always use filesystem for UNIX mtime query. */
2861 ask_sharemode
= false;
2862 if (!lp_unix_extensions()) {
2863 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2868 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2872 if (info_level
== SMB_FIND_EA_LIST
) {
2875 if (total_data
< 4) {
2876 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2880 ea_size
= IVAL(pdata
,0);
2881 if (ea_size
!= total_data
) {
2882 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2883 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2884 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2888 if (!lp_ea_support(SNUM(conn
))) {
2889 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2893 /* Pull out the list of names. */
2894 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2901 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2902 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2906 *ppdata
= (char *)SMB_REALLOC(
2907 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2908 if(*ppdata
== NULL
) {
2909 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2914 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2916 /* Realloc the params space */
2917 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2918 if(*pparams
== NULL
) {
2919 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2925 /* Check that the dptr is valid */
2926 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2927 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2931 directory
= dptr_path(sconn
, dptr_num
);
2933 /* Get the wildcard mask from the dptr */
2934 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2935 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2936 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2940 /* Get the attr mask from the dptr */
2941 dirtype
= dptr_attr(sconn
, dptr_num
);
2943 backup_priv
= dptr_get_priv(dirptr
);
2945 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2946 "backup_priv = %d\n",
2947 dptr_num
, mask
, dirtype
,
2949 dptr_TellDir(dirptr
),
2952 /* Initialize per TRANS2_FIND_NEXT operation data */
2953 dptr_init_search_op(dirptr
);
2955 /* We don't need to check for VOL here as this is returned by
2956 a different TRANS2 call. */
2958 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2959 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2960 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2961 dont_descend
= True
;
2964 space_remaining
= max_data_bytes
;
2965 out_of_space
= False
;
2972 * Seek to the correct position. We no longer use the resume key but
2973 * depend on the last file name instead.
2976 if(!continue_bit
&& resume_name
&& *resume_name
) {
2979 long current_pos
= 0;
2981 * Remember, name_to_8_3 is called by
2982 * get_lanman2_dir_entry(), so the resume name
2983 * could be mangled. Ensure we check the unmangled name.
2986 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2987 char *new_resume_name
= NULL
;
2988 mangle_lookup_name_from_8_3(ctx
,
2992 if (new_resume_name
) {
2993 resume_name
= new_resume_name
;
2998 * Fix for NT redirector problem triggered by resume key indexes
2999 * changing between directory scans. We now return a resume key of 0
3000 * and instead look for the filename to continue from (also given
3001 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3002 * findfirst/findnext (as is usual) then the directory pointer
3003 * should already be at the correct place.
3006 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3007 } /* end if resume_name && !continue_bit */
3009 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3010 bool got_exact_match
= False
;
3012 /* this is a heuristic to avoid seeking the dirptr except when
3013 absolutely necessary. It allows for a filename of about 40 chars */
3014 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3015 out_of_space
= True
;
3018 finished
= !get_lanman2_dir_entry(ctx
,
3022 mask
,dirtype
,info_level
,
3023 requires_resume_key
,dont_descend
,
3026 space_remaining
, &out_of_space
,
3028 &last_entry_off
, ea_list
);
3031 if (finished
&& out_of_space
)
3034 if (!finished
&& !out_of_space
)
3038 * As an optimisation if we know we aren't looking
3039 * for a wildcard name (ie. the name matches the wildcard exactly)
3040 * then we can finish on any (first) match.
3041 * This speeds up large directory searches. JRA.
3047 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3050 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3051 smb_fn_name(req
->cmd
),
3052 mask
, directory
, dirtype
, numentries
) );
3054 /* Check if we can close the dirptr */
3055 if(close_after_request
|| (finished
&& close_if_end
)) {
3056 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3057 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3064 /* Set up the return parameter block */
3065 SSVAL(params
,0,numentries
);
3066 SSVAL(params
,2,finished
);
3067 SSVAL(params
,4,0); /* Never an EA error */
3068 SSVAL(params
,6,last_entry_off
);
3070 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3076 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3078 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3082 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3084 SMB_ASSERT(extended_info
!= NULL
);
3086 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3087 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3088 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3089 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3090 #ifdef SAMBA_VERSION_REVISION
3091 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3093 extended_info
->samba_subversion
= 0;
3094 #ifdef SAMBA_VERSION_RC_RELEASE
3095 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3097 #ifdef SAMBA_VERSION_PRE_RELEASE
3098 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3101 #ifdef SAMBA_VERSION_VENDOR_PATCH
3102 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3104 extended_info
->samba_gitcommitdate
= 0;
3105 #ifdef SAMBA_VERSION_COMMIT_TIME
3106 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3109 memset(extended_info
->samba_version_string
, 0,
3110 sizeof(extended_info
->samba_version_string
));
3112 snprintf (extended_info
->samba_version_string
,
3113 sizeof(extended_info
->samba_version_string
),
3114 "%s", samba_version_string());
3117 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3118 TALLOC_CTX
*mem_ctx
,
3119 uint16_t info_level
,
3121 unsigned int max_data_bytes
,
3122 struct smb_filename
*fname
,
3126 char *pdata
, *end_data
;
3127 int data_len
= 0, len
;
3128 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3129 int snum
= SNUM(conn
);
3130 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3131 char *filename
= NULL
;
3132 uint32 additional_flags
= 0;
3133 struct smb_filename smb_fname
;
3135 NTSTATUS status
= NT_STATUS_OK
;
3137 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3140 filename
= fname
->base_name
;
3144 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3145 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3146 "info level (0x%x) on IPC$.\n",
3147 (unsigned int)info_level
));
3148 return NT_STATUS_ACCESS_DENIED
;
3152 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3154 ZERO_STRUCT(smb_fname
);
3155 smb_fname
.base_name
= discard_const_p(char, filename
);
3157 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3158 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3159 return map_nt_error_from_unix(errno
);
3164 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3165 return NT_STATUS_INVALID_PARAMETER
;
3168 *ppdata
= (char *)SMB_REALLOC(
3169 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3170 if (*ppdata
== NULL
) {
3171 return NT_STATUS_NO_MEMORY
;
3175 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3176 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3178 switch (info_level
) {
3179 case SMB_INFO_ALLOCATION
:
3181 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3183 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3184 return map_nt_error_from_unix(errno
);
3187 block_size
= lp_block_size(snum
);
3188 if (bsize
< block_size
) {
3189 uint64_t factor
= block_size
/bsize
;
3194 if (bsize
> block_size
) {
3195 uint64_t factor
= bsize
/block_size
;
3200 bytes_per_sector
= 512;
3201 sectors_per_unit
= bsize
/bytes_per_sector
;
3203 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3204 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3205 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3207 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3208 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3209 SIVAL(pdata
,l1_cUnit
,dsize
);
3210 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3211 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3215 case SMB_INFO_VOLUME
:
3216 /* Return volume name */
3218 * Add volume serial number - hash of a combination of
3219 * the called hostname and the service name.
3221 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3223 * Win2k3 and previous mess this up by sending a name length
3224 * one byte short. I believe only older clients (OS/2 Win9x) use
3225 * this call so try fixing this by adding a terminating null to
3226 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3230 pdata
+l2_vol_szVolLabel
, vname
,
3231 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3232 STR_NOALIGN
|STR_TERMINATE
);
3233 SCVAL(pdata
,l2_vol_cch
,len
);
3234 data_len
= l2_vol_szVolLabel
+ len
;
3235 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3236 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3240 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3241 case SMB_FS_ATTRIBUTE_INFORMATION
:
3243 additional_flags
= 0;
3244 #if defined(HAVE_SYS_QUOTAS)
3245 additional_flags
|= FILE_VOLUME_QUOTAS
;
3248 if(lp_nt_acl_support(SNUM(conn
))) {
3249 additional_flags
|= FILE_PERSISTENT_ACLS
;
3252 /* Capabilities are filled in at connection time through STATVFS call */
3253 additional_flags
|= conn
->fs_capabilities
;
3254 additional_flags
|= lp_parm_int(conn
->params
->service
,
3255 "share", "fake_fscaps",
3258 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3259 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3260 additional_flags
); /* FS ATTRIBUTES */
3262 SIVAL(pdata
,4,255); /* Max filename component length */
3263 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3264 and will think we can't do long filenames */
3265 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3266 PTR_DIFF(end_data
, pdata
+12),
3269 data_len
= 12 + len
;
3270 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3271 /* the client only requested a portion of the
3273 data_len
= max_data_bytes
;
3274 status
= STATUS_BUFFER_OVERFLOW
;
3278 case SMB_QUERY_FS_LABEL_INFO
:
3279 case SMB_FS_LABEL_INFORMATION
:
3280 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3281 PTR_DIFF(end_data
, pdata
+4), 0);
3286 case SMB_QUERY_FS_VOLUME_INFO
:
3287 case SMB_FS_VOLUME_INFORMATION
:
3290 * Add volume serial number - hash of a combination of
3291 * the called hostname and the service name.
3293 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3294 (str_checksum(get_local_machine_name())<<16));
3296 /* Max label len is 32 characters. */
3297 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3298 PTR_DIFF(end_data
, pdata
+18),
3300 SIVAL(pdata
,12,len
);
3303 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3304 (int)strlen(vname
),vname
,
3305 lp_servicename(talloc_tos(), snum
)));
3306 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3307 /* the client only requested a portion of the
3309 data_len
= max_data_bytes
;
3310 status
= STATUS_BUFFER_OVERFLOW
;
3314 case SMB_QUERY_FS_SIZE_INFO
:
3315 case SMB_FS_SIZE_INFORMATION
:
3317 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3319 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3320 return map_nt_error_from_unix(errno
);
3322 block_size
= lp_block_size(snum
);
3323 if (bsize
< block_size
) {
3324 uint64_t factor
= block_size
/bsize
;
3329 if (bsize
> block_size
) {
3330 uint64_t factor
= bsize
/block_size
;
3335 bytes_per_sector
= 512;
3336 sectors_per_unit
= bsize
/bytes_per_sector
;
3337 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3338 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3339 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3340 SBIG_UINT(pdata
,0,dsize
);
3341 SBIG_UINT(pdata
,8,dfree
);
3342 SIVAL(pdata
,16,sectors_per_unit
);
3343 SIVAL(pdata
,20,bytes_per_sector
);
3347 case SMB_FS_FULL_SIZE_INFORMATION
:
3349 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3351 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3352 return map_nt_error_from_unix(errno
);
3354 block_size
= lp_block_size(snum
);
3355 if (bsize
< block_size
) {
3356 uint64_t factor
= block_size
/bsize
;
3361 if (bsize
> block_size
) {
3362 uint64_t factor
= bsize
/block_size
;
3367 bytes_per_sector
= 512;
3368 sectors_per_unit
= bsize
/bytes_per_sector
;
3369 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3370 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3371 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3372 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3373 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3374 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3375 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3376 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3380 case SMB_QUERY_FS_DEVICE_INFO
:
3381 case SMB_FS_DEVICE_INFORMATION
:
3383 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3385 if (!CAN_WRITE(conn
)) {
3386 characteristics
|= FILE_READ_ONLY_DEVICE
;
3389 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3390 SIVAL(pdata
,4,characteristics
);
3394 #ifdef HAVE_SYS_QUOTAS
3395 case SMB_FS_QUOTA_INFORMATION
:
3397 * what we have to send --metze:
3399 * Unknown1: 24 NULL bytes
3400 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3401 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3402 * Quota Flags: 2 byte :
3403 * Unknown3: 6 NULL bytes
3407 * details for Quota Flags:
3409 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3410 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3411 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3412 * 0x0001 Enable Quotas: enable quota for this fs
3416 /* we need to fake up a fsp here,
3417 * because its not send in this call
3420 SMB_NTQUOTA_STRUCT quotas
;
3423 ZERO_STRUCT(quotas
);
3426 fsp
.fnum
= FNUM_FIELD_INVALID
;
3429 if (get_current_uid(conn
) != 0) {
3430 DEBUG(0,("set_user_quota: access_denied "
3431 "service [%s] user [%s]\n",
3432 lp_servicename(talloc_tos(), SNUM(conn
)),
3433 conn
->session_info
->unix_info
->unix_name
));
3434 return NT_STATUS_ACCESS_DENIED
;
3437 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3438 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3439 return map_nt_error_from_unix(errno
);
3444 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3445 lp_servicename(talloc_tos(), SNUM(conn
))));
3447 /* Unknown1 24 NULL bytes*/
3448 SBIG_UINT(pdata
,0,(uint64_t)0);
3449 SBIG_UINT(pdata
,8,(uint64_t)0);
3450 SBIG_UINT(pdata
,16,(uint64_t)0);
3452 /* Default Soft Quota 8 bytes */
3453 SBIG_UINT(pdata
,24,quotas
.softlim
);
3455 /* Default Hard Quota 8 bytes */
3456 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3458 /* Quota flag 2 bytes */
3459 SSVAL(pdata
,40,quotas
.qflags
);
3461 /* Unknown3 6 NULL bytes */
3467 #endif /* HAVE_SYS_QUOTAS */
3468 case SMB_FS_OBJECTID_INFORMATION
:
3470 unsigned char objid
[16];
3471 struct smb_extended_info extended_info
;
3472 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3473 samba_extended_info_version (&extended_info
);
3474 SIVAL(pdata
,16,extended_info
.samba_magic
);
3475 SIVAL(pdata
,20,extended_info
.samba_version
);
3476 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3477 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3478 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3484 * Query the version and capabilities of the CIFS UNIX extensions
3488 case SMB_QUERY_CIFS_UNIX_INFO
:
3490 bool large_write
= lp_min_receive_file_size() &&
3491 !srv_is_signing_active(conn
->sconn
);
3492 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3493 int encrypt_caps
= 0;
3495 if (!lp_unix_extensions()) {
3496 return NT_STATUS_INVALID_LEVEL
;
3499 switch (conn
->encrypt_level
) {
3500 case SMB_SIGNING_OFF
:
3503 case SMB_SIGNING_IF_REQUIRED
:
3504 case SMB_SIGNING_DEFAULT
:
3505 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3507 case SMB_SIGNING_REQUIRED
:
3508 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3509 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3510 large_write
= false;
3516 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3517 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3519 /* We have POSIX ACLs, pathname, encryption,
3520 * large read/write, and locking capability. */
3522 SBIG_UINT(pdata
,4,((uint64_t)(
3523 CIFS_UNIX_POSIX_ACLS_CAP
|
3524 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3525 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3526 CIFS_UNIX_EXTATTR_CAP
|
3527 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3529 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3531 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3535 case SMB_QUERY_POSIX_FS_INFO
:
3538 vfs_statvfs_struct svfs
;
3540 if (!lp_unix_extensions()) {
3541 return NT_STATUS_INVALID_LEVEL
;
3544 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3548 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3549 SIVAL(pdata
,4,svfs
.BlockSize
);
3550 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3551 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3552 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3553 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3554 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3555 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3556 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3558 } else if (rc
== EOPNOTSUPP
) {
3559 return NT_STATUS_INVALID_LEVEL
;
3560 #endif /* EOPNOTSUPP */
3562 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3563 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3568 case SMB_QUERY_POSIX_WHOAMI
:
3574 if (!lp_unix_extensions()) {
3575 return NT_STATUS_INVALID_LEVEL
;
3578 if (max_data_bytes
< 40) {
3579 return NT_STATUS_BUFFER_TOO_SMALL
;
3582 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3583 flags
|= SMB_WHOAMI_GUEST
;
3586 /* NOTE: 8 bytes for UID/GID, irrespective of native
3587 * platform size. This matches
3588 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3590 data_len
= 4 /* flags */
3597 + 4 /* pad/reserved */
3598 + (conn
->session_info
->unix_token
->ngroups
* 8)
3600 + (conn
->session_info
->security_token
->num_sids
*
3604 SIVAL(pdata
, 0, flags
);
3605 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3607 (uint64_t)conn
->session_info
->unix_token
->uid
);
3608 SBIG_UINT(pdata
, 16,
3609 (uint64_t)conn
->session_info
->unix_token
->gid
);
3612 if (data_len
>= max_data_bytes
) {
3613 /* Potential overflow, skip the GIDs and SIDs. */
3615 SIVAL(pdata
, 24, 0); /* num_groups */
3616 SIVAL(pdata
, 28, 0); /* num_sids */
3617 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3618 SIVAL(pdata
, 36, 0); /* reserved */
3624 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3625 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3627 /* We walk the SID list twice, but this call is fairly
3628 * infrequent, and I don't expect that it's performance
3629 * sensitive -- jpeach
3631 for (i
= 0, sid_bytes
= 0;
3632 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3633 sid_bytes
+= ndr_size_dom_sid(
3634 &conn
->session_info
->security_token
->sids
[i
],
3638 /* SID list byte count */
3639 SIVAL(pdata
, 32, sid_bytes
);
3641 /* 4 bytes pad/reserved - must be zero */
3642 SIVAL(pdata
, 36, 0);
3646 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3647 SBIG_UINT(pdata
, data_len
,
3648 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3654 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3655 int sid_len
= ndr_size_dom_sid(
3656 &conn
->session_info
->security_token
->sids
[i
],
3659 sid_linearize(pdata
+ data_len
, sid_len
,
3660 &conn
->session_info
->security_token
->sids
[i
]);
3661 data_len
+= sid_len
;
3667 case SMB_MAC_QUERY_FS_INFO
:
3669 * Thursby MAC extension... ONLY on NTFS filesystems
3670 * once we do streams then we don't need this
3672 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3674 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3679 return NT_STATUS_INVALID_LEVEL
;
3682 *ret_data_len
= data_len
;
3686 /****************************************************************************
3687 Reply to a TRANS2_QFSINFO (query filesystem info).
3688 ****************************************************************************/
3690 static void call_trans2qfsinfo(connection_struct
*conn
,
3691 struct smb_request
*req
,
3692 char **pparams
, int total_params
,
3693 char **ppdata
, int total_data
,
3694 unsigned int max_data_bytes
)
3696 char *params
= *pparams
;
3697 uint16_t info_level
;
3701 if (total_params
< 2) {
3702 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3706 info_level
= SVAL(params
,0);
3708 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3709 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3710 DEBUG(0,("call_trans2qfsinfo: encryption required "
3711 "and info level 0x%x sent.\n",
3712 (unsigned int)info_level
));
3713 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3718 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3720 status
= smbd_do_qfsinfo(conn
, req
,
3726 if (!NT_STATUS_IS_OK(status
)) {
3727 reply_nterror(req
, status
);
3731 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3734 DEBUG( 4, ( "%s info_level = %d\n",
3735 smb_fn_name(req
->cmd
), info_level
) );
3740 /****************************************************************************
3741 Reply to a TRANS2_SETFSINFO (set filesystem info).
3742 ****************************************************************************/
3744 static void call_trans2setfsinfo(connection_struct
*conn
,
3745 struct smb_request
*req
,
3746 char **pparams
, int total_params
,
3747 char **ppdata
, int total_data
,
3748 unsigned int max_data_bytes
)
3750 struct smbd_server_connection
*sconn
= req
->sconn
;
3751 char *pdata
= *ppdata
;
3752 char *params
= *pparams
;
3755 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3756 lp_servicename(talloc_tos(), SNUM(conn
))));
3759 if (total_params
< 4) {
3760 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3766 info_level
= SVAL(params
,2);
3769 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3770 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3771 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3772 "info level (0x%x) on IPC$.\n",
3773 (unsigned int)info_level
));
3774 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3779 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3780 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3781 DEBUG(0,("call_trans2setfsinfo: encryption required "
3782 "and info level 0x%x sent.\n",
3783 (unsigned int)info_level
));
3784 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3789 switch(info_level
) {
3790 case SMB_SET_CIFS_UNIX_INFO
:
3791 if (!lp_unix_extensions()) {
3792 DEBUG(2,("call_trans2setfsinfo: "
3793 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3794 "unix extensions off\n"));
3796 NT_STATUS_INVALID_LEVEL
);
3800 /* There should be 12 bytes of capabilities set. */
3801 if (total_data
< 12) {
3804 NT_STATUS_INVALID_PARAMETER
);
3807 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3808 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3809 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3810 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3811 /* Just print these values for now. */
3812 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3813 "major = %u, minor = %u cap_low = 0x%x, "
3815 (unsigned int)sconn
->
3816 smb1
.unix_info
.client_major
,
3817 (unsigned int)sconn
->
3818 smb1
.unix_info
.client_minor
,
3819 (unsigned int)sconn
->
3820 smb1
.unix_info
.client_cap_low
,
3821 (unsigned int)sconn
->
3822 smb1
.unix_info
.client_cap_high
));
3824 /* Here is where we must switch to posix pathname processing... */
3825 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3826 lp_set_posix_pathnames();
3827 mangle_change_to_posix();
3830 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3831 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3832 /* Client that knows how to do posix locks,
3833 * but not posix open/mkdir operations. Set a
3834 * default type for read/write checks. */
3836 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3841 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3844 size_t param_len
= 0;
3845 size_t data_len
= total_data
;
3847 if (!lp_unix_extensions()) {
3850 NT_STATUS_INVALID_LEVEL
);
3854 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3857 NT_STATUS_NOT_SUPPORTED
);
3861 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3862 DEBUG( 2,("call_trans2setfsinfo: "
3863 "request transport encryption disabled"
3864 "with 'fork echo handler = yes'\n"));
3867 NT_STATUS_NOT_SUPPORTED
);
3871 DEBUG( 4,("call_trans2setfsinfo: "
3872 "request transport encryption.\n"));
3874 status
= srv_request_encryption_setup(conn
,
3875 (unsigned char **)ppdata
,
3877 (unsigned char **)pparams
,
3880 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3881 !NT_STATUS_IS_OK(status
)) {
3882 reply_nterror(req
, status
);
3886 send_trans2_replies(conn
, req
,
3894 if (NT_STATUS_IS_OK(status
)) {
3895 /* Server-side transport
3896 * encryption is now *on*. */
3897 status
= srv_encryption_start(conn
);
3898 if (!NT_STATUS_IS_OK(status
)) {
3899 char *reason
= talloc_asprintf(talloc_tos(),
3900 "Failure in setting "
3901 "up encrypted transport: %s",
3903 exit_server_cleanly(reason
);
3909 case SMB_FS_QUOTA_INFORMATION
:
3911 files_struct
*fsp
= NULL
;
3912 SMB_NTQUOTA_STRUCT quotas
;
3914 ZERO_STRUCT(quotas
);
3917 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3918 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3919 lp_servicename(talloc_tos(), SNUM(conn
)),
3920 conn
->session_info
->unix_info
->unix_name
));
3921 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3925 /* note: normaly there're 48 bytes,
3926 * but we didn't use the last 6 bytes for now
3929 fsp
= file_fsp(req
, SVAL(params
,0));
3931 if (!check_fsp_ntquota_handle(conn
, req
,
3933 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3935 req
, NT_STATUS_INVALID_HANDLE
);
3939 if (total_data
< 42) {
3940 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3944 NT_STATUS_INVALID_PARAMETER
);
3948 /* unknown_1 24 NULL bytes in pdata*/
3950 /* the soft quotas 8 bytes (uint64_t)*/
3951 quotas
.softlim
= BVAL(pdata
,24);
3953 /* the hard quotas 8 bytes (uint64_t)*/
3954 quotas
.hardlim
= BVAL(pdata
,32);
3956 /* quota_flags 2 bytes **/
3957 quotas
.qflags
= SVAL(pdata
,40);
3959 /* unknown_2 6 NULL bytes follow*/
3961 /* now set the quotas */
3962 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3963 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3964 reply_nterror(req
, map_nt_error_from_unix(errno
));
3971 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3973 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3979 * sending this reply works fine,
3980 * but I'm not sure it's the same
3981 * like windows do...
3984 reply_outbuf(req
, 10, 0);
3987 #if defined(HAVE_POSIX_ACLS)
3988 /****************************************************************************
3989 Utility function to count the number of entries in a POSIX acl.
3990 ****************************************************************************/
3992 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3994 unsigned int ace_count
= 0;
3995 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3996 SMB_ACL_ENTRY_T entry
;
3998 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4000 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4001 entry_id
= SMB_ACL_NEXT_ENTRY
;
4008 /****************************************************************************
4009 Utility function to marshall a POSIX acl into wire format.
4010 ****************************************************************************/
4012 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4014 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4015 SMB_ACL_ENTRY_T entry
;
4017 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4018 SMB_ACL_TAG_T tagtype
;
4019 SMB_ACL_PERMSET_T permset
;
4020 unsigned char perms
= 0;
4021 unsigned int own_grp
;
4024 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4025 entry_id
= SMB_ACL_NEXT_ENTRY
;
4028 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4029 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4033 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4034 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4038 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4039 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4040 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4042 SCVAL(pdata
,1,perms
);
4045 case SMB_ACL_USER_OBJ
:
4046 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4047 own_grp
= (unsigned int)pst
->st_ex_uid
;
4048 SIVAL(pdata
,2,own_grp
);
4053 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4055 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4058 own_grp
= (unsigned int)*puid
;
4059 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4060 SIVAL(pdata
,2,own_grp
);
4064 case SMB_ACL_GROUP_OBJ
:
4065 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4066 own_grp
= (unsigned int)pst
->st_ex_gid
;
4067 SIVAL(pdata
,2,own_grp
);
4072 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4074 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4077 own_grp
= (unsigned int)*pgid
;
4078 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4079 SIVAL(pdata
,2,own_grp
);
4084 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4085 SIVAL(pdata
,2,0xFFFFFFFF);
4086 SIVAL(pdata
,6,0xFFFFFFFF);
4089 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4090 SIVAL(pdata
,2,0xFFFFFFFF);
4091 SIVAL(pdata
,6,0xFFFFFFFF);
4094 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4097 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4104 /****************************************************************************
4105 Store the FILE_UNIX_BASIC info.
4106 ****************************************************************************/
4108 static char *store_file_unix_basic(connection_struct
*conn
,
4111 const SMB_STRUCT_STAT
*psbuf
)
4113 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4116 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4117 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4119 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4122 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4125 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4126 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4127 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4130 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4134 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4138 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4141 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4142 devno
= psbuf
->st_ex_rdev
;
4144 devno
= psbuf
->st_ex_dev
;
4147 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4151 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4155 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4158 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4162 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4169 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4170 * the chflags(2) (or equivalent) flags.
4172 * XXX: this really should be behind the VFS interface. To do this, we would
4173 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4174 * Each VFS module could then implement its own mapping as appropriate for the
4175 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4177 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4181 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4185 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4189 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4193 { UF_HIDDEN
, EXT_HIDDEN
},
4196 /* Do not remove. We need to guarantee that this array has at least one
4197 * entry to build on HP-UX.
4203 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4204 uint32
*smb_fflags
, uint32
*smb_fmask
)
4208 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4209 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4210 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4211 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4216 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4217 const uint32 smb_fflags
,
4218 const uint32 smb_fmask
,
4221 uint32 max_fmask
= 0;
4224 *stat_fflags
= psbuf
->st_ex_flags
;
4226 /* For each flags requested in smb_fmask, check the state of the
4227 * corresponding flag in smb_fflags and set or clear the matching
4231 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4232 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4233 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4234 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4235 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4237 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4242 /* If smb_fmask is asking to set any bits that are not supported by
4243 * our flag mappings, we should fail.
4245 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4253 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4254 * of file flags and birth (create) time.
4256 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4259 const SMB_STRUCT_STAT
*psbuf
)
4261 uint32 file_flags
= 0;
4262 uint32 flags_mask
= 0;
4264 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4266 /* Create (birth) time 64 bit */
4267 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4270 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4271 SIVAL(pdata
, 0, file_flags
); /* flags */
4272 SIVAL(pdata
, 4, flags_mask
); /* mask */
4278 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4279 const struct stream_struct
*streams
,
4281 unsigned int max_data_bytes
,
4282 unsigned int *data_size
)
4285 unsigned int ofs
= 0;
4287 for (i
= 0; i
< num_streams
; i
++) {
4288 unsigned int next_offset
;
4290 smb_ucs2_t
*namebuf
;
4292 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4293 streams
[i
].name
, &namelen
) ||
4296 return NT_STATUS_INVALID_PARAMETER
;
4300 * name_buf is now null-terminated, we need to marshall as not
4307 * We cannot overflow ...
4309 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4310 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4312 TALLOC_FREE(namebuf
);
4313 return STATUS_BUFFER_OVERFLOW
;
4316 SIVAL(data
, ofs
+4, namelen
);
4317 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4318 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4319 memcpy(data
+ofs
+24, namebuf
, namelen
);
4320 TALLOC_FREE(namebuf
);
4322 next_offset
= ofs
+ 24 + namelen
;
4324 if (i
== num_streams
-1) {
4325 SIVAL(data
, ofs
, 0);
4328 unsigned int align
= ndr_align_size(next_offset
, 8);
4330 if ((next_offset
+ align
) > max_data_bytes
) {
4331 DEBUG(10, ("refusing to overflow align "
4332 "reply at stream %u\n",
4334 TALLOC_FREE(namebuf
);
4335 return STATUS_BUFFER_OVERFLOW
;
4338 memset(data
+next_offset
, 0, align
);
4339 next_offset
+= align
;
4341 SIVAL(data
, ofs
, next_offset
- ofs
);
4348 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4352 return NT_STATUS_OK
;
4355 /****************************************************************************
4356 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4357 ****************************************************************************/
4359 static void call_trans2qpipeinfo(connection_struct
*conn
,
4360 struct smb_request
*req
,
4361 unsigned int tran_call
,
4362 char **pparams
, int total_params
,
4363 char **ppdata
, int total_data
,
4364 unsigned int max_data_bytes
)
4366 char *params
= *pparams
;
4367 char *pdata
= *ppdata
;
4368 unsigned int data_size
= 0;
4369 unsigned int param_size
= 2;
4374 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4378 if (total_params
< 4) {
4379 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4383 fsp
= file_fsp(req
, SVAL(params
,0));
4384 if (!fsp_is_np(fsp
)) {
4385 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4389 info_level
= SVAL(params
,2);
4391 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4392 if (*pparams
== NULL
) {
4393 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4398 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4399 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4402 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4403 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4404 if (*ppdata
== NULL
) {
4405 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4410 switch (info_level
) {
4411 case SMB_FILE_STANDARD_INFORMATION
:
4413 SOFF_T(pdata
,0,4096LL);
4420 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4424 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4430 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4431 TALLOC_CTX
*mem_ctx
,
4432 uint16_t info_level
,
4434 struct smb_filename
*smb_fname
,
4435 bool delete_pending
,
4436 struct timespec write_time_ts
,
4437 struct ea_list
*ea_list
,
4438 int lock_data_count
,
4441 unsigned int max_data_bytes
,
4443 unsigned int *pdata_size
)
4445 char *pdata
= *ppdata
;
4446 char *dstart
, *dend
;
4447 unsigned int data_size
;
4448 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4449 time_t create_time
, mtime
, atime
, c_time
;
4450 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4457 uint64_t file_size
= 0;
4459 uint64_t allocation_size
= 0;
4460 uint64_t file_index
= 0;
4461 uint32_t access_mask
= 0;
4463 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4464 return NT_STATUS_INVALID_LEVEL
;
4467 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4468 smb_fname_str_dbg(smb_fname
),
4470 info_level
, max_data_bytes
));
4472 mode
= dos_mode(conn
, smb_fname
);
4473 nlink
= psbuf
->st_ex_nlink
;
4475 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4479 if ((nlink
> 0) && delete_pending
) {
4483 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4484 return NT_STATUS_INVALID_PARAMETER
;
4487 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4488 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4489 if (*ppdata
== NULL
) {
4490 return NT_STATUS_NO_MEMORY
;
4494 dend
= dstart
+ data_size
- 1;
4496 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4497 update_stat_ex_mtime(psbuf
, write_time_ts
);
4500 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4501 mtime_ts
= psbuf
->st_ex_mtime
;
4502 atime_ts
= psbuf
->st_ex_atime
;
4503 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4505 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4506 dos_filetime_timespec(&create_time_ts
);
4507 dos_filetime_timespec(&mtime_ts
);
4508 dos_filetime_timespec(&atime_ts
);
4509 dos_filetime_timespec(&ctime_ts
);
4512 create_time
= convert_timespec_to_time_t(create_time_ts
);
4513 mtime
= convert_timespec_to_time_t(mtime_ts
);
4514 atime
= convert_timespec_to_time_t(atime_ts
);
4515 c_time
= convert_timespec_to_time_t(ctime_ts
);
4517 p
= strrchr_m(smb_fname
->base_name
,'/');
4519 base_name
= smb_fname
->base_name
;
4523 /* NT expects the name to be in an exact form of the *full*
4524 filename. See the trans2 torture test */
4525 if (ISDOT(base_name
)) {
4526 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4528 return NT_STATUS_NO_MEMORY
;
4531 dos_fname
= talloc_asprintf(mem_ctx
,
4533 smb_fname
->base_name
);
4535 return NT_STATUS_NO_MEMORY
;
4537 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4538 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4539 smb_fname
->stream_name
);
4541 return NT_STATUS_NO_MEMORY
;
4545 string_replace(dos_fname
, '/', '\\');
4548 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4551 /* Do we have this path open ? */
4553 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4554 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4555 if (fsp1
&& fsp1
->initial_allocation_size
) {
4556 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4560 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4561 file_size
= get_file_size_stat(psbuf
);
4565 pos
= fsp
->fh
->position_information
;
4569 access_mask
= fsp
->access_mask
;
4571 /* GENERIC_EXECUTE mapping from Windows */
4572 access_mask
= 0x12019F;
4575 /* This should be an index number - looks like
4578 I think this causes us to fail the IFSKIT
4579 BasicFileInformationTest. -tpot */
4580 file_index
= get_FileIndex(conn
, psbuf
);
4582 switch (info_level
) {
4583 case SMB_INFO_STANDARD
:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4586 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4587 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4588 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4589 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4590 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4591 SSVAL(pdata
,l1_attrFile
,mode
);
4594 case SMB_INFO_QUERY_EA_SIZE
:
4596 unsigned int ea_size
=
4597 estimate_ea_size(conn
, fsp
,
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4601 srv_put_dos_date2(pdata
,0,create_time
);
4602 srv_put_dos_date2(pdata
,4,atime
);
4603 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4604 SIVAL(pdata
,12,(uint32
)file_size
);
4605 SIVAL(pdata
,16,(uint32
)allocation_size
);
4606 SSVAL(pdata
,20,mode
);
4607 SIVAL(pdata
,22,ea_size
);
4611 case SMB_INFO_IS_NAME_VALID
:
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4614 /* os/2 needs this ? really ?*/
4615 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4617 /* This is only reached for qpathinfo */
4621 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4623 size_t total_ea_len
= 0;
4624 struct ea_list
*ea_file_list
= NULL
;
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4628 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4630 &total_ea_len
, &ea_file_list
);
4631 if (!NT_STATUS_IS_OK(status
)) {
4635 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4637 if (!ea_list
|| (total_ea_len
> data_size
)) {
4639 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4643 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4647 case SMB_INFO_QUERY_ALL_EAS
:
4649 /* We have data_size bytes to put EA's into. */
4650 size_t total_ea_len
= 0;
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4653 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4655 &total_ea_len
, &ea_list
);
4656 if (!NT_STATUS_IS_OK(status
)) {
4660 if (!ea_list
|| (total_ea_len
> data_size
)) {
4662 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4666 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4670 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4672 /* This is FileFullEaInformation - 0xF which maps to
4673 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4675 /* We have data_size bytes to put EA's into. */
4676 size_t total_ea_len
= 0;
4677 struct ea_list
*ea_file_list
= NULL
;
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4681 /*TODO: add filtering and index handling */
4684 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4686 &total_ea_len
, &ea_file_list
);
4687 if (!NT_STATUS_IS_OK(status
)) {
4690 if (!ea_file_list
) {
4691 return NT_STATUS_NO_EAS_ON_FILE
;
4694 status
= fill_ea_chained_buffer(mem_ctx
,
4698 conn
, ea_file_list
);
4699 if (!NT_STATUS_IS_OK(status
)) {
4705 case SMB_FILE_BASIC_INFORMATION
:
4706 case SMB_QUERY_FILE_BASIC_INFO
:
4708 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4710 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4716 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4717 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4718 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4719 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4720 SIVAL(pdata
,32,mode
);
4722 DEBUG(5,("SMB_QFBI - "));
4723 DEBUG(5,("create: %s ", ctime(&create_time
)));
4724 DEBUG(5,("access: %s ", ctime(&atime
)));
4725 DEBUG(5,("write: %s ", ctime(&mtime
)));
4726 DEBUG(5,("change: %s ", ctime(&c_time
)));
4727 DEBUG(5,("mode: %x\n", mode
));
4730 case SMB_FILE_STANDARD_INFORMATION
:
4731 case SMB_QUERY_FILE_STANDARD_INFO
:
4733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4735 SOFF_T(pdata
,0,allocation_size
);
4736 SOFF_T(pdata
,8,file_size
);
4737 SIVAL(pdata
,16,nlink
);
4738 SCVAL(pdata
,20,delete_pending
?1:0);
4739 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4740 SSVAL(pdata
,22,0); /* Padding. */
4743 case SMB_FILE_EA_INFORMATION
:
4744 case SMB_QUERY_FILE_EA_INFO
:
4746 unsigned int ea_size
=
4747 estimate_ea_size(conn
, fsp
, smb_fname
);
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4750 SIVAL(pdata
,0,ea_size
);
4754 /* Get the 8.3 name - used if NT SMB was negotiated. */
4755 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4756 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4759 char mangled_name
[13];
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4761 if (!name_to_8_3(base_name
,mangled_name
,
4762 True
,conn
->params
)) {
4763 return NT_STATUS_NO_MEMORY
;
4765 len
= srvstr_push(dstart
, flags2
,
4766 pdata
+4, mangled_name
,
4767 PTR_DIFF(dend
, pdata
+4),
4769 data_size
= 4 + len
;
4774 case SMB_QUERY_FILE_NAME_INFO
:
4778 this must be *exactly* right for ACLs on mapped drives to work
4780 len
= srvstr_push(dstart
, flags2
,
4782 PTR_DIFF(dend
, pdata
+4),
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4785 data_size
= 4 + len
;
4790 case SMB_FILE_ALLOCATION_INFORMATION
:
4791 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4794 SOFF_T(pdata
,0,allocation_size
);
4797 case SMB_FILE_END_OF_FILE_INFORMATION
:
4798 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4801 SOFF_T(pdata
,0,file_size
);
4804 case SMB_QUERY_FILE_ALL_INFO
:
4805 case SMB_FILE_ALL_INFORMATION
:
4808 unsigned int ea_size
=
4809 estimate_ea_size(conn
, fsp
, smb_fname
);
4810 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4811 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4812 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4813 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4814 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4815 SIVAL(pdata
,32,mode
);
4816 SIVAL(pdata
,36,0); /* padding. */
4818 SOFF_T(pdata
,0,allocation_size
);
4819 SOFF_T(pdata
,8,file_size
);
4820 SIVAL(pdata
,16,nlink
);
4821 SCVAL(pdata
,20,delete_pending
);
4822 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4825 SIVAL(pdata
,0,ea_size
);
4826 pdata
+= 4; /* EA info */
4827 len
= srvstr_push(dstart
, flags2
,
4829 PTR_DIFF(dend
, pdata
+4),
4833 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4837 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4840 unsigned int ea_size
=
4841 estimate_ea_size(conn
, fsp
, smb_fname
);
4842 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4843 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4844 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4845 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4846 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4847 SIVAL(pdata
, 0x20, mode
);
4848 SIVAL(pdata
, 0x24, 0); /* padding. */
4849 SBVAL(pdata
, 0x28, allocation_size
);
4850 SBVAL(pdata
, 0x30, file_size
);
4851 SIVAL(pdata
, 0x38, nlink
);
4852 SCVAL(pdata
, 0x3C, delete_pending
);
4853 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4854 SSVAL(pdata
, 0x3E, 0); /* padding */
4855 SBVAL(pdata
, 0x40, file_index
);
4856 SIVAL(pdata
, 0x48, ea_size
);
4857 SIVAL(pdata
, 0x4C, access_mask
);
4858 SBVAL(pdata
, 0x50, pos
);
4859 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4860 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4864 len
= srvstr_push(dstart
, flags2
,
4866 PTR_DIFF(dend
, pdata
+4),
4870 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4873 case SMB_FILE_INTERNAL_INFORMATION
:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4876 SBVAL(pdata
, 0, file_index
);
4880 case SMB_FILE_ACCESS_INFORMATION
:
4881 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4882 SIVAL(pdata
, 0, access_mask
);
4886 case SMB_FILE_NAME_INFORMATION
:
4887 /* Pathname with leading '\'. */
4890 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4892 SIVAL(pdata
,0,byte_len
);
4893 data_size
= 4 + byte_len
;
4897 case SMB_FILE_DISPOSITION_INFORMATION
:
4898 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4900 SCVAL(pdata
,0,delete_pending
);
4903 case SMB_FILE_POSITION_INFORMATION
:
4904 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4906 SOFF_T(pdata
,0,pos
);
4909 case SMB_FILE_MODE_INFORMATION
:
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4911 SIVAL(pdata
,0,mode
);
4915 case SMB_FILE_ALIGNMENT_INFORMATION
:
4916 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4917 SIVAL(pdata
,0,0); /* No alignment needed. */
4922 * NT4 server just returns "invalid query" to this - if we try
4923 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4926 /* The first statement above is false - verified using Thursby
4927 * client against NT4 -- gcolley.
4929 case SMB_QUERY_FILE_STREAM_INFO
:
4930 case SMB_FILE_STREAM_INFORMATION
: {
4931 unsigned int num_streams
= 0;
4932 struct stream_struct
*streams
= NULL
;
4934 DEBUG(10,("smbd_do_qfilepathinfo: "
4935 "SMB_FILE_STREAM_INFORMATION\n"));
4937 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4938 return NT_STATUS_INVALID_PARAMETER
;
4941 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4942 talloc_tos(), &num_streams
, &streams
);
4944 if (!NT_STATUS_IS_OK(status
)) {
4945 DEBUG(10, ("could not get stream info: %s\n",
4946 nt_errstr(status
)));
4950 status
= marshall_stream_info(num_streams
, streams
,
4951 pdata
, max_data_bytes
,
4954 if (!NT_STATUS_IS_OK(status
)) {
4955 DEBUG(10, ("marshall_stream_info failed: %s\n",
4956 nt_errstr(status
)));
4957 TALLOC_FREE(streams
);
4961 TALLOC_FREE(streams
);
4965 case SMB_QUERY_COMPRESSION_INFO
:
4966 case SMB_FILE_COMPRESSION_INFORMATION
:
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4968 SOFF_T(pdata
,0,file_size
);
4969 SIVAL(pdata
,8,0); /* ??? */
4970 SIVAL(pdata
,12,0); /* ??? */
4974 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4975 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4976 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4977 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4978 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4979 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4980 SOFF_T(pdata
,32,allocation_size
);
4981 SOFF_T(pdata
,40,file_size
);
4982 SIVAL(pdata
,48,mode
);
4983 SIVAL(pdata
,52,0); /* ??? */
4987 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4988 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4989 SIVAL(pdata
,0,mode
);
4995 * CIFS UNIX Extensions.
4998 case SMB_QUERY_FILE_UNIX_BASIC
:
5000 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5001 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5003 DEBUG(4,("smbd_do_qfilepathinfo: "
5004 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5005 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5009 case SMB_QUERY_FILE_UNIX_INFO2
:
5011 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5012 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5016 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5018 for (i
=0; i
<100; i
++)
5019 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5025 case SMB_QUERY_FILE_UNIX_LINK
:
5028 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5031 return NT_STATUS_NO_MEMORY
;
5034 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5036 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5037 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5040 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5042 len
= SMB_VFS_READLINK(conn
,
5043 smb_fname
->base_name
,
5046 return map_nt_error_from_unix(errno
);
5049 len
= srvstr_push(dstart
, flags2
,
5051 PTR_DIFF(dend
, pdata
),
5054 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5059 #if defined(HAVE_POSIX_ACLS)
5060 case SMB_QUERY_POSIX_ACL
:
5062 SMB_ACL_T file_acl
= NULL
;
5063 SMB_ACL_T def_acl
= NULL
;
5064 uint16 num_file_acls
= 0;
5065 uint16 num_def_acls
= 0;
5067 if (fsp
&& fsp
->fh
->fd
!= -1) {
5068 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5072 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5073 smb_fname
->base_name
,
5074 SMB_ACL_TYPE_ACCESS
,
5078 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5079 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5080 "not implemented on "
5081 "filesystem containing %s\n",
5082 smb_fname
->base_name
));
5083 return NT_STATUS_NOT_IMPLEMENTED
;
5086 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5087 if (fsp
&& fsp
->is_directory
) {
5089 SMB_VFS_SYS_ACL_GET_FILE(
5091 fsp
->fsp_name
->base_name
,
5092 SMB_ACL_TYPE_DEFAULT
,
5096 SMB_VFS_SYS_ACL_GET_FILE(
5098 smb_fname
->base_name
,
5099 SMB_ACL_TYPE_DEFAULT
,
5102 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5105 num_file_acls
= count_acl_entries(conn
, file_acl
);
5106 num_def_acls
= count_acl_entries(conn
, def_acl
);
5108 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5109 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5111 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5112 SMB_POSIX_ACL_HEADER_SIZE
) ));
5114 TALLOC_FREE(file_acl
);
5117 TALLOC_FREE(def_acl
);
5119 return NT_STATUS_BUFFER_TOO_SMALL
;
5122 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5123 SSVAL(pdata
,2,num_file_acls
);
5124 SSVAL(pdata
,4,num_def_acls
);
5125 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5127 TALLOC_FREE(file_acl
);
5130 TALLOC_FREE(def_acl
);
5132 return NT_STATUS_INTERNAL_ERROR
;
5134 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5136 TALLOC_FREE(file_acl
);
5139 TALLOC_FREE(def_acl
);
5141 return NT_STATUS_INTERNAL_ERROR
;
5145 TALLOC_FREE(file_acl
);
5148 TALLOC_FREE(def_acl
);
5150 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5156 case SMB_QUERY_POSIX_LOCK
:
5161 enum brl_type lock_type
;
5163 /* We need an open file with a real fd for this. */
5164 if (!fsp
|| fsp
->fh
->fd
== -1) {
5165 return NT_STATUS_INVALID_LEVEL
;
5168 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5169 return NT_STATUS_INVALID_PARAMETER
;
5172 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5173 case POSIX_LOCK_TYPE_READ
:
5174 lock_type
= READ_LOCK
;
5176 case POSIX_LOCK_TYPE_WRITE
:
5177 lock_type
= WRITE_LOCK
;
5179 case POSIX_LOCK_TYPE_UNLOCK
:
5181 /* There's no point in asking for an unlock... */
5182 return NT_STATUS_INVALID_PARAMETER
;
5185 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5186 #if defined(HAVE_LONGLONG)
5187 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5188 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5189 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5190 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5191 #else /* HAVE_LONGLONG */
5192 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5193 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5194 #endif /* HAVE_LONGLONG */
5196 status
= query_lock(fsp
,
5203 if (ERROR_WAS_LOCK_DENIED(status
)) {
5204 /* Here we need to report who has it locked... */
5205 data_size
= POSIX_LOCK_DATA_SIZE
;
5207 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5208 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5209 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5210 #if defined(HAVE_LONGLONG)
5211 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5212 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5213 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5214 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5215 #else /* HAVE_LONGLONG */
5216 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5217 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5218 #endif /* HAVE_LONGLONG */
5220 } else if (NT_STATUS_IS_OK(status
)) {
5221 /* For success we just return a copy of what we sent
5222 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5223 data_size
= POSIX_LOCK_DATA_SIZE
;
5224 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5225 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5233 return NT_STATUS_INVALID_LEVEL
;
5236 *pdata_size
= data_size
;
5237 return NT_STATUS_OK
;
5240 /****************************************************************************
5241 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5242 file name or file id).
5243 ****************************************************************************/
5245 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5246 struct smb_request
*req
,
5247 unsigned int tran_call
,
5248 char **pparams
, int total_params
,
5249 char **ppdata
, int total_data
,
5250 unsigned int max_data_bytes
)
5252 char *params
= *pparams
;
5253 char *pdata
= *ppdata
;
5255 unsigned int data_size
= 0;
5256 unsigned int param_size
= 2;
5257 struct smb_filename
*smb_fname
= NULL
;
5258 bool delete_pending
= False
;
5259 struct timespec write_time_ts
;
5260 files_struct
*fsp
= NULL
;
5261 struct file_id fileid
;
5262 struct ea_list
*ea_list
= NULL
;
5263 int lock_data_count
= 0;
5264 char *lock_data
= NULL
;
5265 NTSTATUS status
= NT_STATUS_OK
;
5268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5272 ZERO_STRUCT(write_time_ts
);
5274 if (tran_call
== TRANSACT2_QFILEINFO
) {
5275 if (total_params
< 4) {
5276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5281 call_trans2qpipeinfo(conn
, req
, tran_call
,
5282 pparams
, total_params
,
5288 fsp
= file_fsp(req
, SVAL(params
,0));
5289 info_level
= SVAL(params
,2);
5291 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5293 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5294 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5298 /* Initial check for valid fsp ptr. */
5299 if (!check_fsp_open(conn
, req
, fsp
)) {
5303 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5304 if (smb_fname
== NULL
) {
5305 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5309 if(fsp
->fake_file_handle
) {
5311 * This is actually for the QUOTA_FAKE_FILE --metze
5314 /* We know this name is ok, it's already passed the checks. */
5316 } else if(fsp
->fh
->fd
== -1) {
5318 * This is actually a QFILEINFO on a directory
5319 * handle (returned from an NT SMB). NT5.0 seems
5320 * to do this call. JRA.
5323 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5324 /* Always do lstat for UNIX calls. */
5325 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5326 DEBUG(3,("call_trans2qfilepathinfo: "
5327 "SMB_VFS_LSTAT of %s failed "
5329 smb_fname_str_dbg(smb_fname
),
5332 map_nt_error_from_unix(errno
));
5335 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5336 DEBUG(3,("call_trans2qfilepathinfo: "
5337 "SMB_VFS_STAT of %s failed (%s)\n",
5338 smb_fname_str_dbg(smb_fname
),
5341 map_nt_error_from_unix(errno
));
5345 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5346 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5349 * Original code - this is an open file.
5351 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5352 DEBUG(3, ("fstat of %s failed (%s)\n",
5353 fsp_fnum_dbg(fsp
), strerror(errno
)));
5355 map_nt_error_from_unix(errno
));
5358 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5359 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5365 uint32_t ucf_flags
= 0;
5368 if (total_params
< 7) {
5369 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5373 info_level
= SVAL(params
,0);
5375 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5377 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5378 if (!lp_unix_extensions()) {
5379 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5382 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5383 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5384 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5385 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5389 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5391 STR_TERMINATE
, &status
);
5392 if (!NT_STATUS_IS_OK(status
)) {
5393 reply_nterror(req
, status
);
5397 status
= filename_convert(req
,
5399 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5404 if (!NT_STATUS_IS_OK(status
)) {
5405 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5406 reply_botherror(req
,
5407 NT_STATUS_PATH_NOT_COVERED
,
5408 ERRSRV
, ERRbadpath
);
5411 reply_nterror(req
, status
);
5415 /* If this is a stream, check if there is a delete_pending. */
5416 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5417 && is_ntfs_stream_smb_fname(smb_fname
)) {
5418 struct smb_filename
*smb_fname_base
;
5420 /* Create an smb_filename with stream_name == NULL. */
5421 smb_fname_base
= synthetic_smb_fname(
5422 talloc_tos(), smb_fname
->base_name
,
5424 if (smb_fname_base
== NULL
) {
5425 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5429 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5430 /* Always do lstat for UNIX calls. */
5431 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5432 DEBUG(3,("call_trans2qfilepathinfo: "
5433 "SMB_VFS_LSTAT of %s failed "
5435 smb_fname_str_dbg(smb_fname_base
),
5437 TALLOC_FREE(smb_fname_base
);
5439 map_nt_error_from_unix(errno
));
5443 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5444 DEBUG(3,("call_trans2qfilepathinfo: "
5445 "fileinfo of %s failed "
5447 smb_fname_str_dbg(smb_fname_base
),
5449 TALLOC_FREE(smb_fname_base
);
5451 map_nt_error_from_unix(errno
));
5456 status
= file_name_hash(conn
,
5457 smb_fname_str_dbg(smb_fname_base
),
5459 if (!NT_STATUS_IS_OK(status
)) {
5460 TALLOC_FREE(smb_fname_base
);
5461 reply_nterror(req
, status
);
5465 fileid
= vfs_file_id_from_sbuf(conn
,
5466 &smb_fname_base
->st
);
5467 TALLOC_FREE(smb_fname_base
);
5468 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5469 if (delete_pending
) {
5470 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5475 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5476 /* Always do lstat for UNIX calls. */
5477 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5478 DEBUG(3,("call_trans2qfilepathinfo: "
5479 "SMB_VFS_LSTAT of %s failed (%s)\n",
5480 smb_fname_str_dbg(smb_fname
),
5483 map_nt_error_from_unix(errno
));
5488 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5489 DEBUG(3,("call_trans2qfilepathinfo: "
5490 "SMB_VFS_STAT of %s failed (%s)\n",
5491 smb_fname_str_dbg(smb_fname
),
5494 map_nt_error_from_unix(errno
));
5499 status
= file_name_hash(conn
,
5500 smb_fname_str_dbg(smb_fname
),
5502 if (!NT_STATUS_IS_OK(status
)) {
5503 reply_nterror(req
, status
);
5507 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5508 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5509 if (delete_pending
) {
5510 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5515 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5516 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5518 info_level
,tran_call
,total_data
));
5520 /* Pull out any data sent here before we realloc. */
5521 switch (info_level
) {
5522 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5524 /* Pull any EA list from the data portion. */
5527 if (total_data
< 4) {
5529 req
, NT_STATUS_INVALID_PARAMETER
);
5532 ea_size
= IVAL(pdata
,0);
5534 if (total_data
> 0 && ea_size
!= total_data
) {
5535 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5536 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5538 req
, NT_STATUS_INVALID_PARAMETER
);
5542 if (!lp_ea_support(SNUM(conn
))) {
5543 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5547 /* Pull out the list of names. */
5548 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5551 req
, NT_STATUS_INVALID_PARAMETER
);
5557 case SMB_QUERY_POSIX_LOCK
:
5559 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5560 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5564 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5566 req
, NT_STATUS_INVALID_PARAMETER
);
5570 /* Copy the lock range data. */
5571 lock_data
= (char *)talloc_memdup(
5572 req
, pdata
, total_data
);
5574 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5577 lock_data_count
= total_data
;
5583 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5584 if (*pparams
== NULL
) {
5585 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5592 * draft-leach-cifs-v1-spec-02.txt
5593 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5596 * The requested information is placed in the Data portion of the
5597 * transaction response. For the information levels greater than 0x100,
5598 * the transaction response has 1 parameter word which should be
5599 * ignored by the client.
5601 * However Windows only follows this rule for the IS_NAME_VALID call.
5603 switch (info_level
) {
5604 case SMB_INFO_IS_NAME_VALID
:
5609 if ((info_level
& 0xFF00) == 0xFF00) {
5611 * We use levels that start with 0xFF00
5612 * internally to represent SMB2 specific levels
5614 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5618 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5620 delete_pending
, write_time_ts
,
5622 lock_data_count
, lock_data
,
5623 req
->flags2
, max_data_bytes
,
5624 ppdata
, &data_size
);
5625 if (!NT_STATUS_IS_OK(status
)) {
5626 reply_nterror(req
, status
);
5630 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5636 /****************************************************************************
5637 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5639 ****************************************************************************/
5641 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5642 connection_struct
*conn
,
5643 struct smb_request
*req
,
5644 bool overwrite_if_exists
,
5645 const struct smb_filename
*smb_fname_old
,
5646 struct smb_filename
*smb_fname_new
)
5648 NTSTATUS status
= NT_STATUS_OK
;
5650 /* source must already exist. */
5651 if (!VALID_STAT(smb_fname_old
->st
)) {
5652 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5655 if (VALID_STAT(smb_fname_new
->st
)) {
5656 if (overwrite_if_exists
) {
5657 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5658 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5660 status
= unlink_internals(conn
,
5662 FILE_ATTRIBUTE_NORMAL
,
5665 if (!NT_STATUS_IS_OK(status
)) {
5669 /* Disallow if newname already exists. */
5670 return NT_STATUS_OBJECT_NAME_COLLISION
;
5674 /* No links from a directory. */
5675 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5676 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5679 /* Setting a hardlink to/from a stream isn't currently supported. */
5680 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5681 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5682 return NT_STATUS_INVALID_PARAMETER
;
5685 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5686 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5688 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5689 smb_fname_new
->base_name
) != 0) {
5690 status
= map_nt_error_from_unix(errno
);
5691 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5692 nt_errstr(status
), smb_fname_old
->base_name
,
5693 smb_fname_new
->base_name
));
5698 /****************************************************************************
5699 Deal with setting the time from any of the setfilepathinfo functions.
5700 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5701 calling this function.
5702 ****************************************************************************/
5704 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5706 const struct smb_filename
*smb_fname
,
5707 struct smb_file_time
*ft
,
5708 bool setting_write_time
)
5710 struct smb_filename smb_fname_base
;
5712 FILE_NOTIFY_CHANGE_LAST_ACCESS
5713 |FILE_NOTIFY_CHANGE_LAST_WRITE
5714 |FILE_NOTIFY_CHANGE_CREATION
;
5716 if (!VALID_STAT(smb_fname
->st
)) {
5717 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5720 /* get some defaults (no modifications) if any info is zero or -1. */
5721 if (null_timespec(ft
->create_time
)) {
5722 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5725 if (null_timespec(ft
->atime
)) {
5726 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5729 if (null_timespec(ft
->mtime
)) {
5730 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5733 if (!setting_write_time
) {
5734 /* ft->mtime comes from change time, not write time. */
5735 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5738 /* Ensure the resolution is the correct for
5739 * what we can store on this filesystem. */
5741 round_timespec(conn
->ts_res
, &ft
->create_time
);
5742 round_timespec(conn
->ts_res
, &ft
->ctime
);
5743 round_timespec(conn
->ts_res
, &ft
->atime
);
5744 round_timespec(conn
->ts_res
, &ft
->mtime
);
5746 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5747 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5748 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5749 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5750 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5751 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5752 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5753 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5755 if (setting_write_time
) {
5757 * This was a Windows setfileinfo on an open file.
5758 * NT does this a lot. We also need to
5759 * set the time here, as it can be read by
5760 * FindFirst/FindNext and with the patch for bug #2045
5761 * in smbd/fileio.c it ensures that this timestamp is
5762 * kept sticky even after a write. We save the request
5763 * away and will set it on file close and after a write. JRA.
5766 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5767 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5770 if (fsp
->base_fsp
) {
5771 set_sticky_write_time_fsp(fsp
->base_fsp
,
5774 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5777 set_sticky_write_time_path(
5778 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5783 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5785 /* Always call ntimes on the base, even if a stream was passed in. */
5786 smb_fname_base
= *smb_fname
;
5787 smb_fname_base
.stream_name
= NULL
;
5789 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5790 return map_nt_error_from_unix(errno
);
5793 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5794 smb_fname
->base_name
);
5795 return NT_STATUS_OK
;
5798 /****************************************************************************
5799 Deal with setting the dosmode from any of the setfilepathinfo functions.
5800 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5801 done before calling this function.
5802 ****************************************************************************/
5804 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5805 const struct smb_filename
*smb_fname
,
5808 struct smb_filename
*smb_fname_base
;
5811 if (!VALID_STAT(smb_fname
->st
)) {
5812 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5815 /* Always operate on the base_name, even if a stream was passed in. */
5816 smb_fname_base
= synthetic_smb_fname(
5817 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5818 if (smb_fname_base
== NULL
) {
5819 return NT_STATUS_NO_MEMORY
;
5823 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5824 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5826 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5830 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5832 /* check the mode isn't different, before changing it */
5833 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5834 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5835 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5836 (unsigned int)dosmode
));
5838 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5840 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5842 smb_fname_str_dbg(smb_fname_base
),
5844 status
= map_nt_error_from_unix(errno
);
5848 status
= NT_STATUS_OK
;
5850 TALLOC_FREE(smb_fname_base
);
5854 /****************************************************************************
5855 Deal with setting the size from any of the setfilepathinfo functions.
5856 ****************************************************************************/
5858 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5859 struct smb_request
*req
,
5861 const struct smb_filename
*smb_fname
,
5862 const SMB_STRUCT_STAT
*psbuf
,
5864 bool fail_after_createfile
)
5866 NTSTATUS status
= NT_STATUS_OK
;
5867 struct smb_filename
*smb_fname_tmp
= NULL
;
5868 files_struct
*new_fsp
= NULL
;
5870 if (!VALID_STAT(*psbuf
)) {
5871 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5874 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5876 if (size
== get_file_size_stat(psbuf
)) {
5877 return NT_STATUS_OK
;
5880 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5881 smb_fname_str_dbg(smb_fname
), (double)size
));
5883 if (fsp
&& fsp
->fh
->fd
!= -1) {
5884 /* Handle based call. */
5885 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5886 return NT_STATUS_ACCESS_DENIED
;
5889 if (vfs_set_filelen(fsp
, size
) == -1) {
5890 return map_nt_error_from_unix(errno
);
5892 trigger_write_time_update_immediate(fsp
);
5893 return NT_STATUS_OK
;
5896 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
5897 if (smb_fname_tmp
== NULL
) {
5898 return NT_STATUS_NO_MEMORY
;
5901 smb_fname_tmp
->st
= *psbuf
;
5903 status
= SMB_VFS_CREATE_FILE(
5906 0, /* root_dir_fid */
5907 smb_fname_tmp
, /* fname */
5908 FILE_WRITE_DATA
, /* access_mask */
5909 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5911 FILE_OPEN
, /* create_disposition*/
5912 0, /* create_options */
5913 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5914 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5915 0, /* allocation_size */
5916 0, /* private_flags */
5919 &new_fsp
, /* result */
5922 TALLOC_FREE(smb_fname_tmp
);
5924 if (!NT_STATUS_IS_OK(status
)) {
5925 /* NB. We check for open_was_deferred in the caller. */
5929 /* See RAW-SFILEINFO-END-OF-FILE */
5930 if (fail_after_createfile
) {
5931 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5932 return NT_STATUS_INVALID_LEVEL
;
5935 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5936 status
= map_nt_error_from_unix(errno
);
5937 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5941 trigger_write_time_update_immediate(new_fsp
);
5942 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5943 return NT_STATUS_OK
;
5946 /****************************************************************************
5947 Deal with SMB_INFO_SET_EA.
5948 ****************************************************************************/
5950 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5954 const struct smb_filename
*smb_fname
)
5956 struct ea_list
*ea_list
= NULL
;
5957 TALLOC_CTX
*ctx
= NULL
;
5958 NTSTATUS status
= NT_STATUS_OK
;
5960 if (total_data
< 10) {
5962 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5963 length. They seem to have no effect. Bug #3212. JRA */
5965 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5966 /* We're done. We only get EA info in this call. */
5967 return NT_STATUS_OK
;
5970 return NT_STATUS_INVALID_PARAMETER
;
5973 if (IVAL(pdata
,0) > total_data
) {
5974 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5975 IVAL(pdata
,0), (unsigned int)total_data
));
5976 return NT_STATUS_INVALID_PARAMETER
;
5980 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5982 return NT_STATUS_INVALID_PARAMETER
;
5985 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5990 /****************************************************************************
5991 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5992 ****************************************************************************/
5994 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5999 struct ea_list
*ea_list
= NULL
;
6003 return NT_STATUS_INVALID_HANDLE
;
6006 if (!lp_ea_support(SNUM(conn
))) {
6007 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6008 "EA's not supported.\n",
6009 (unsigned int)total_data
));
6010 return NT_STATUS_EAS_NOT_SUPPORTED
;
6013 if (total_data
< 10) {
6014 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6016 (unsigned int)total_data
));
6017 return NT_STATUS_INVALID_PARAMETER
;
6020 ea_list
= read_nttrans_ea_list(talloc_tos(),
6025 return NT_STATUS_INVALID_PARAMETER
;
6028 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6030 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6031 smb_fname_str_dbg(fsp
->fsp_name
),
6032 nt_errstr(status
) ));
6038 /****************************************************************************
6039 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6040 ****************************************************************************/
6042 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6046 struct smb_filename
*smb_fname
)
6048 NTSTATUS status
= NT_STATUS_OK
;
6049 bool delete_on_close
;
6052 if (total_data
< 1) {
6053 return NT_STATUS_INVALID_PARAMETER
;
6057 return NT_STATUS_INVALID_HANDLE
;
6060 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6061 dosmode
= dos_mode(conn
, smb_fname
);
6063 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6064 "delete_on_close = %u\n",
6065 smb_fname_str_dbg(smb_fname
),
6066 (unsigned int)dosmode
,
6067 (unsigned int)delete_on_close
));
6069 if (delete_on_close
) {
6070 status
= can_set_delete_on_close(fsp
, dosmode
);
6071 if (!NT_STATUS_IS_OK(status
)) {
6076 /* The set is across all open files on this dev/inode pair. */
6077 if (!set_delete_on_close(fsp
, delete_on_close
,
6078 conn
->session_info
->security_token
,
6079 conn
->session_info
->unix_token
)) {
6080 return NT_STATUS_ACCESS_DENIED
;
6082 return NT_STATUS_OK
;
6085 /****************************************************************************
6086 Deal with SMB_FILE_POSITION_INFORMATION.
6087 ****************************************************************************/
6089 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6094 uint64_t position_information
;
6096 if (total_data
< 8) {
6097 return NT_STATUS_INVALID_PARAMETER
;
6101 /* Ignore on pathname based set. */
6102 return NT_STATUS_OK
;
6105 position_information
= (uint64_t)IVAL(pdata
,0);
6106 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6108 DEBUG(10,("smb_file_position_information: Set file position "
6109 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6110 (double)position_information
));
6111 fsp
->fh
->position_information
= position_information
;
6112 return NT_STATUS_OK
;
6115 /****************************************************************************
6116 Deal with SMB_FILE_MODE_INFORMATION.
6117 ****************************************************************************/
6119 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6125 if (total_data
< 4) {
6126 return NT_STATUS_INVALID_PARAMETER
;
6128 mode
= IVAL(pdata
,0);
6129 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6130 return NT_STATUS_INVALID_PARAMETER
;
6132 return NT_STATUS_OK
;
6135 /****************************************************************************
6136 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6137 ****************************************************************************/
6139 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6140 struct smb_request
*req
,
6143 const struct smb_filename
*smb_fname
)
6145 char *link_target
= NULL
;
6146 const char *newname
= smb_fname
->base_name
;
6147 TALLOC_CTX
*ctx
= talloc_tos();
6149 /* Set a symbolic link. */
6150 /* Don't allow this if follow links is false. */
6152 if (total_data
== 0) {
6153 return NT_STATUS_INVALID_PARAMETER
;
6156 if (!lp_symlinks(SNUM(conn
))) {
6157 return NT_STATUS_ACCESS_DENIED
;
6160 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6161 total_data
, STR_TERMINATE
);
6164 return NT_STATUS_INVALID_PARAMETER
;
6167 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6168 newname
, link_target
));
6170 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6171 return map_nt_error_from_unix(errno
);
6174 return NT_STATUS_OK
;
6177 /****************************************************************************
6178 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6179 ****************************************************************************/
6181 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6182 struct smb_request
*req
,
6183 const char *pdata
, int total_data
,
6184 struct smb_filename
*smb_fname_new
)
6186 char *oldname
= NULL
;
6187 struct smb_filename
*smb_fname_old
= NULL
;
6188 TALLOC_CTX
*ctx
= talloc_tos();
6189 NTSTATUS status
= NT_STATUS_OK
;
6191 /* Set a hard link. */
6192 if (total_data
== 0) {
6193 return NT_STATUS_INVALID_PARAMETER
;
6196 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6197 total_data
, STR_TERMINATE
, &status
);
6198 if (!NT_STATUS_IS_OK(status
)) {
6202 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6203 smb_fname_str_dbg(smb_fname_new
), oldname
));
6205 status
= filename_convert(ctx
,
6207 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6212 if (!NT_STATUS_IS_OK(status
)) {
6216 return hardlink_internals(ctx
, conn
, req
, false,
6217 smb_fname_old
, smb_fname_new
);
6220 /****************************************************************************
6221 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6222 ****************************************************************************/
6224 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6225 struct smb_request
*req
,
6229 struct smb_filename
*smb_fname_src
)
6233 char *newname
= NULL
;
6234 struct smb_filename
*smb_fname_dst
= NULL
;
6235 NTSTATUS status
= NT_STATUS_OK
;
6236 TALLOC_CTX
*ctx
= talloc_tos();
6239 return NT_STATUS_INVALID_HANDLE
;
6242 if (total_data
< 20) {
6243 return NT_STATUS_INVALID_PARAMETER
;
6246 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6247 len
= IVAL(pdata
,16);
6249 if (len
> (total_data
- 20) || (len
== 0)) {
6250 return NT_STATUS_INVALID_PARAMETER
;
6253 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6254 &pdata
[20], len
, STR_TERMINATE
,
6256 if (!NT_STATUS_IS_OK(status
)) {
6260 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6263 status
= filename_convert(ctx
,
6265 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6270 if (!NT_STATUS_IS_OK(status
)) {
6274 if (fsp
->base_fsp
) {
6275 /* newname must be a stream name. */
6276 if (newname
[0] != ':') {
6277 return NT_STATUS_NOT_SUPPORTED
;
6280 /* Create an smb_fname to call rename_internals_fsp() with. */
6281 smb_fname_dst
= synthetic_smb_fname(
6282 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6284 if (smb_fname_dst
== NULL
) {
6285 status
= NT_STATUS_NO_MEMORY
;
6290 * Set the original last component, since
6291 * rename_internals_fsp() requires it.
6293 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6295 if (smb_fname_dst
->original_lcomp
== NULL
) {
6296 status
= NT_STATUS_NO_MEMORY
;
6302 DEBUG(10,("smb2_file_rename_information: "
6303 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6304 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6305 smb_fname_str_dbg(smb_fname_dst
)));
6306 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6307 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6311 TALLOC_FREE(smb_fname_dst
);
6315 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6316 struct smb_request
*req
,
6320 struct smb_filename
*smb_fname_src
)
6324 char *newname
= NULL
;
6325 struct smb_filename
*smb_fname_dst
= NULL
;
6326 NTSTATUS status
= NT_STATUS_OK
;
6327 TALLOC_CTX
*ctx
= talloc_tos();
6330 return NT_STATUS_INVALID_HANDLE
;
6333 if (total_data
< 20) {
6334 return NT_STATUS_INVALID_PARAMETER
;
6337 overwrite
= (CVAL(pdata
,0) ? true : false);
6338 len
= IVAL(pdata
,16);
6340 if (len
> (total_data
- 20) || (len
== 0)) {
6341 return NT_STATUS_INVALID_PARAMETER
;
6344 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6345 &pdata
[20], len
, STR_TERMINATE
,
6347 if (!NT_STATUS_IS_OK(status
)) {
6351 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6354 status
= filename_convert(ctx
,
6356 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6361 if (!NT_STATUS_IS_OK(status
)) {
6365 if (fsp
->base_fsp
) {
6366 /* No stream names. */
6367 return NT_STATUS_NOT_SUPPORTED
;
6370 DEBUG(10,("smb_file_link_information: "
6371 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6372 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6373 smb_fname_str_dbg(smb_fname_dst
)));
6374 status
= hardlink_internals(ctx
,
6381 TALLOC_FREE(smb_fname_dst
);
6385 /****************************************************************************
6386 Deal with SMB_FILE_RENAME_INFORMATION.
6387 ****************************************************************************/
6389 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6390 struct smb_request
*req
,
6394 struct smb_filename
*smb_fname_src
)
6399 char *newname
= NULL
;
6400 struct smb_filename
*smb_fname_dst
= NULL
;
6401 bool dest_has_wcard
= False
;
6402 NTSTATUS status
= NT_STATUS_OK
;
6404 TALLOC_CTX
*ctx
= talloc_tos();
6406 if (total_data
< 13) {
6407 return NT_STATUS_INVALID_PARAMETER
;
6410 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6411 root_fid
= IVAL(pdata
,4);
6412 len
= IVAL(pdata
,8);
6414 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6421 if (!NT_STATUS_IS_OK(status
)) {
6425 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6428 status
= resolve_dfspath_wcard(ctx
, conn
,
6429 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6432 !conn
->sconn
->using_smb2
,
6435 if (!NT_STATUS_IS_OK(status
)) {
6439 /* Check the new name has no '/' characters. */
6440 if (strchr_m(newname
, '/')) {
6441 return NT_STATUS_NOT_SUPPORTED
;
6444 if (fsp
&& fsp
->base_fsp
) {
6445 /* newname must be a stream name. */
6446 if (newname
[0] != ':') {
6447 return NT_STATUS_NOT_SUPPORTED
;
6450 /* Create an smb_fname to call rename_internals_fsp() with. */
6451 smb_fname_dst
= synthetic_smb_fname(
6452 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6454 if (smb_fname_dst
== NULL
) {
6455 status
= NT_STATUS_NO_MEMORY
;
6460 * Set the original last component, since
6461 * rename_internals_fsp() requires it.
6463 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6465 if (smb_fname_dst
->original_lcomp
== NULL
) {
6466 status
= NT_STATUS_NO_MEMORY
;
6472 * Build up an smb_fname_dst based on the filename passed in.
6473 * We basically just strip off the last component, and put on
6474 * the newname instead.
6476 char *base_name
= NULL
;
6478 /* newname must *not* be a stream name. */
6479 if (newname
[0] == ':') {
6480 return NT_STATUS_NOT_SUPPORTED
;
6484 * Strip off the last component (filename) of the path passed
6487 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6489 return NT_STATUS_NO_MEMORY
;
6491 p
= strrchr_m(base_name
, '/');
6495 base_name
= talloc_strdup(ctx
, "");
6497 return NT_STATUS_NO_MEMORY
;
6500 /* Append the new name. */
6501 base_name
= talloc_asprintf_append(base_name
,
6505 return NT_STATUS_NO_MEMORY
;
6508 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6511 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6514 /* If an error we expect this to be
6515 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6517 if (!NT_STATUS_IS_OK(status
)) {
6518 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6522 /* Create an smb_fname to call rename_internals_fsp() */
6523 smb_fname_dst
= synthetic_smb_fname(
6524 ctx
, base_name
, NULL
, NULL
);
6525 if (smb_fname_dst
== NULL
) {
6526 status
= NT_STATUS_NO_MEMORY
;
6533 DEBUG(10,("smb_file_rename_information: "
6534 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6535 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6536 smb_fname_str_dbg(smb_fname_dst
)));
6537 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6540 DEBUG(10,("smb_file_rename_information: "
6541 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6542 smb_fname_str_dbg(smb_fname_src
),
6543 smb_fname_str_dbg(smb_fname_dst
)));
6544 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6545 smb_fname_dst
, 0, overwrite
, false,
6547 FILE_WRITE_ATTRIBUTES
);
6550 TALLOC_FREE(smb_fname_dst
);
6554 /****************************************************************************
6555 Deal with SMB_SET_POSIX_ACL.
6556 ****************************************************************************/
6558 #if defined(HAVE_POSIX_ACLS)
6559 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6563 const struct smb_filename
*smb_fname
)
6565 uint16 posix_acl_version
;
6566 uint16 num_file_acls
;
6567 uint16 num_def_acls
;
6568 bool valid_file_acls
= True
;
6569 bool valid_def_acls
= True
;
6571 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6572 return NT_STATUS_INVALID_PARAMETER
;
6574 posix_acl_version
= SVAL(pdata
,0);
6575 num_file_acls
= SVAL(pdata
,2);
6576 num_def_acls
= SVAL(pdata
,4);
6578 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6579 valid_file_acls
= False
;
6583 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6584 valid_def_acls
= False
;
6588 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6589 return NT_STATUS_INVALID_PARAMETER
;
6592 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6593 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6594 return NT_STATUS_INVALID_PARAMETER
;
6597 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6598 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6599 (unsigned int)num_file_acls
,
6600 (unsigned int)num_def_acls
));
6602 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6603 smb_fname
->base_name
, num_file_acls
,
6604 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6605 return map_nt_error_from_unix(errno
);
6608 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6609 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6610 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6611 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6612 return map_nt_error_from_unix(errno
);
6614 return NT_STATUS_OK
;
6618 /****************************************************************************
6619 Deal with SMB_SET_POSIX_LOCK.
6620 ****************************************************************************/
6622 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6623 struct smb_request
*req
,
6631 bool blocking_lock
= False
;
6632 enum brl_type lock_type
;
6634 NTSTATUS status
= NT_STATUS_OK
;
6636 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6637 return NT_STATUS_INVALID_HANDLE
;
6640 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6641 return NT_STATUS_INVALID_PARAMETER
;
6644 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6645 case POSIX_LOCK_TYPE_READ
:
6646 lock_type
= READ_LOCK
;
6648 case POSIX_LOCK_TYPE_WRITE
:
6649 /* Return the right POSIX-mappable error code for files opened read-only. */
6650 if (!fsp
->can_write
) {
6651 return NT_STATUS_INVALID_HANDLE
;
6653 lock_type
= WRITE_LOCK
;
6655 case POSIX_LOCK_TYPE_UNLOCK
:
6656 lock_type
= UNLOCK_LOCK
;
6659 return NT_STATUS_INVALID_PARAMETER
;
6662 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6663 blocking_lock
= False
;
6664 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6665 blocking_lock
= True
;
6667 return NT_STATUS_INVALID_PARAMETER
;
6670 if (!lp_blocking_locks(SNUM(conn
))) {
6671 blocking_lock
= False
;
6674 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6675 #if defined(HAVE_LONGLONG)
6676 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6677 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6678 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6679 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6680 #else /* HAVE_LONGLONG */
6681 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6682 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6683 #endif /* HAVE_LONGLONG */
6685 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6686 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6688 (unsigned int)lock_type
,
6689 (unsigned long long)smblctx
,
6693 if (lock_type
== UNLOCK_LOCK
) {
6694 status
= do_unlock(req
->sconn
->msg_ctx
,
6701 uint64_t block_smblctx
;
6703 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6715 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6717 * A blocking lock was requested. Package up
6718 * this smb into a queued request and push it
6719 * onto the blocking lock queue.
6721 if(push_blocking_lock_request(br_lck
,
6724 -1, /* infinite timeout. */
6732 TALLOC_FREE(br_lck
);
6736 TALLOC_FREE(br_lck
);
6742 /****************************************************************************
6743 Deal with SMB_SET_FILE_BASIC_INFO.
6744 ****************************************************************************/
6746 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6750 const struct smb_filename
*smb_fname
)
6752 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6753 struct smb_file_time ft
;
6755 NTSTATUS status
= NT_STATUS_OK
;
6759 if (total_data
< 36) {
6760 return NT_STATUS_INVALID_PARAMETER
;
6763 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6764 if (!NT_STATUS_IS_OK(status
)) {
6768 /* Set the attributes */
6769 dosmode
= IVAL(pdata
,32);
6770 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6771 if (!NT_STATUS_IS_OK(status
)) {
6776 ft
.create_time
= interpret_long_date(pdata
);
6779 ft
.atime
= interpret_long_date(pdata
+8);
6782 ft
.mtime
= interpret_long_date(pdata
+16);
6785 ft
.ctime
= interpret_long_date(pdata
+24);
6787 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6788 smb_fname_str_dbg(smb_fname
)));
6790 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6794 /****************************************************************************
6795 Deal with SMB_INFO_STANDARD.
6796 ****************************************************************************/
6798 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6802 const struct smb_filename
*smb_fname
)
6805 struct smb_file_time ft
;
6809 if (total_data
< 12) {
6810 return NT_STATUS_INVALID_PARAMETER
;
6814 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6816 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6818 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6820 DEBUG(10,("smb_set_info_standard: file %s\n",
6821 smb_fname_str_dbg(smb_fname
)));
6823 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6824 if (!NT_STATUS_IS_OK(status
)) {
6828 return smb_set_file_time(conn
,
6835 /****************************************************************************
6836 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6837 ****************************************************************************/
6839 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6840 struct smb_request
*req
,
6844 struct smb_filename
*smb_fname
)
6846 uint64_t allocation_size
= 0;
6847 NTSTATUS status
= NT_STATUS_OK
;
6848 files_struct
*new_fsp
= NULL
;
6850 if (!VALID_STAT(smb_fname
->st
)) {
6851 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6854 if (total_data
< 8) {
6855 return NT_STATUS_INVALID_PARAMETER
;
6858 allocation_size
= (uint64_t)IVAL(pdata
,0);
6859 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6860 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6861 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6862 (double)allocation_size
));
6864 if (allocation_size
) {
6865 allocation_size
= smb_roundup(conn
, allocation_size
);
6868 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6869 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6870 (double)allocation_size
));
6872 if (fsp
&& fsp
->fh
->fd
!= -1) {
6873 /* Open file handle. */
6874 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6875 return NT_STATUS_ACCESS_DENIED
;
6878 /* Only change if needed. */
6879 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6880 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6881 return map_nt_error_from_unix(errno
);
6884 /* But always update the time. */
6886 * This is equivalent to a write. Ensure it's seen immediately
6887 * if there are no pending writes.
6889 trigger_write_time_update_immediate(fsp
);
6890 return NT_STATUS_OK
;
6893 /* Pathname or stat or directory file. */
6894 status
= SMB_VFS_CREATE_FILE(
6897 0, /* root_dir_fid */
6898 smb_fname
, /* fname */
6899 FILE_WRITE_DATA
, /* access_mask */
6900 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6902 FILE_OPEN
, /* create_disposition*/
6903 0, /* create_options */
6904 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6905 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6906 0, /* allocation_size */
6907 0, /* private_flags */
6910 &new_fsp
, /* result */
6913 if (!NT_STATUS_IS_OK(status
)) {
6914 /* NB. We check for open_was_deferred in the caller. */
6918 /* Only change if needed. */
6919 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6920 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6921 status
= map_nt_error_from_unix(errno
);
6922 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6927 /* Changing the allocation size should set the last mod time. */
6929 * This is equivalent to a write. Ensure it's seen immediately
6930 * if there are no pending writes.
6932 trigger_write_time_update_immediate(new_fsp
);
6934 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6935 return NT_STATUS_OK
;
6938 /****************************************************************************
6939 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6940 ****************************************************************************/
6942 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6943 struct smb_request
*req
,
6947 const struct smb_filename
*smb_fname
,
6948 bool fail_after_createfile
)
6952 if (total_data
< 8) {
6953 return NT_STATUS_INVALID_PARAMETER
;
6956 size
= IVAL(pdata
,0);
6957 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6958 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6959 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6962 return smb_set_file_size(conn
, req
,
6967 fail_after_createfile
);
6970 /****************************************************************************
6971 Allow a UNIX info mknod.
6972 ****************************************************************************/
6974 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6977 const struct smb_filename
*smb_fname
)
6979 uint32 file_type
= IVAL(pdata
,56);
6980 #if defined(HAVE_MAKEDEV)
6981 uint32 dev_major
= IVAL(pdata
,60);
6982 uint32 dev_minor
= IVAL(pdata
,68);
6984 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6985 uint32 raw_unixmode
= IVAL(pdata
,84);
6989 if (total_data
< 100) {
6990 return NT_STATUS_INVALID_PARAMETER
;
6993 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6994 PERM_NEW_FILE
, &unixmode
);
6995 if (!NT_STATUS_IS_OK(status
)) {
6999 #if defined(HAVE_MAKEDEV)
7000 dev
= makedev(dev_major
, dev_minor
);
7003 switch (file_type
) {
7004 #if defined(S_IFIFO)
7005 case UNIX_TYPE_FIFO
:
7006 unixmode
|= S_IFIFO
;
7009 #if defined(S_IFSOCK)
7010 case UNIX_TYPE_SOCKET
:
7011 unixmode
|= S_IFSOCK
;
7014 #if defined(S_IFCHR)
7015 case UNIX_TYPE_CHARDEV
:
7016 unixmode
|= S_IFCHR
;
7019 #if defined(S_IFBLK)
7020 case UNIX_TYPE_BLKDEV
:
7021 unixmode
|= S_IFBLK
;
7025 return NT_STATUS_INVALID_PARAMETER
;
7028 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7029 "%.0f mode 0%o for file %s\n", (double)dev
,
7030 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7032 /* Ok - do the mknod. */
7033 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7034 return map_nt_error_from_unix(errno
);
7037 /* If any of the other "set" calls fail we
7038 * don't want to end up with a half-constructed mknod.
7041 if (lp_inherit_perms(SNUM(conn
))) {
7043 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7045 return NT_STATUS_NO_MEMORY
;
7047 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7049 TALLOC_FREE(parent
);
7052 return NT_STATUS_OK
;
7055 /****************************************************************************
7056 Deal with SMB_SET_FILE_UNIX_BASIC.
7057 ****************************************************************************/
7059 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7060 struct smb_request
*req
,
7064 const struct smb_filename
*smb_fname
)
7066 struct smb_file_time ft
;
7067 uint32 raw_unixmode
;
7070 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7071 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7072 NTSTATUS status
= NT_STATUS_OK
;
7073 bool delete_on_fail
= False
;
7074 enum perm_type ptype
;
7075 files_struct
*all_fsps
= NULL
;
7076 bool modify_mtime
= true;
7078 struct smb_filename
*smb_fname_tmp
= NULL
;
7079 SMB_STRUCT_STAT sbuf
;
7083 if (total_data
< 100) {
7084 return NT_STATUS_INVALID_PARAMETER
;
7087 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7088 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7089 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7090 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7093 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7094 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7095 set_owner
= (uid_t
)IVAL(pdata
,40);
7096 set_grp
= (gid_t
)IVAL(pdata
,48);
7097 raw_unixmode
= IVAL(pdata
,84);
7099 if (VALID_STAT(smb_fname
->st
)) {
7100 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7101 ptype
= PERM_EXISTING_DIR
;
7103 ptype
= PERM_EXISTING_FILE
;
7106 ptype
= PERM_NEW_FILE
;
7109 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7111 if (!NT_STATUS_IS_OK(status
)) {
7115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7116 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7117 smb_fname_str_dbg(smb_fname
), (double)size
,
7118 (unsigned int)set_owner
, (unsigned int)set_grp
,
7119 (int)raw_unixmode
));
7121 sbuf
= smb_fname
->st
;
7123 if (!VALID_STAT(sbuf
)) {
7125 * The only valid use of this is to create character and block
7126 * devices, and named pipes. This is deprecated (IMHO) and
7127 * a new info level should be used for mknod. JRA.
7130 status
= smb_unix_mknod(conn
,
7134 if (!NT_STATUS_IS_OK(status
)) {
7138 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7139 if (smb_fname_tmp
== NULL
) {
7140 return NT_STATUS_NO_MEMORY
;
7143 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7144 status
= map_nt_error_from_unix(errno
);
7145 TALLOC_FREE(smb_fname_tmp
);
7146 SMB_VFS_UNLINK(conn
, smb_fname
);
7150 sbuf
= smb_fname_tmp
->st
;
7151 smb_fname
= smb_fname_tmp
;
7153 /* Ensure we don't try and change anything else. */
7154 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7155 size
= get_file_size_stat(&sbuf
);
7156 ft
.atime
= sbuf
.st_ex_atime
;
7157 ft
.mtime
= sbuf
.st_ex_mtime
;
7159 * We continue here as we might want to change the
7162 delete_on_fail
= True
;
7166 /* Horrible backwards compatibility hack as an old server bug
7167 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7171 size
= get_file_size_stat(&sbuf
);
7176 * Deal with the UNIX specific mode set.
7179 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7180 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7181 "setting mode 0%o for file %s\n",
7182 (unsigned int)unixmode
,
7183 smb_fname_str_dbg(smb_fname
)));
7184 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7185 return map_nt_error_from_unix(errno
);
7190 * Deal with the UNIX specific uid set.
7193 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7194 (sbuf
.st_ex_uid
!= set_owner
)) {
7197 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7198 "changing owner %u for path %s\n",
7199 (unsigned int)set_owner
,
7200 smb_fname_str_dbg(smb_fname
)));
7202 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7203 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7204 set_owner
, (gid_t
)-1);
7206 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7207 set_owner
, (gid_t
)-1);
7211 status
= map_nt_error_from_unix(errno
);
7212 if (delete_on_fail
) {
7213 SMB_VFS_UNLINK(conn
, smb_fname
);
7220 * Deal with the UNIX specific gid set.
7223 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7224 (sbuf
.st_ex_gid
!= set_grp
)) {
7225 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7226 "changing group %u for file %s\n",
7227 (unsigned int)set_owner
,
7228 smb_fname_str_dbg(smb_fname
)));
7229 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7231 status
= map_nt_error_from_unix(errno
);
7232 if (delete_on_fail
) {
7233 SMB_VFS_UNLINK(conn
, smb_fname
);
7239 /* Deal with any size changes. */
7241 status
= smb_set_file_size(conn
, req
,
7247 if (!NT_STATUS_IS_OK(status
)) {
7251 /* Deal with any time changes. */
7252 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7253 /* No change, don't cancel anything. */
7257 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7258 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7259 all_fsps
= file_find_di_next(all_fsps
)) {
7261 * We're setting the time explicitly for UNIX.
7262 * Cancel any pending changes over all handles.
7264 all_fsps
->update_write_time_on_close
= false;
7265 TALLOC_FREE(all_fsps
->update_write_time_event
);
7269 * Override the "setting_write_time"
7270 * parameter here as it almost does what
7271 * we need. Just remember if we modified
7272 * mtime and send the notify ourselves.
7274 if (null_timespec(ft
.mtime
)) {
7275 modify_mtime
= false;
7278 status
= smb_set_file_time(conn
,
7284 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7285 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7290 /****************************************************************************
7291 Deal with SMB_SET_FILE_UNIX_INFO2.
7292 ****************************************************************************/
7294 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7295 struct smb_request
*req
,
7299 const struct smb_filename
*smb_fname
)
7305 if (total_data
< 116) {
7306 return NT_STATUS_INVALID_PARAMETER
;
7309 /* Start by setting all the fields that are common between UNIX_BASIC
7312 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7314 if (!NT_STATUS_IS_OK(status
)) {
7318 smb_fflags
= IVAL(pdata
, 108);
7319 smb_fmask
= IVAL(pdata
, 112);
7321 /* NB: We should only attempt to alter the file flags if the client
7322 * sends a non-zero mask.
7324 if (smb_fmask
!= 0) {
7325 int stat_fflags
= 0;
7327 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7328 smb_fmask
, &stat_fflags
)) {
7329 /* Client asked to alter a flag we don't understand. */
7330 return NT_STATUS_INVALID_PARAMETER
;
7333 if (fsp
&& fsp
->fh
->fd
!= -1) {
7334 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7335 return NT_STATUS_NOT_SUPPORTED
;
7337 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7338 stat_fflags
) != 0) {
7339 return map_nt_error_from_unix(errno
);
7344 /* XXX: need to add support for changing the create_time here. You
7345 * can do this for paths on Darwin with setattrlist(2). The right way
7346 * to hook this up is probably by extending the VFS utimes interface.
7349 return NT_STATUS_OK
;
7352 /****************************************************************************
7353 Create a directory with POSIX semantics.
7354 ****************************************************************************/
7356 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7357 struct smb_request
*req
,
7360 struct smb_filename
*smb_fname
,
7361 int *pdata_return_size
)
7363 NTSTATUS status
= NT_STATUS_OK
;
7364 uint32 raw_unixmode
= 0;
7365 uint32 mod_unixmode
= 0;
7366 mode_t unixmode
= (mode_t
)0;
7367 files_struct
*fsp
= NULL
;
7368 uint16 info_level_return
= 0;
7370 char *pdata
= *ppdata
;
7372 if (total_data
< 18) {
7373 return NT_STATUS_INVALID_PARAMETER
;
7376 raw_unixmode
= IVAL(pdata
,8);
7377 /* Next 4 bytes are not yet defined. */
7379 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7380 PERM_NEW_DIR
, &unixmode
);
7381 if (!NT_STATUS_IS_OK(status
)) {
7385 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7387 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7388 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7390 status
= SMB_VFS_CREATE_FILE(
7393 0, /* root_dir_fid */
7394 smb_fname
, /* fname */
7395 FILE_READ_ATTRIBUTES
, /* access_mask */
7396 FILE_SHARE_NONE
, /* share_access */
7397 FILE_CREATE
, /* create_disposition*/
7398 FILE_DIRECTORY_FILE
, /* create_options */
7399 mod_unixmode
, /* file_attributes */
7400 0, /* oplock_request */
7401 0, /* allocation_size */
7402 0, /* private_flags */
7408 if (NT_STATUS_IS_OK(status
)) {
7409 close_file(req
, fsp
, NORMAL_CLOSE
);
7412 info_level_return
= SVAL(pdata
,16);
7414 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7415 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7416 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7417 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7419 *pdata_return_size
= 12;
7422 /* Realloc the data size */
7423 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7424 if (*ppdata
== NULL
) {
7425 *pdata_return_size
= 0;
7426 return NT_STATUS_NO_MEMORY
;
7430 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7431 SSVAL(pdata
,2,0); /* No fnum. */
7432 SIVAL(pdata
,4,info
); /* Was directory created. */
7434 switch (info_level_return
) {
7435 case SMB_QUERY_FILE_UNIX_BASIC
:
7436 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7437 SSVAL(pdata
,10,0); /* Padding. */
7438 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7441 case SMB_QUERY_FILE_UNIX_INFO2
:
7442 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7443 SSVAL(pdata
,10,0); /* Padding. */
7444 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7448 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7449 SSVAL(pdata
,10,0); /* Padding. */
7456 /****************************************************************************
7457 Open/Create a file with POSIX semantics.
7458 ****************************************************************************/
7460 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7461 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7463 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7464 struct smb_request
*req
,
7467 struct smb_filename
*smb_fname
,
7468 int *pdata_return_size
)
7470 bool extended_oplock_granted
= False
;
7471 char *pdata
= *ppdata
;
7473 uint32 wire_open_mode
= 0;
7474 uint32 raw_unixmode
= 0;
7475 uint32 mod_unixmode
= 0;
7476 uint32 create_disp
= 0;
7477 uint32 access_mask
= 0;
7478 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7479 NTSTATUS status
= NT_STATUS_OK
;
7480 mode_t unixmode
= (mode_t
)0;
7481 files_struct
*fsp
= NULL
;
7482 int oplock_request
= 0;
7484 uint16 info_level_return
= 0;
7486 if (total_data
< 18) {
7487 return NT_STATUS_INVALID_PARAMETER
;
7490 flags
= IVAL(pdata
,0);
7491 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7492 if (oplock_request
) {
7493 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7496 wire_open_mode
= IVAL(pdata
,4);
7498 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7499 return smb_posix_mkdir(conn
, req
,
7506 switch (wire_open_mode
& SMB_ACCMODE
) {
7508 access_mask
= SMB_O_RDONLY_MAPPING
;
7511 access_mask
= SMB_O_WRONLY_MAPPING
;
7514 access_mask
= (SMB_O_RDONLY_MAPPING
|
7515 SMB_O_WRONLY_MAPPING
);
7518 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7519 (unsigned int)wire_open_mode
));
7520 return NT_STATUS_INVALID_PARAMETER
;
7523 wire_open_mode
&= ~SMB_ACCMODE
;
7525 /* First take care of O_CREAT|O_EXCL interactions. */
7526 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7527 case (SMB_O_CREAT
| SMB_O_EXCL
):
7528 /* File exists fail. File not exist create. */
7529 create_disp
= FILE_CREATE
;
7532 /* File exists open. File not exist create. */
7533 create_disp
= FILE_OPEN_IF
;
7536 /* O_EXCL on its own without O_CREAT is undefined.
7537 We deliberately ignore it as some versions of
7538 Linux CIFSFS can send a bare O_EXCL on the
7539 wire which other filesystems in the kernel
7540 ignore. See bug 9519 for details. */
7545 /* File exists open. File not exist fail. */
7546 create_disp
= FILE_OPEN
;
7549 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7550 (unsigned int)wire_open_mode
));
7551 return NT_STATUS_INVALID_PARAMETER
;
7554 /* Next factor in the effects of O_TRUNC. */
7555 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7557 if (wire_open_mode
& SMB_O_TRUNC
) {
7558 switch (create_disp
) {
7560 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7561 /* Leave create_disp alone as
7562 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7564 /* File exists fail. File not exist create. */
7567 /* SMB_O_CREAT | SMB_O_TRUNC */
7568 /* File exists overwrite. File not exist create. */
7569 create_disp
= FILE_OVERWRITE_IF
;
7573 /* File exists overwrite. File not exist fail. */
7574 create_disp
= FILE_OVERWRITE
;
7577 /* Cannot get here. */
7578 smb_panic("smb_posix_open: logic error");
7579 return NT_STATUS_INVALID_PARAMETER
;
7583 raw_unixmode
= IVAL(pdata
,8);
7584 /* Next 4 bytes are not yet defined. */
7586 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7587 (VALID_STAT(smb_fname
->st
) ?
7588 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7591 if (!NT_STATUS_IS_OK(status
)) {
7595 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7597 if (wire_open_mode
& SMB_O_SYNC
) {
7598 create_options
|= FILE_WRITE_THROUGH
;
7600 if (wire_open_mode
& SMB_O_APPEND
) {
7601 access_mask
|= FILE_APPEND_DATA
;
7603 if (wire_open_mode
& SMB_O_DIRECT
) {
7604 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7607 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7608 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7609 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7610 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7612 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7613 create_options
|= FILE_DIRECTORY_FILE
;
7616 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7617 smb_fname_str_dbg(smb_fname
),
7618 (unsigned int)wire_open_mode
,
7619 (unsigned int)unixmode
));
7621 status
= SMB_VFS_CREATE_FILE(
7624 0, /* root_dir_fid */
7625 smb_fname
, /* fname */
7626 access_mask
, /* access_mask */
7627 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7629 create_disp
, /* create_disposition*/
7630 create_options
, /* create_options */
7631 mod_unixmode
, /* file_attributes */
7632 oplock_request
, /* oplock_request */
7633 0, /* allocation_size */
7634 0, /* private_flags */
7640 if (!NT_STATUS_IS_OK(status
)) {
7644 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7645 extended_oplock_granted
= True
;
7648 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7649 extended_oplock_granted
= True
;
7652 info_level_return
= SVAL(pdata
,16);
7654 /* Allocate the correct return size. */
7656 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7657 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7658 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7659 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7661 *pdata_return_size
= 12;
7664 /* Realloc the data size */
7665 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7666 if (*ppdata
== NULL
) {
7667 close_file(req
, fsp
, ERROR_CLOSE
);
7668 *pdata_return_size
= 0;
7669 return NT_STATUS_NO_MEMORY
;
7673 if (extended_oplock_granted
) {
7674 if (flags
& REQUEST_BATCH_OPLOCK
) {
7675 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7677 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7679 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7680 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7682 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7685 SSVAL(pdata
,2,fsp
->fnum
);
7686 SIVAL(pdata
,4,info
); /* Was file created etc. */
7688 switch (info_level_return
) {
7689 case SMB_QUERY_FILE_UNIX_BASIC
:
7690 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7691 SSVAL(pdata
,10,0); /* padding. */
7692 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7695 case SMB_QUERY_FILE_UNIX_INFO2
:
7696 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7697 SSVAL(pdata
,10,0); /* padding. */
7698 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7702 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7703 SSVAL(pdata
,10,0); /* padding. */
7706 return NT_STATUS_OK
;
7709 /****************************************************************************
7710 Delete a file with POSIX semantics.
7711 ****************************************************************************/
7713 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7714 struct smb_request
*req
,
7717 struct smb_filename
*smb_fname
)
7719 NTSTATUS status
= NT_STATUS_OK
;
7720 files_struct
*fsp
= NULL
;
7724 int create_options
= 0;
7726 struct share_mode_lock
*lck
= NULL
;
7728 if (total_data
< 2) {
7729 return NT_STATUS_INVALID_PARAMETER
;
7732 flags
= SVAL(pdata
,0);
7734 if (!VALID_STAT(smb_fname
->st
)) {
7735 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7738 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7739 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7740 return NT_STATUS_NOT_A_DIRECTORY
;
7743 DEBUG(10,("smb_posix_unlink: %s %s\n",
7744 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7745 smb_fname_str_dbg(smb_fname
)));
7747 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7748 create_options
|= FILE_DIRECTORY_FILE
;
7751 status
= SMB_VFS_CREATE_FILE(
7754 0, /* root_dir_fid */
7755 smb_fname
, /* fname */
7756 DELETE_ACCESS
, /* access_mask */
7757 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7759 FILE_OPEN
, /* create_disposition*/
7760 create_options
, /* create_options */
7761 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7762 0, /* oplock_request */
7763 0, /* allocation_size */
7764 0, /* private_flags */
7770 if (!NT_STATUS_IS_OK(status
)) {
7775 * Don't lie to client. If we can't really delete due to
7776 * non-POSIX opens return SHARING_VIOLATION.
7779 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7781 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7782 "lock for file %s\n", fsp_str_dbg(fsp
)));
7783 close_file(req
, fsp
, NORMAL_CLOSE
);
7784 return NT_STATUS_INVALID_PARAMETER
;
7788 * See if others still have the file open. If this is the case, then
7789 * don't delete. If all opens are POSIX delete we can set the delete
7790 * on close disposition.
7792 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7793 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7794 if (is_valid_share_mode_entry(e
)) {
7795 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7798 if (share_mode_stale_pid(lck
->data
, i
)) {
7801 /* Fail with sharing violation. */
7803 close_file(req
, fsp
, NORMAL_CLOSE
);
7804 return NT_STATUS_SHARING_VIOLATION
;
7809 * Set the delete on close.
7811 status
= smb_set_file_disposition_info(conn
,
7819 if (!NT_STATUS_IS_OK(status
)) {
7820 close_file(req
, fsp
, NORMAL_CLOSE
);
7823 return close_file(req
, fsp
, NORMAL_CLOSE
);
7826 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7827 struct smb_request
*req
,
7828 TALLOC_CTX
*mem_ctx
,
7829 uint16_t info_level
,
7831 struct smb_filename
*smb_fname
,
7832 char **ppdata
, int total_data
,
7835 char *pdata
= *ppdata
;
7836 NTSTATUS status
= NT_STATUS_OK
;
7837 int data_return_size
= 0;
7841 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7842 return NT_STATUS_INVALID_LEVEL
;
7845 if (!CAN_WRITE(conn
)) {
7846 /* Allow POSIX opens. The open path will deny
7847 * any non-readonly opens. */
7848 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7849 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7853 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7854 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7856 info_level
, total_data
));
7858 switch (info_level
) {
7860 case SMB_INFO_STANDARD
:
7862 status
= smb_set_info_standard(conn
,
7870 case SMB_INFO_SET_EA
:
7872 status
= smb_info_set_ea(conn
,
7880 case SMB_SET_FILE_BASIC_INFO
:
7881 case SMB_FILE_BASIC_INFORMATION
:
7883 status
= smb_set_file_basic_info(conn
,
7891 case SMB_FILE_ALLOCATION_INFORMATION
:
7892 case SMB_SET_FILE_ALLOCATION_INFO
:
7894 status
= smb_set_file_allocation_info(conn
, req
,
7902 case SMB_FILE_END_OF_FILE_INFORMATION
:
7903 case SMB_SET_FILE_END_OF_FILE_INFO
:
7906 * XP/Win7 both fail after the createfile with
7907 * SMB_SET_FILE_END_OF_FILE_INFO but not
7908 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7909 * The level is known here, so pass it down
7913 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7915 status
= smb_set_file_end_of_file_info(conn
, req
,
7924 case SMB_FILE_DISPOSITION_INFORMATION
:
7925 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7928 /* JRA - We used to just ignore this on a path ?
7929 * Shouldn't this be invalid level on a pathname
7932 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7933 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7936 status
= smb_set_file_disposition_info(conn
,
7944 case SMB_FILE_POSITION_INFORMATION
:
7946 status
= smb_file_position_information(conn
,
7953 case SMB_FILE_FULL_EA_INFORMATION
:
7955 status
= smb_set_file_full_ea_info(conn
,
7962 /* From tridge Samba4 :
7963 * MODE_INFORMATION in setfileinfo (I have no
7964 * idea what "mode information" on a file is - it takes a value of 0,
7965 * 2, 4 or 6. What could it be?).
7968 case SMB_FILE_MODE_INFORMATION
:
7970 status
= smb_file_mode_information(conn
,
7977 * CIFS UNIX extensions.
7980 case SMB_SET_FILE_UNIX_BASIC
:
7982 status
= smb_set_file_unix_basic(conn
, req
,
7990 case SMB_SET_FILE_UNIX_INFO2
:
7992 status
= smb_set_file_unix_info2(conn
, req
,
8000 case SMB_SET_FILE_UNIX_LINK
:
8003 /* We must have a pathname for this. */
8004 return NT_STATUS_INVALID_LEVEL
;
8006 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8007 total_data
, smb_fname
);
8011 case SMB_SET_FILE_UNIX_HLINK
:
8014 /* We must have a pathname for this. */
8015 return NT_STATUS_INVALID_LEVEL
;
8017 status
= smb_set_file_unix_hlink(conn
, req
,
8023 case SMB_FILE_RENAME_INFORMATION
:
8025 status
= smb_file_rename_information(conn
, req
,
8031 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8033 /* SMB2 rename information. */
8034 status
= smb2_file_rename_information(conn
, req
,
8040 case SMB_FILE_LINK_INFORMATION
:
8042 status
= smb_file_link_information(conn
, req
,
8048 #if defined(HAVE_POSIX_ACLS)
8049 case SMB_SET_POSIX_ACL
:
8051 status
= smb_set_posix_acl(conn
,
8060 case SMB_SET_POSIX_LOCK
:
8063 return NT_STATUS_INVALID_LEVEL
;
8065 status
= smb_set_posix_lock(conn
, req
,
8066 pdata
, total_data
, fsp
);
8070 case SMB_POSIX_PATH_OPEN
:
8073 /* We must have a pathname for this. */
8074 return NT_STATUS_INVALID_LEVEL
;
8077 status
= smb_posix_open(conn
, req
,
8085 case SMB_POSIX_PATH_UNLINK
:
8088 /* We must have a pathname for this. */
8089 return NT_STATUS_INVALID_LEVEL
;
8092 status
= smb_posix_unlink(conn
, req
,
8100 return NT_STATUS_INVALID_LEVEL
;
8103 if (!NT_STATUS_IS_OK(status
)) {
8107 *ret_data_size
= data_return_size
;
8108 return NT_STATUS_OK
;
8111 /****************************************************************************
8112 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8113 ****************************************************************************/
8115 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8116 struct smb_request
*req
,
8117 unsigned int tran_call
,
8118 char **pparams
, int total_params
,
8119 char **ppdata
, int total_data
,
8120 unsigned int max_data_bytes
)
8122 char *params
= *pparams
;
8123 char *pdata
= *ppdata
;
8125 struct smb_filename
*smb_fname
= NULL
;
8126 files_struct
*fsp
= NULL
;
8127 NTSTATUS status
= NT_STATUS_OK
;
8128 int data_return_size
= 0;
8131 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8135 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8136 if (total_params
< 4) {
8137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8141 fsp
= file_fsp(req
, SVAL(params
,0));
8142 /* Basic check for non-null fsp. */
8143 if (!check_fsp_open(conn
, req
, fsp
)) {
8146 info_level
= SVAL(params
,2);
8148 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8149 if (smb_fname
== NULL
) {
8150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8154 if(fsp
->fh
->fd
== -1) {
8156 * This is actually a SETFILEINFO on a directory
8157 * handle (returned from an NT SMB). NT5.0 seems
8158 * to do this call. JRA.
8160 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8161 /* Always do lstat for UNIX calls. */
8162 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8163 DEBUG(3,("call_trans2setfilepathinfo: "
8164 "SMB_VFS_LSTAT of %s failed "
8166 smb_fname_str_dbg(smb_fname
),
8168 reply_nterror(req
, map_nt_error_from_unix(errno
));
8172 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8173 DEBUG(3,("call_trans2setfilepathinfo: "
8174 "fileinfo of %s failed (%s)\n",
8175 smb_fname_str_dbg(smb_fname
),
8177 reply_nterror(req
, map_nt_error_from_unix(errno
));
8181 } else if (fsp
->print_file
) {
8183 * Doing a DELETE_ON_CLOSE should cancel a print job.
8185 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8186 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8188 DEBUG(3,("call_trans2setfilepathinfo: "
8189 "Cancelling print job (%s)\n",
8193 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8199 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8204 * Original code - this is an open file.
8206 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8207 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8208 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8210 reply_nterror(req
, map_nt_error_from_unix(errno
));
8216 uint32_t ucf_flags
= 0;
8219 if (total_params
< 7) {
8220 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8224 info_level
= SVAL(params
,0);
8225 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8226 total_params
- 6, STR_TERMINATE
,
8228 if (!NT_STATUS_IS_OK(status
)) {
8229 reply_nterror(req
, status
);
8233 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8234 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8235 info_level
== SMB_FILE_RENAME_INFORMATION
||
8236 info_level
== SMB_POSIX_PATH_UNLINK
) {
8237 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8240 status
= filename_convert(req
, conn
,
8241 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8246 if (!NT_STATUS_IS_OK(status
)) {
8247 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8248 reply_botherror(req
,
8249 NT_STATUS_PATH_NOT_COVERED
,
8250 ERRSRV
, ERRbadpath
);
8253 reply_nterror(req
, status
);
8257 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8259 * For CIFS UNIX extensions the target name may not exist.
8262 /* Always do lstat for UNIX calls. */
8263 SMB_VFS_LSTAT(conn
, smb_fname
);
8265 } else if (!VALID_STAT(smb_fname
->st
) &&
8266 SMB_VFS_STAT(conn
, smb_fname
)) {
8267 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8269 smb_fname_str_dbg(smb_fname
),
8271 reply_nterror(req
, map_nt_error_from_unix(errno
));
8276 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8277 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8279 info_level
,total_data
));
8281 /* Realloc the parameter size */
8282 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8283 if (*pparams
== NULL
) {
8284 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8291 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8297 if (!NT_STATUS_IS_OK(status
)) {
8298 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8299 /* We have re-scheduled this call. */
8302 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8303 /* We have re-scheduled this call. */
8306 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8307 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8308 ERRSRV
, ERRbadpath
);
8311 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8312 reply_openerror(req
, status
);
8317 * Invalid EA name needs to return 2 param bytes,
8318 * not a zero-length error packet.
8320 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8321 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8324 reply_nterror(req
, status
);
8329 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8335 /****************************************************************************
8336 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8337 ****************************************************************************/
8339 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8340 char **pparams
, int total_params
,
8341 char **ppdata
, int total_data
,
8342 unsigned int max_data_bytes
)
8344 struct smb_filename
*smb_dname
= NULL
;
8345 char *params
= *pparams
;
8346 char *pdata
= *ppdata
;
8347 char *directory
= NULL
;
8348 NTSTATUS status
= NT_STATUS_OK
;
8349 struct ea_list
*ea_list
= NULL
;
8350 TALLOC_CTX
*ctx
= talloc_tos();
8352 if (!CAN_WRITE(conn
)) {
8353 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8357 if (total_params
< 5) {
8358 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8362 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8363 total_params
- 4, STR_TERMINATE
,
8365 if (!NT_STATUS_IS_OK(status
)) {
8366 reply_nterror(req
, status
);
8370 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8372 status
= filename_convert(ctx
,
8374 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8380 if (!NT_STATUS_IS_OK(status
)) {
8381 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8382 reply_botherror(req
,
8383 NT_STATUS_PATH_NOT_COVERED
,
8384 ERRSRV
, ERRbadpath
);
8387 reply_nterror(req
, status
);
8392 * OS/2 workplace shell seems to send SET_EA requests of "null"
8393 * length (4 bytes containing IVAL 4).
8394 * They seem to have no effect. Bug #3212. JRA.
8397 if (total_data
&& (total_data
!= 4)) {
8398 /* Any data in this call is an EA list. */
8399 if (total_data
< 10) {
8400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8404 if (IVAL(pdata
,0) > total_data
) {
8405 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8406 IVAL(pdata
,0), (unsigned int)total_data
));
8407 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8411 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8414 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8418 if (!lp_ea_support(SNUM(conn
))) {
8419 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8423 /* If total_data == 4 Windows doesn't care what values
8424 * are placed in that field, it just ignores them.
8425 * The System i QNTC IBM SMB client puts bad values here,
8426 * so ignore them. */
8428 status
= create_directory(conn
, req
, smb_dname
);
8430 if (!NT_STATUS_IS_OK(status
)) {
8431 reply_nterror(req
, status
);
8435 /* Try and set any given EA. */
8437 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8438 if (!NT_STATUS_IS_OK(status
)) {
8439 reply_nterror(req
, status
);
8444 /* Realloc the parameter and data sizes */
8445 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8446 if(*pparams
== NULL
) {
8447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8454 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8457 TALLOC_FREE(smb_dname
);
8461 /****************************************************************************
8462 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8463 We don't actually do this - we just send a null response.
8464 ****************************************************************************/
8466 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8467 struct smb_request
*req
,
8468 char **pparams
, int total_params
,
8469 char **ppdata
, int total_data
,
8470 unsigned int max_data_bytes
)
8472 char *params
= *pparams
;
8475 if (total_params
< 6) {
8476 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8480 info_level
= SVAL(params
,4);
8481 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8483 switch (info_level
) {
8488 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8492 /* Realloc the parameter and data sizes */
8493 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8494 if (*pparams
== NULL
) {
8495 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8500 SSVAL(params
,0,fnf_handle
);
8501 SSVAL(params
,2,0); /* No changes */
8502 SSVAL(params
,4,0); /* No EA errors */
8509 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8514 /****************************************************************************
8515 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8516 changes). Currently this does nothing.
8517 ****************************************************************************/
8519 static void call_trans2findnotifynext(connection_struct
*conn
,
8520 struct smb_request
*req
,
8521 char **pparams
, int total_params
,
8522 char **ppdata
, int total_data
,
8523 unsigned int max_data_bytes
)
8525 char *params
= *pparams
;
8527 DEBUG(3,("call_trans2findnotifynext\n"));
8529 /* Realloc the parameter and data sizes */
8530 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8531 if (*pparams
== NULL
) {
8532 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8537 SSVAL(params
,0,0); /* No changes */
8538 SSVAL(params
,2,0); /* No EA errors */
8540 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8545 /****************************************************************************
8546 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8547 ****************************************************************************/
8549 static void call_trans2getdfsreferral(connection_struct
*conn
,
8550 struct smb_request
*req
,
8551 char **pparams
, int total_params
,
8552 char **ppdata
, int total_data
,
8553 unsigned int max_data_bytes
)
8555 char *params
= *pparams
;
8556 char *pathname
= NULL
;
8558 int max_referral_level
;
8559 NTSTATUS status
= NT_STATUS_OK
;
8560 TALLOC_CTX
*ctx
= talloc_tos();
8562 DEBUG(10,("call_trans2getdfsreferral\n"));
8564 if (total_params
< 3) {
8565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8569 max_referral_level
= SVAL(params
,0);
8571 if(!lp_host_msdfs()) {
8572 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8576 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8577 total_params
- 2, STR_TERMINATE
);
8579 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8582 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8583 ppdata
,&status
)) < 0) {
8584 reply_nterror(req
, status
);
8588 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8589 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8590 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8595 #define LMCAT_SPL 0x53
8596 #define LMFUNC_GETJOBID 0x60
8598 /****************************************************************************
8599 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8600 ****************************************************************************/
8602 static void call_trans2ioctl(connection_struct
*conn
,
8603 struct smb_request
*req
,
8604 char **pparams
, int total_params
,
8605 char **ppdata
, int total_data
,
8606 unsigned int max_data_bytes
)
8608 char *pdata
= *ppdata
;
8609 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8611 /* check for an invalid fid before proceeding */
8614 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8618 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8619 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8620 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8621 if (*ppdata
== NULL
) {
8622 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8627 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8628 CAN ACCEPT THIS IN UNICODE. JRA. */
8631 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8633 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8634 lp_netbios_name(), 15,
8635 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8636 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8637 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8638 STR_ASCII
|STR_TERMINATE
); /* Service name */
8639 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8644 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8645 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8648 /****************************************************************************
8649 Reply to a SMBfindclose (stop trans2 directory search).
8650 ****************************************************************************/
8652 void reply_findclose(struct smb_request
*req
)
8655 struct smbd_server_connection
*sconn
= req
->sconn
;
8657 START_PROFILE(SMBfindclose
);
8660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8661 END_PROFILE(SMBfindclose
);
8665 dptr_num
= SVALS(req
->vwv
+0, 0);
8667 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8669 dptr_close(sconn
, &dptr_num
);
8671 reply_outbuf(req
, 0, 0);
8673 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8675 END_PROFILE(SMBfindclose
);
8679 /****************************************************************************
8680 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8681 ****************************************************************************/
8683 void reply_findnclose(struct smb_request
*req
)
8687 START_PROFILE(SMBfindnclose
);
8690 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8691 END_PROFILE(SMBfindnclose
);
8695 dptr_num
= SVAL(req
->vwv
+0, 0);
8697 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8699 /* We never give out valid handles for a
8700 findnotifyfirst - so any dptr_num is ok here.
8703 reply_outbuf(req
, 0, 0);
8705 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8707 END_PROFILE(SMBfindnclose
);
8711 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8712 struct trans_state
*state
)
8714 if (get_Protocol() >= PROTOCOL_NT1
) {
8715 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8716 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8719 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8720 if (state
->call
!= TRANSACT2_QFSINFO
&&
8721 state
->call
!= TRANSACT2_SETFSINFO
) {
8722 DEBUG(0,("handle_trans2: encryption required "
8724 (unsigned int)state
->call
));
8725 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8730 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8732 /* Now we must call the relevant TRANS2 function */
8733 switch(state
->call
) {
8734 case TRANSACT2_OPEN
:
8736 START_PROFILE(Trans2_open
);
8737 call_trans2open(conn
, req
,
8738 &state
->param
, state
->total_param
,
8739 &state
->data
, state
->total_data
,
8740 state
->max_data_return
);
8741 END_PROFILE(Trans2_open
);
8745 case TRANSACT2_FINDFIRST
:
8747 START_PROFILE(Trans2_findfirst
);
8748 call_trans2findfirst(conn
, req
,
8749 &state
->param
, state
->total_param
,
8750 &state
->data
, state
->total_data
,
8751 state
->max_data_return
);
8752 END_PROFILE(Trans2_findfirst
);
8756 case TRANSACT2_FINDNEXT
:
8758 START_PROFILE(Trans2_findnext
);
8759 call_trans2findnext(conn
, req
,
8760 &state
->param
, state
->total_param
,
8761 &state
->data
, state
->total_data
,
8762 state
->max_data_return
);
8763 END_PROFILE(Trans2_findnext
);
8767 case TRANSACT2_QFSINFO
:
8769 START_PROFILE(Trans2_qfsinfo
);
8770 call_trans2qfsinfo(conn
, req
,
8771 &state
->param
, state
->total_param
,
8772 &state
->data
, state
->total_data
,
8773 state
->max_data_return
);
8774 END_PROFILE(Trans2_qfsinfo
);
8778 case TRANSACT2_SETFSINFO
:
8780 START_PROFILE(Trans2_setfsinfo
);
8781 call_trans2setfsinfo(conn
, req
,
8782 &state
->param
, state
->total_param
,
8783 &state
->data
, state
->total_data
,
8784 state
->max_data_return
);
8785 END_PROFILE(Trans2_setfsinfo
);
8789 case TRANSACT2_QPATHINFO
:
8790 case TRANSACT2_QFILEINFO
:
8792 START_PROFILE(Trans2_qpathinfo
);
8793 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8794 &state
->param
, state
->total_param
,
8795 &state
->data
, state
->total_data
,
8796 state
->max_data_return
);
8797 END_PROFILE(Trans2_qpathinfo
);
8801 case TRANSACT2_SETPATHINFO
:
8802 case TRANSACT2_SETFILEINFO
:
8804 START_PROFILE(Trans2_setpathinfo
);
8805 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8806 &state
->param
, state
->total_param
,
8807 &state
->data
, state
->total_data
,
8808 state
->max_data_return
);
8809 END_PROFILE(Trans2_setpathinfo
);
8813 case TRANSACT2_FINDNOTIFYFIRST
:
8815 START_PROFILE(Trans2_findnotifyfirst
);
8816 call_trans2findnotifyfirst(conn
, req
,
8817 &state
->param
, state
->total_param
,
8818 &state
->data
, state
->total_data
,
8819 state
->max_data_return
);
8820 END_PROFILE(Trans2_findnotifyfirst
);
8824 case TRANSACT2_FINDNOTIFYNEXT
:
8826 START_PROFILE(Trans2_findnotifynext
);
8827 call_trans2findnotifynext(conn
, req
,
8828 &state
->param
, state
->total_param
,
8829 &state
->data
, state
->total_data
,
8830 state
->max_data_return
);
8831 END_PROFILE(Trans2_findnotifynext
);
8835 case TRANSACT2_MKDIR
:
8837 START_PROFILE(Trans2_mkdir
);
8838 call_trans2mkdir(conn
, req
,
8839 &state
->param
, state
->total_param
,
8840 &state
->data
, state
->total_data
,
8841 state
->max_data_return
);
8842 END_PROFILE(Trans2_mkdir
);
8846 case TRANSACT2_GET_DFS_REFERRAL
:
8848 START_PROFILE(Trans2_get_dfs_referral
);
8849 call_trans2getdfsreferral(conn
, req
,
8850 &state
->param
, state
->total_param
,
8851 &state
->data
, state
->total_data
,
8852 state
->max_data_return
);
8853 END_PROFILE(Trans2_get_dfs_referral
);
8857 case TRANSACT2_IOCTL
:
8859 START_PROFILE(Trans2_ioctl
);
8860 call_trans2ioctl(conn
, req
,
8861 &state
->param
, state
->total_param
,
8862 &state
->data
, state
->total_data
,
8863 state
->max_data_return
);
8864 END_PROFILE(Trans2_ioctl
);
8869 /* Error in request */
8870 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8871 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8875 /****************************************************************************
8876 Reply to a SMBtrans2.
8877 ****************************************************************************/
8879 void reply_trans2(struct smb_request
*req
)
8881 connection_struct
*conn
= req
->conn
;
8886 unsigned int tran_call
;
8887 struct trans_state
*state
;
8890 START_PROFILE(SMBtrans2
);
8892 if (req
->wct
< 14) {
8893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8894 END_PROFILE(SMBtrans2
);
8898 dsoff
= SVAL(req
->vwv
+12, 0);
8899 dscnt
= SVAL(req
->vwv
+11, 0);
8900 psoff
= SVAL(req
->vwv
+10, 0);
8901 pscnt
= SVAL(req
->vwv
+9, 0);
8902 tran_call
= SVAL(req
->vwv
+14, 0);
8904 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8905 if (!NT_STATUS_IS_OK(result
)) {
8906 DEBUG(2, ("Got invalid trans2 request: %s\n",
8907 nt_errstr(result
)));
8908 reply_nterror(req
, result
);
8909 END_PROFILE(SMBtrans2
);
8914 switch (tran_call
) {
8915 /* List the allowed trans2 calls on IPC$ */
8916 case TRANSACT2_OPEN
:
8917 case TRANSACT2_GET_DFS_REFERRAL
:
8918 case TRANSACT2_QFILEINFO
:
8919 case TRANSACT2_QFSINFO
:
8920 case TRANSACT2_SETFSINFO
:
8923 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8924 END_PROFILE(SMBtrans2
);
8929 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8930 DEBUG(0, ("talloc failed\n"));
8931 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8932 END_PROFILE(SMBtrans2
);
8936 state
->cmd
= SMBtrans2
;
8938 state
->mid
= req
->mid
;
8939 state
->vuid
= req
->vuid
;
8940 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8941 state
->setup
= NULL
;
8942 state
->total_param
= SVAL(req
->vwv
+0, 0);
8943 state
->param
= NULL
;
8944 state
->total_data
= SVAL(req
->vwv
+1, 0);
8946 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8947 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8948 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8949 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8950 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8952 state
->call
= tran_call
;
8954 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8955 is so as a sanity check */
8956 if (state
->setup_count
!= 1) {
8958 * Need to have rc=0 for ioctl to get job id for OS/2.
8959 * Network printing will fail if function is not successful.
8960 * Similar function in reply.c will be used if protocol
8961 * is LANMAN1.0 instead of LM1.2X002.
8962 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8963 * outbuf doesn't have to be set(only job id is used).
8965 if ( (state
->setup_count
== 4)
8966 && (tran_call
== TRANSACT2_IOCTL
)
8967 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8968 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8969 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8971 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8972 DEBUG(2,("Transaction is %d\n",tran_call
));
8974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8975 END_PROFILE(SMBtrans2
);
8980 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8983 if (state
->total_data
) {
8985 if (trans_oob(state
->total_data
, 0, dscnt
)
8986 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8990 /* Can't use talloc here, the core routines do realloc on the
8991 * params and data. */
8992 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8993 if (state
->data
== NULL
) {
8994 DEBUG(0,("reply_trans2: data malloc fail for %u "
8995 "bytes !\n", (unsigned int)state
->total_data
));
8997 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8998 END_PROFILE(SMBtrans2
);
9002 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9005 if (state
->total_param
) {
9007 if (trans_oob(state
->total_param
, 0, pscnt
)
9008 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9012 /* Can't use talloc here, the core routines do realloc on the
9013 * params and data. */
9014 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9015 if (state
->param
== NULL
) {
9016 DEBUG(0,("reply_trans: param malloc fail for %u "
9017 "bytes !\n", (unsigned int)state
->total_param
));
9018 SAFE_FREE(state
->data
);
9020 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9021 END_PROFILE(SMBtrans2
);
9025 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9028 state
->received_data
= dscnt
;
9029 state
->received_param
= pscnt
;
9031 if ((state
->received_param
== state
->total_param
) &&
9032 (state
->received_data
== state
->total_data
)) {
9034 handle_trans2(conn
, req
, state
);
9036 SAFE_FREE(state
->data
);
9037 SAFE_FREE(state
->param
);
9039 END_PROFILE(SMBtrans2
);
9043 DLIST_ADD(conn
->pending_trans
, state
);
9045 /* We need to send an interim response then receive the rest
9046 of the parameter/data bytes */
9047 reply_outbuf(req
, 0, 0);
9048 show_msg((char *)req
->outbuf
);
9049 END_PROFILE(SMBtrans2
);
9054 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9055 SAFE_FREE(state
->data
);
9056 SAFE_FREE(state
->param
);
9058 END_PROFILE(SMBtrans2
);
9059 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9063 /****************************************************************************
9064 Reply to a SMBtranss2
9065 ****************************************************************************/
9067 void reply_transs2(struct smb_request
*req
)
9069 connection_struct
*conn
= req
->conn
;
9070 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9071 struct trans_state
*state
;
9073 START_PROFILE(SMBtranss2
);
9075 show_msg((const char *)req
->inbuf
);
9077 /* Windows clients expect all replies to
9078 a transact secondary (SMBtranss2 0x33)
9079 to have a command code of transact
9080 (SMBtrans2 0x32). See bug #8989
9081 and also [MS-CIFS] section 2.2.4.47.2
9084 req
->cmd
= SMBtrans2
;
9087 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9088 END_PROFILE(SMBtranss2
);
9092 for (state
= conn
->pending_trans
; state
!= NULL
;
9093 state
= state
->next
) {
9094 if (state
->mid
== req
->mid
) {
9099 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9100 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9101 END_PROFILE(SMBtranss2
);
9105 /* Revise state->total_param and state->total_data in case they have
9106 changed downwards */
9108 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9109 state
->total_param
= SVAL(req
->vwv
+0, 0);
9110 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9111 state
->total_data
= SVAL(req
->vwv
+1, 0);
9113 pcnt
= SVAL(req
->vwv
+2, 0);
9114 poff
= SVAL(req
->vwv
+3, 0);
9115 pdisp
= SVAL(req
->vwv
+4, 0);
9117 dcnt
= SVAL(req
->vwv
+5, 0);
9118 doff
= SVAL(req
->vwv
+6, 0);
9119 ddisp
= SVAL(req
->vwv
+7, 0);
9121 state
->received_param
+= pcnt
;
9122 state
->received_data
+= dcnt
;
9124 if ((state
->received_data
> state
->total_data
) ||
9125 (state
->received_param
> state
->total_param
))
9129 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9130 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9133 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9137 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9138 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9141 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9144 if ((state
->received_param
< state
->total_param
) ||
9145 (state
->received_data
< state
->total_data
)) {
9146 END_PROFILE(SMBtranss2
);
9150 handle_trans2(conn
, req
, state
);
9152 DLIST_REMOVE(conn
->pending_trans
, state
);
9153 SAFE_FREE(state
->data
);
9154 SAFE_FREE(state
->param
);
9157 END_PROFILE(SMBtranss2
);
9162 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9163 DLIST_REMOVE(conn
->pending_trans
, state
);
9164 SAFE_FREE(state
->data
);
9165 SAFE_FREE(state
->param
);
9167 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9168 END_PROFILE(SMBtranss2
);