2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct
*conn
,
50 const SMB_STRUCT_STAT
*psbuf
);
52 static char *store_file_unix_basic_info2(connection_struct
*conn
,
55 const SMB_STRUCT_STAT
*psbuf
);
57 /********************************************************************
58 The canonical "check access" based on object handle or path function.
59 ********************************************************************/
61 NTSTATUS
check_access(connection_struct
*conn
,
63 const struct smb_filename
*smb_fname
,
67 if (!(fsp
->access_mask
& access_mask
)) {
68 return NT_STATUS_ACCESS_DENIED
;
71 NTSTATUS status
= smbd_check_access_rights(conn
,
75 if (!NT_STATUS_IS_OK(status
)) {
82 /********************************************************************
83 Roundup a value to the nearest allocation roundup size boundary.
84 Only do this for Windows clients.
85 ********************************************************************/
87 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
89 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
91 /* Only roundup for Windows clients. */
92 enum remote_arch_types ra_type
= get_remote_arch();
93 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
94 val
= SMB_ROUNDUP(val
,rval
);
99 /********************************************************************
100 Create a 64 bit FileIndex. If the file is on the same device as
101 the root of the share, just return the 64-bit inode. If it isn't,
102 mangle as we used to do.
103 ********************************************************************/
105 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
108 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
109 return (uint64_t)psbuf
->st_ex_ino
;
111 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
112 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
116 /****************************************************************************
117 Utility functions for dealing with extended attributes.
118 ****************************************************************************/
120 /****************************************************************************
121 Refuse to allow clients to overwrite our private xattrs.
122 ****************************************************************************/
124 bool samba_private_attr_name(const char *unix_ea_name
)
126 static const char * const prohibited_ea_names
[] = {
127 SAMBA_POSIX_INHERITANCE_EA_NAME
,
128 SAMBA_XATTR_DOS_ATTRIB
,
136 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
137 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
140 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
141 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
147 /****************************************************************************
148 Get one EA value. Fill in a struct ea_struct.
149 ****************************************************************************/
151 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
152 files_struct
*fsp
, const char *fname
,
153 const char *ea_name
, struct ea_struct
*pea
)
155 /* Get the value of this xattr. Max size is 64k. */
156 size_t attr_size
= 256;
162 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
164 return NT_STATUS_NO_MEMORY
;
167 if (fsp
&& fsp
->fh
->fd
!= -1) {
168 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
170 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
173 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
179 return map_nt_error_from_unix(errno
);
182 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
183 dump_data(10, (uint8_t *)val
, sizeret
);
186 if (strnequal(ea_name
, "user.", 5)) {
187 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
189 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
191 if (pea
->name
== NULL
) {
193 return NT_STATUS_NO_MEMORY
;
195 pea
->value
.data
= (unsigned char *)val
;
196 pea
->value
.length
= (size_t)sizeret
;
200 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
201 files_struct
*fsp
, const char *fname
,
202 char ***pnames
, size_t *pnum_names
)
204 /* Get a list of all xattrs. Max namesize is 64k. */
205 size_t ea_namelist_size
= 1024;
206 char *ea_namelist
= NULL
;
211 ssize_t sizeret
= -1;
213 if (!lp_ea_support(SNUM(conn
))) {
222 * TALLOC the result early to get the talloc hierarchy right.
225 names
= talloc_array(mem_ctx
, char *, 1);
227 DEBUG(0, ("talloc failed\n"));
228 return NT_STATUS_NO_MEMORY
;
231 while (ea_namelist_size
<= 65536) {
233 ea_namelist
= talloc_realloc(
234 names
, ea_namelist
, char, ea_namelist_size
);
235 if (ea_namelist
== NULL
) {
236 DEBUG(0, ("talloc failed\n"));
238 return NT_STATUS_NO_MEMORY
;
241 if (fsp
&& fsp
->fh
->fd
!= -1) {
242 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
245 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
249 if ((sizeret
== -1) && (errno
== ERANGE
)) {
250 ea_namelist_size
*= 2;
259 return map_nt_error_from_unix(errno
);
262 DEBUG(10, ("%s: ea_namelist size = %u\n",
263 __func__
, (unsigned int)sizeret
));
275 * Ensure the result is 0-terminated
278 if (ea_namelist
[sizeret
-1] != '\0') {
280 return NT_STATUS_INTERNAL_ERROR
;
288 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
292 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
294 DEBUG(0, ("talloc failed\n"));
296 return NT_STATUS_NO_MEMORY
;
302 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
303 names
[num_names
++] = p
;
311 *pnum_names
= num_names
;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
320 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
322 /* Get a list of all xattrs. Max namesize is 64k. */
325 struct ea_list
*ea_list_head
= NULL
;
331 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
334 if (!NT_STATUS_IS_OK(status
)) {
338 if (num_names
== 0) {
343 for (i
=0; i
<num_names
; i
++) {
344 struct ea_list
*listp
;
347 if (strnequal(names
[i
], "system.", 7)
348 || samba_private_attr_name(names
[i
]))
352 * Filter out any underlying POSIX EA names
353 * that a Windows client can't handle.
355 if (!lp_posix_pathnames() &&
356 is_invalid_windows_ea_name(names
[i
])) {
360 listp
= talloc(mem_ctx
, struct ea_list
);
362 return NT_STATUS_NO_MEMORY
;
365 status
= get_ea_value(listp
, conn
, fsp
,
369 if (!NT_STATUS_IS_OK(status
)) {
374 if (listp
->ea
.value
.length
== 0) {
376 * We can never return a zero length EA.
377 * Windows reports the EA's as corrupted.
383 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
386 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
388 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
389 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
390 (unsigned int)listp
->ea
.value
.length
));
392 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
396 /* Add on 4 for total length. */
397 if (*pea_total_len
) {
401 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
402 (unsigned int)*pea_total_len
));
404 *ea_list
= ea_list_head
;
408 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
409 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
414 if (!lp_ea_support(SNUM(conn
))) {
418 if (is_ntfs_stream_smb_fname(smb_fname
)) {
419 return NT_STATUS_INVALID_PARAMETER
;
422 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
425 /****************************************************************************
426 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
428 ****************************************************************************/
430 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
431 connection_struct
*conn
, struct ea_list
*ea_list
)
433 unsigned int ret_data_size
= 4;
436 SMB_ASSERT(total_data_size
>= 4);
438 if (!lp_ea_support(SNUM(conn
))) {
443 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
446 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
447 dos_namelen
= strlen(dos_ea_name
);
448 if (dos_namelen
> 255 || dos_namelen
== 0) {
451 if (ea_list
->ea
.value
.length
> 65535) {
454 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
458 /* We know we have room. */
459 SCVAL(p
,0,ea_list
->ea
.flags
);
460 SCVAL(p
,1,dos_namelen
);
461 SSVAL(p
,2,ea_list
->ea
.value
.length
);
462 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
463 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
465 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
466 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
469 ret_data_size
= PTR_DIFF(p
, pdata
);
470 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
471 SIVAL(pdata
,0,ret_data_size
);
472 return ret_data_size
;
475 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
477 unsigned int total_data_size
,
478 unsigned int *ret_data_size
,
479 connection_struct
*conn
,
480 struct ea_list
*ea_list
)
482 uint8_t *p
= (uint8_t *)pdata
;
483 uint8_t *last_start
= NULL
;
484 bool do_store_data
= (pdata
!= NULL
);
488 if (!lp_ea_support(SNUM(conn
))) {
489 return NT_STATUS_NO_EAS_ON_FILE
;
492 for (; ea_list
; ea_list
= ea_list
->next
) {
498 if (last_start
!= NULL
&& do_store_data
) {
499 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
503 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
504 dos_namelen
= strlen(dos_ea_name
);
505 if (dos_namelen
> 255 || dos_namelen
== 0) {
506 return NT_STATUS_INTERNAL_ERROR
;
508 if (ea_list
->ea
.value
.length
> 65535) {
509 return NT_STATUS_INTERNAL_ERROR
;
512 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
515 pad
= (4 - (this_size
% 4)) % 4;
520 if (this_size
> total_data_size
) {
521 return NT_STATUS_INFO_LENGTH_MISMATCH
;
524 /* We know we have room. */
525 SIVAL(p
, 0x00, 0); /* next offset */
526 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
527 SCVAL(p
, 0x05, dos_namelen
);
528 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
529 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
530 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
532 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
536 total_data_size
-= this_size
;
542 *ret_data_size
= PTR_DIFF(p
, pdata
);
543 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
547 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
549 size_t total_ea_len
= 0;
551 struct ea_list
*ea_list
= NULL
;
553 if (!lp_ea_support(SNUM(conn
))) {
556 mem_ctx
= talloc_stackframe();
558 /* If this is a stream fsp, then we need to instead find the
559 * estimated ea len from the main file, not the stream
560 * (streams cannot have EAs), but the estimate isn't just 0 in
562 if (is_ntfs_stream_smb_fname(smb_fname
)) {
565 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
566 if(conn
->sconn
->using_smb2
) {
568 unsigned int ret_data_size
;
570 * We're going to be using fill_ea_chained_buffer() to
571 * marshall EA's - this size is significantly larger
572 * than the SMB1 buffer. Re-calculate the size without
575 status
= fill_ea_chained_buffer(mem_ctx
,
581 if (!NT_STATUS_IS_OK(status
)) {
584 total_ea_len
= ret_data_size
;
586 TALLOC_FREE(mem_ctx
);
590 /****************************************************************************
591 Ensure the EA name is case insensitive by matching any existing EA name.
592 ****************************************************************************/
594 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
597 TALLOC_CTX
*mem_ctx
= talloc_tos();
598 struct ea_list
*ea_list
;
599 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
600 if (!NT_STATUS_IS_OK(status
)) {
604 for (; ea_list
; ea_list
= ea_list
->next
) {
605 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
606 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
607 &unix_ea_name
[5], ea_list
->ea
.name
));
608 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
614 /****************************************************************************
615 Set or delete an extended attribute.
616 ****************************************************************************/
618 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
619 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
624 if (!lp_ea_support(SNUM(conn
))) {
625 return NT_STATUS_EAS_NOT_SUPPORTED
;
628 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
629 if (!NT_STATUS_IS_OK(status
)) {
633 /* Setting EAs on streams isn't supported. */
634 if (is_ntfs_stream_smb_fname(smb_fname
)) {
635 return NT_STATUS_INVALID_PARAMETER
;
639 * Filter out invalid Windows EA names - before
640 * we set *any* of them.
643 if (ea_list_has_invalid_name(ea_list
)) {
644 return STATUS_INVALID_EA_NAME
;
647 fname
= smb_fname
->base_name
;
649 for (;ea_list
; ea_list
= ea_list
->next
) {
651 fstring unix_ea_name
;
653 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
654 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
656 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
658 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
660 if (samba_private_attr_name(unix_ea_name
)) {
661 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
662 return NT_STATUS_ACCESS_DENIED
;
665 if (ea_list
->ea
.value
.length
== 0) {
666 /* Remove the attribute. */
667 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
668 DEBUG(10,("set_ea: deleting ea name %s on "
669 "file %s by file descriptor.\n",
670 unix_ea_name
, fsp_str_dbg(fsp
)));
671 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
673 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
674 unix_ea_name
, fname
));
675 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
678 /* Removing a non existent attribute always succeeds. */
679 if (ret
== -1 && errno
== ENOATTR
) {
680 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
686 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
687 DEBUG(10,("set_ea: setting ea name %s on file "
688 "%s by file descriptor.\n",
689 unix_ea_name
, fsp_str_dbg(fsp
)));
690 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
691 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
693 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
694 unix_ea_name
, fname
));
695 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
696 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
702 if (errno
== ENOTSUP
) {
703 return NT_STATUS_EAS_NOT_SUPPORTED
;
706 return map_nt_error_from_unix(errno
);
712 /****************************************************************************
713 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
718 struct ea_list
*ea_list_head
= NULL
;
719 size_t converted_size
, offset
= 0;
721 while (offset
+ 2 < data_size
) {
722 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
723 unsigned int namelen
= CVAL(pdata
,offset
);
725 offset
++; /* Go past the namelen byte. */
727 /* integer wrap paranioa. */
728 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
729 (offset
> data_size
) || (namelen
> data_size
) ||
730 (offset
+ namelen
>= data_size
)) {
733 /* Ensure the name is null terminated. */
734 if (pdata
[offset
+ namelen
] != '\0') {
737 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
739 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
740 "failed: %s", strerror(errno
)));
746 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
747 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
748 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
760 struct ea_list
*ea_list_head
= NULL
;
762 size_t bytes_used
= 0;
764 while (offset
< data_size
) {
765 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
771 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
772 offset
+= bytes_used
;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list
*ealist
)
785 struct ea_list
*listp
;
788 for (listp
= ealist
; listp
; listp
= listp
->next
) {
789 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
790 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
792 /* Add on 4 for total length. */
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
808 struct ea_list
*nlistp
, *flistp
;
810 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
811 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
812 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
818 /* Copy the data from this entry. */
819 nlistp
->ea
.flags
= flistp
->ea
.flags
;
820 nlistp
->ea
.value
= flistp
->ea
.value
;
823 nlistp
->ea
.flags
= 0;
824 ZERO_STRUCT(nlistp
->ea
.value
);
828 *total_ea_len
= ea_list_size(name_list
);
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct
*conn
,
840 struct smb_request
*req
,
848 /* As we are using a protocol > LANMAN1 then the max_send
849 variable must have been set in the sessetupX call.
850 This takes precedence over the max_xmit field in the
851 global struct. These different max_xmit variables should
852 be merged as this is now too confusing */
854 int data_to_send
= datasize
;
855 int params_to_send
= paramsize
;
857 const char *pp
= params
;
858 const char *pd
= pdata
;
859 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
860 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
861 int data_alignment_offset
= 0;
862 bool overflow
= False
;
863 struct smbXsrv_connection
*xconn
= req
->xconn
;
864 int max_send
= xconn
->smb1
.sessions
.max_send
;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
871 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes
, datasize
));
874 datasize
= data_to_send
= max_data_bytes
;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send
== 0 && data_to_send
== 0) {
881 reply_outbuf(req
, 10, 0);
882 if (NT_STATUS_V(status
)) {
885 ntstatus_to_dos(status
, &eclass
, &ecode
);
886 error_packet_set((char *)req
->outbuf
,
887 eclass
, ecode
, status
,
890 show_msg((char *)req
->outbuf
);
891 if (!srv_send_smb(xconn
,
894 IS_CONN_ENCRYPTED(conn
),
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req
->outbuf
);
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
907 data_alignment_offset
= 4 - (params_to_send
% 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space
= max_send
- (smb_size
916 + data_alignment_offset
);
918 if (useable_space
< 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space
));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send
|| data_to_send
) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime
= params_to_send
+ data_to_send
;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
939 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
940 + data_alignment_offset
);
942 /* Set total params and data to be sent */
943 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
944 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime
= MIN(params_to_send
,useable_space
);
951 data_sent_thistime
= useable_space
- params_sent_thistime
;
952 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
954 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req
->outbuf
,smb_proff
,
962 ((smb_buf(req
->outbuf
)+alignment_offset
)
963 - smb_base(req
->outbuf
)));
965 if(params_sent_thistime
== 0)
966 SSVAL(req
->outbuf
,smb_prdisp
,0);
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
971 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
972 if(data_sent_thistime
== 0) {
973 SSVAL(req
->outbuf
,smb_droff
,0);
974 SSVAL(req
->outbuf
,smb_drdisp
, 0);
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req
->outbuf
, smb_droff
,
979 ((smb_buf(req
->outbuf
)+alignment_offset
)
980 - smb_base(req
->outbuf
))
981 + params_sent_thistime
+ data_alignment_offset
);
982 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
985 /* Initialize the padding for alignment */
987 if (alignment_offset
!= 0) {
988 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime
) {
994 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
995 params_sent_thistime
);
998 /* Copy in the data bytes */
999 if(data_sent_thistime
) {
1000 if (data_alignment_offset
!= 0) {
1001 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1002 params_sent_thistime
), 0,
1003 data_alignment_offset
);
1005 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1006 +params_sent_thistime
+data_alignment_offset
,
1007 pd
,data_sent_thistime
);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime
, data_sent_thistime
, useable_space
));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send
, data_to_send
, paramsize
, datasize
));
1016 error_packet_set((char *)req
->outbuf
,
1017 ERRDOS
,ERRbufferoverflow
,
1018 STATUS_BUFFER_OVERFLOW
,
1020 } else if (NT_STATUS_V(status
)) {
1023 ntstatus_to_dos(status
, &eclass
, &ecode
);
1024 error_packet_set((char *)req
->outbuf
,
1025 eclass
, ecode
, status
,
1029 /* Send the packet */
1030 show_msg((char *)req
->outbuf
);
1031 if (!srv_send_smb(xconn
,
1032 (char *)req
->outbuf
,
1033 true, req
->seqnum
+1,
1034 IS_CONN_ENCRYPTED(conn
),
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req
->outbuf
);
1040 pp
+= params_sent_thistime
;
1041 pd
+= data_sent_thistime
;
1043 params_to_send
-= params_sent_thistime
;
1044 data_to_send
-= data_sent_thistime
;
1047 if(params_to_send
< 0 || data_to_send
< 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send
, data_to_send
));
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct
*conn
,
1062 struct smb_request
*req
,
1063 char **pparams
, int total_params
,
1064 char **ppdata
, int total_data
,
1065 unsigned int max_data_bytes
)
1067 struct smb_filename
*smb_fname
= NULL
;
1068 char *params
= *pparams
;
1069 char *pdata
= *ppdata
;
1072 bool oplock_request
;
1074 bool return_additional_info
;
1083 int fattr
=0,mtime
=0;
1084 SMB_INO_T inode
= 0;
1087 struct ea_list
*ea_list
= NULL
;
1090 uint32_t access_mask
;
1091 uint32_t share_mode
;
1092 uint32_t create_disposition
;
1093 uint32_t create_options
= 0;
1094 uint32_t private_flags
= 0;
1095 TALLOC_CTX
*ctx
= talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params
< 29) {
1102 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1106 flags
= SVAL(params
, 0);
1107 deny_mode
= SVAL(params
, 2);
1108 open_attr
= SVAL(params
,6);
1109 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1110 if (oplock_request
) {
1111 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1115 return_additional_info
= BITSETW(params
,0);
1116 open_sattr
= SVAL(params
, 4);
1117 open_time
= make_unix_date3(params
+8);
1119 open_ofun
= SVAL(params
,12);
1120 open_size
= IVAL(params
,14);
1121 pname
= ¶ms
[28];
1124 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1128 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1129 total_params
- 28, STR_TERMINATE
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 reply_nterror(req
, status
);
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1138 (unsigned int)open_ofun
, open_size
));
1140 status
= filename_convert(ctx
,
1142 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1147 if (!NT_STATUS_IS_OK(status
)) {
1148 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1149 reply_botherror(req
,
1150 NT_STATUS_PATH_NOT_COVERED
,
1151 ERRSRV
, ERRbadpath
);
1154 reply_nterror(req
, status
);
1158 if (open_ofun
== 0) {
1159 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1163 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1165 &access_mask
, &share_mode
,
1166 &create_disposition
,
1169 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1173 /* Any data in this call is an EA list. */
1174 if (total_data
&& (total_data
!= 4)) {
1175 if (total_data
< 10) {
1176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1180 if (IVAL(pdata
,0) > total_data
) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata
,0), (unsigned int)total_data
));
1183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1187 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1194 if (!lp_ea_support(SNUM(conn
))) {
1195 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1199 if (ea_list_has_invalid_name(ea_list
)) {
1201 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1202 if(*pparams
== NULL
) {
1203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1207 memset(params
, '\0', param_len
);
1208 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1209 params
, param_len
, NULL
, 0, max_data_bytes
);
1214 status
= SMB_VFS_CREATE_FILE(
1217 0, /* root_dir_fid */
1218 smb_fname
, /* fname */
1219 access_mask
, /* access_mask */
1220 share_mode
, /* share_access */
1221 create_disposition
, /* create_disposition*/
1222 create_options
, /* create_options */
1223 open_attr
, /* file_attributes */
1224 oplock_request
, /* oplock_request */
1226 open_size
, /* allocation_size */
1229 ea_list
, /* ea_list */
1231 &smb_action
, /* psbuf */
1232 NULL
, NULL
); /* create context */
1234 if (!NT_STATUS_IS_OK(status
)) {
1235 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1236 /* We have re-scheduled this call. */
1239 reply_openerror(req
, status
);
1243 size
= get_file_size_stat(&smb_fname
->st
);
1244 fattr
= dos_mode(conn
, smb_fname
);
1245 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1246 inode
= smb_fname
->st
.st_ex_ino
;
1247 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1248 close_file(req
, fsp
, ERROR_CLOSE
);
1249 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1253 /* Realloc the size of parameters and data we will return */
1254 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1255 if(*pparams
== NULL
) {
1256 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1261 SSVAL(params
,0,fsp
->fnum
);
1262 SSVAL(params
,2,fattr
);
1263 srv_put_dos_date2(params
,4, mtime
);
1264 SIVAL(params
,8, (uint32_t)size
);
1265 SSVAL(params
,12,deny_mode
);
1266 SSVAL(params
,14,0); /* open_type - file or directory. */
1267 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1269 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1270 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1273 SSVAL(params
,18,smb_action
);
1276 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1278 SIVAL(params
,20,inode
);
1279 SSVAL(params
,24,0); /* Padding. */
1281 uint32_t ea_size
= estimate_ea_size(conn
, fsp
,
1283 SIVAL(params
, 26, ea_size
);
1285 SIVAL(params
, 26, 0);
1288 /* Send the required number of replies */
1289 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1291 TALLOC_FREE(smb_fname
);
1294 /*********************************************************
1295 Routine to check if a given string matches exactly.
1296 as a special case a mask of "." does NOT match. That
1297 is required for correct wildcard semantics
1298 Case can be significant or not.
1299 **********************************************************/
1301 static bool exact_match(bool has_wild
,
1302 bool case_sensitive
,
1306 if (mask
[0] == '.' && mask
[1] == 0) {
1314 if (case_sensitive
) {
1315 return strcmp(str
,mask
)==0;
1317 return strcasecmp_m(str
,mask
) == 0;
1321 /****************************************************************************
1322 Return the filetype for UNIX extensions.
1323 ****************************************************************************/
1325 static uint32_t unix_filetype(mode_t mode
)
1328 return UNIX_TYPE_FILE
;
1329 else if(S_ISDIR(mode
))
1330 return UNIX_TYPE_DIR
;
1332 else if(S_ISLNK(mode
))
1333 return UNIX_TYPE_SYMLINK
;
1336 else if(S_ISCHR(mode
))
1337 return UNIX_TYPE_CHARDEV
;
1340 else if(S_ISBLK(mode
))
1341 return UNIX_TYPE_BLKDEV
;
1344 else if(S_ISFIFO(mode
))
1345 return UNIX_TYPE_FIFO
;
1348 else if(S_ISSOCK(mode
))
1349 return UNIX_TYPE_SOCKET
;
1352 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1353 return UNIX_TYPE_UNKNOWN
;
1356 /****************************************************************************
1357 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1358 ****************************************************************************/
1360 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1362 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1363 const SMB_STRUCT_STAT
*psbuf
,
1365 enum perm_type ptype
,
1370 if (perms
== SMB_MODE_NO_CHANGE
) {
1371 if (!VALID_STAT(*psbuf
)) {
1372 return NT_STATUS_INVALID_PARAMETER
;
1374 *ret_perms
= psbuf
->st_ex_mode
;
1375 return NT_STATUS_OK
;
1379 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1380 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1381 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1382 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1383 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1384 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1385 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1386 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1387 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1389 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1392 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1395 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1398 if (ptype
== PERM_NEW_FILE
) {
1400 * "create mask"/"force create mode" are
1401 * only applied to new files, not existing ones.
1403 ret
&= lp_create_mask(SNUM(conn
));
1404 /* Add in force bits */
1405 ret
|= lp_force_create_mode(SNUM(conn
));
1406 } else if (ptype
== PERM_NEW_DIR
) {
1408 * "directory mask"/"force directory mode" are
1409 * only applied to new directories, not existing ones.
1411 ret
&= lp_directory_mask(SNUM(conn
));
1412 /* Add in force bits */
1413 ret
|= lp_force_directory_mode(SNUM(conn
));
1417 return NT_STATUS_OK
;
1420 /****************************************************************************
1421 Needed to show the msdfs symlinks as directories. Modifies psbuf
1422 to be a directory if it's a msdfs link.
1423 ****************************************************************************/
1425 static bool check_msdfs_link(connection_struct
*conn
,
1426 const char *pathname
,
1427 SMB_STRUCT_STAT
*psbuf
)
1429 int saved_errno
= errno
;
1430 if(lp_host_msdfs() &&
1431 lp_msdfs_root(SNUM(conn
)) &&
1432 is_msdfs_link(conn
, pathname
, psbuf
)) {
1434 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1437 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1438 errno
= saved_errno
;
1441 errno
= saved_errno
;
1446 /****************************************************************************
1447 Get a level dependent lanman2 dir entry.
1448 ****************************************************************************/
1450 struct smbd_dirptr_lanman2_state
{
1451 connection_struct
*conn
;
1452 uint32_t info_level
;
1453 bool check_mangled_names
;
1455 bool got_exact_match
;
1458 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1464 struct smbd_dirptr_lanman2_state
*state
=
1465 (struct smbd_dirptr_lanman2_state
*)private_data
;
1467 char mangled_name
[13]; /* mangled 8.3 name. */
1471 /* Mangle fname if it's an illegal name. */
1472 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1474 * Slow path - ensure we can push the original name as UCS2. If
1475 * not, then just don't return this name.
1479 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1480 uint8_t *tmp
= talloc_array(talloc_tos(),
1484 status
= srvstr_push(NULL
,
1485 FLAGS2_UNICODE_STRINGS
,
1494 if (!NT_STATUS_IS_OK(status
)) {
1498 ok
= name_to_8_3(dname
, mangled_name
,
1499 true, state
->conn
->params
);
1503 fname
= mangled_name
;
1508 got_match
= exact_match(state
->has_wild
,
1509 state
->conn
->case_sensitive
,
1511 state
->got_exact_match
= got_match
;
1513 got_match
= mask_match(fname
, mask
,
1514 state
->conn
->case_sensitive
);
1517 if(!got_match
&& state
->check_mangled_names
&&
1518 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1520 * It turns out that NT matches wildcards against
1521 * both long *and* short names. This may explain some
1522 * of the wildcard wierdness from old DOS clients
1523 * that some people have been seeing.... JRA.
1525 /* Force the mangling into 8.3. */
1526 ok
= name_to_8_3(fname
, mangled_name
,
1527 false, state
->conn
->params
);
1532 got_match
= exact_match(state
->has_wild
,
1533 state
->conn
->case_sensitive
,
1534 mangled_name
, mask
);
1535 state
->got_exact_match
= got_match
;
1537 got_match
= mask_match(mangled_name
, mask
,
1538 state
->conn
->case_sensitive
);
1546 *_fname
= talloc_strdup(ctx
, fname
);
1547 if (*_fname
== NULL
) {
1554 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1556 struct smb_filename
*smb_fname
,
1559 struct smbd_dirptr_lanman2_state
*state
=
1560 (struct smbd_dirptr_lanman2_state
*)private_data
;
1561 bool ms_dfs_link
= false;
1564 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1565 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1566 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1567 "Couldn't lstat [%s] (%s)\n",
1568 smb_fname_str_dbg(smb_fname
),
1572 } else if (!VALID_STAT(smb_fname
->st
) &&
1573 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1574 /* Needed to show the msdfs symlinks as
1577 ms_dfs_link
= check_msdfs_link(state
->conn
,
1578 smb_fname
->base_name
,
1581 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1582 "Couldn't stat [%s] (%s)\n",
1583 smb_fname_str_dbg(smb_fname
),
1590 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1592 mode
= dos_mode(state
->conn
, smb_fname
);
1599 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1600 connection_struct
*conn
,
1602 uint32_t info_level
,
1603 struct ea_list
*name_list
,
1604 bool check_mangled_names
,
1605 bool requires_resume_key
,
1608 const struct smb_filename
*smb_fname
,
1609 int space_remaining
,
1615 uint64_t *last_entry_off
)
1617 char *p
, *q
, *pdata
= *ppdata
;
1619 uint64_t file_size
= 0;
1620 uint64_t allocation_size
= 0;
1621 uint64_t file_index
= 0;
1623 struct timespec mdate_ts
= {0};
1624 struct timespec adate_ts
= {0};
1625 struct timespec cdate_ts
= {0};
1626 struct timespec create_date_ts
= {0};
1627 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1629 char *last_entry_ptr
;
1634 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1636 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1637 file_size
= get_file_size_stat(&smb_fname
->st
);
1639 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1641 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1642 if (!NT_STATUS_IS_OK(status
)) {
1643 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1648 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1650 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1651 adate_ts
= smb_fname
->st
.st_ex_atime
;
1652 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1653 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1655 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1656 dos_filetime_timespec(&create_date_ts
);
1657 dos_filetime_timespec(&mdate_ts
);
1658 dos_filetime_timespec(&adate_ts
);
1659 dos_filetime_timespec(&cdate_ts
);
1662 create_date
= convert_timespec_to_time_t(create_date_ts
);
1663 mdate
= convert_timespec_to_time_t(mdate_ts
);
1664 adate
= convert_timespec_to_time_t(adate_ts
);
1666 /* align the record */
1667 SMB_ASSERT(align
>= 1);
1669 off
= (int)PTR_DIFF(pdata
, base_data
);
1670 pad
= (off
+ (align
-1)) & ~(align
-1);
1673 if (pad
&& pad
> space_remaining
) {
1674 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1675 "for padding (wanted %u, had %d)\n",
1678 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1682 /* initialize padding to 0 */
1684 memset(pdata
, 0, pad
);
1686 space_remaining
-= pad
;
1688 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1698 switch (info_level
) {
1699 case SMB_FIND_INFO_STANDARD
:
1700 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1701 if(requires_resume_key
) {
1705 srv_put_dos_date2(p
,0,create_date
);
1706 srv_put_dos_date2(p
,4,adate
);
1707 srv_put_dos_date2(p
,8,mdate
);
1708 SIVAL(p
,12,(uint32_t)file_size
);
1709 SIVAL(p
,16,(uint32_t)allocation_size
);
1713 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1714 p
+= ucs2_align(base_data
, p
, 0);
1716 status
= srvstr_push(base_data
, flags2
, p
,
1717 fname
, PTR_DIFF(end_data
, p
),
1718 STR_TERMINATE
, &len
);
1719 if (!NT_STATUS_IS_OK(status
)) {
1722 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1724 SCVAL(nameptr
, -1, len
- 2);
1726 SCVAL(nameptr
, -1, 0);
1730 SCVAL(nameptr
, -1, len
- 1);
1732 SCVAL(nameptr
, -1, 0);
1738 case SMB_FIND_EA_SIZE
:
1739 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1740 if (requires_resume_key
) {
1744 srv_put_dos_date2(p
,0,create_date
);
1745 srv_put_dos_date2(p
,4,adate
);
1746 srv_put_dos_date2(p
,8,mdate
);
1747 SIVAL(p
,12,(uint32_t)file_size
);
1748 SIVAL(p
,16,(uint32_t)allocation_size
);
1751 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1753 SIVAL(p
,22,ea_size
); /* Extended attributes */
1757 status
= srvstr_push(base_data
, flags2
,
1758 p
, fname
, PTR_DIFF(end_data
, p
),
1759 STR_TERMINATE
| STR_NOALIGN
, &len
);
1760 if (!NT_STATUS_IS_OK(status
)) {
1763 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1776 SCVAL(nameptr
,0,len
);
1778 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1781 case SMB_FIND_EA_LIST
:
1783 struct ea_list
*file_list
= NULL
;
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1788 return NT_STATUS_INVALID_PARAMETER
;
1790 if (requires_resume_key
) {
1794 srv_put_dos_date2(p
,0,create_date
);
1795 srv_put_dos_date2(p
,4,adate
);
1796 srv_put_dos_date2(p
,8,mdate
);
1797 SIVAL(p
,12,(uint32_t)file_size
);
1798 SIVAL(p
,16,(uint32_t)allocation_size
);
1800 p
+= 22; /* p now points to the EA area. */
1802 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1804 &ea_len
, &file_list
);
1805 if (!NT_STATUS_IS_OK(status
)) {
1808 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1810 /* We need to determine if this entry will fit in the space available. */
1811 /* Max string size is 255 bytes. */
1812 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1813 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1814 "(wanted %u, had %d)\n",
1815 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1817 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1820 /* Push the ea_data followed by the name. */
1821 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1823 status
= srvstr_push(base_data
, flags2
,
1824 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1825 STR_TERMINATE
| STR_NOALIGN
, &len
);
1826 if (!NT_STATUS_IS_OK(status
)) {
1829 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1842 SCVAL(nameptr
,0,len
);
1844 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1848 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1850 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1852 SIVAL(p
,0,reskey
); p
+= 4;
1853 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1854 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1855 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1856 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1857 SOFF_T(p
,0,file_size
); p
+= 8;
1858 SOFF_T(p
,0,allocation_size
); p
+= 8;
1859 SIVAL(p
,0,mode
); p
+= 4;
1860 q
= p
; p
+= 4; /* q is placeholder for name length. */
1861 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1862 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1864 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1866 SIVAL(p
,0,ea_size
); /* Extended attributes */
1869 /* Clear the short name buffer. This is
1870 * IMPORTANT as not doing so will trigger
1871 * a Win2k client bug. JRA.
1873 if (!was_8_3
&& check_mangled_names
) {
1874 char mangled_name
[13]; /* mangled 8.3 name. */
1875 if (!name_to_8_3(fname
,mangled_name
,True
,
1877 /* Error - mangle failed ! */
1878 memset(mangled_name
,'\0',12);
1880 mangled_name
[12] = 0;
1881 status
= srvstr_push(base_data
, flags2
,
1882 p
+2, mangled_name
, 24,
1883 STR_UPPER
|STR_UNICODE
, &len
);
1884 if (!NT_STATUS_IS_OK(status
)) {
1888 memset(p
+ 2 + len
,'\0',24 - len
);
1895 status
= srvstr_push(base_data
, flags2
, p
,
1896 fname
, PTR_DIFF(end_data
, p
),
1897 STR_TERMINATE_ASCII
, &len
);
1898 if (!NT_STATUS_IS_OK(status
)) {
1904 len
= PTR_DIFF(p
, pdata
);
1905 pad
= (len
+ (align
-1)) & ~(align
-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1913 * set padding to zero
1916 memset(p
, 0, pad
- len
);
1923 case SMB_FIND_FILE_DIRECTORY_INFO
:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1926 SIVAL(p
,0,reskey
); p
+= 4;
1927 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1928 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1929 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1930 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1931 SOFF_T(p
,0,file_size
); p
+= 8;
1932 SOFF_T(p
,0,allocation_size
); p
+= 8;
1933 SIVAL(p
,0,mode
); p
+= 4;
1934 status
= srvstr_push(base_data
, flags2
,
1935 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1936 STR_TERMINATE_ASCII
, &len
);
1937 if (!NT_STATUS_IS_OK(status
)) {
1943 len
= PTR_DIFF(p
, pdata
);
1944 pad
= (len
+ (align
-1)) & ~(align
-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1952 * set padding to zero
1955 memset(p
, 0, pad
- len
);
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1965 SIVAL(p
,0,reskey
); p
+= 4;
1966 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1967 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1968 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1969 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1970 SOFF_T(p
,0,file_size
); p
+= 8;
1971 SOFF_T(p
,0,allocation_size
); p
+= 8;
1972 SIVAL(p
,0,mode
); p
+= 4;
1973 q
= p
; p
+= 4; /* q is placeholder for name length. */
1975 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1977 SIVAL(p
,0,ea_size
); /* Extended attributes */
1980 status
= srvstr_push(base_data
, flags2
, p
,
1981 fname
, PTR_DIFF(end_data
, p
),
1982 STR_TERMINATE_ASCII
, &len
);
1983 if (!NT_STATUS_IS_OK(status
)) {
1989 len
= PTR_DIFF(p
, pdata
);
1990 pad
= (len
+ (align
-1)) & ~(align
-1);
1992 * offset to the next entry, the caller
1993 * will overwrite it for the last entry
1994 * that's why we always include the padding
1998 * set padding to zero
2001 memset(p
, 0, pad
- len
);
2008 case SMB_FIND_FILE_NAMES_INFO
:
2009 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2011 SIVAL(p
,0,reskey
); p
+= 4;
2013 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2014 acl on a dir (tridge) */
2015 status
= srvstr_push(base_data
, flags2
, p
,
2016 fname
, PTR_DIFF(end_data
, p
),
2017 STR_TERMINATE_ASCII
, &len
);
2018 if (!NT_STATUS_IS_OK(status
)) {
2024 len
= PTR_DIFF(p
, pdata
);
2025 pad
= (len
+ (align
-1)) & ~(align
-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2033 * set padding to zero
2036 memset(p
, 0, pad
- len
);
2043 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2044 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2046 SIVAL(p
,0,reskey
); p
+= 4;
2047 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2048 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2049 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2050 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2051 SOFF_T(p
,0,file_size
); p
+= 8;
2052 SOFF_T(p
,0,allocation_size
); p
+= 8;
2053 SIVAL(p
,0,mode
); p
+= 4;
2054 q
= p
; p
+= 4; /* q is placeholder for name length. */
2055 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2056 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
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 status
= srvstr_push(base_data
, flags2
, p
,
2066 fname
, PTR_DIFF(end_data
, p
),
2067 STR_TERMINATE_ASCII
, &len
);
2068 if (!NT_STATUS_IS_OK(status
)) {
2074 len
= PTR_DIFF(p
, pdata
);
2075 pad
= (len
+ (align
-1)) & ~(align
-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2083 * set padding to zero
2086 memset(p
, 0, pad
- len
);
2093 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2095 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2097 SIVAL(p
,0,reskey
); p
+= 4;
2098 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2099 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2100 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2101 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2102 SOFF_T(p
,0,file_size
); p
+= 8;
2103 SOFF_T(p
,0,allocation_size
); p
+= 8;
2104 SIVAL(p
,0,mode
); p
+= 4;
2105 q
= p
; p
+= 4; /* q is placeholder for name length */
2106 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2107 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2108 } else if (readdir_attr_data
&&
2109 readdir_attr_data
->type
== RDATTR_AAPL
) {
2111 * OS X specific SMB2 extension negotiated via
2112 * AAPL create context: return max_access in
2115 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2117 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2119 SIVAL(p
,0,ea_size
); /* Extended attributes */
2123 if (readdir_attr_data
&&
2124 readdir_attr_data
->type
== RDATTR_AAPL
) {
2126 * OS X specific SMB2 extension negotiated via
2127 * AAPL create context: return resource fork
2128 * length and compressed FinderInfo in
2131 * According to documentation short_name_len
2132 * should be 0, but on the wire behaviour
2133 * shows its set to 24 by clients.
2137 /* Resourefork length */
2138 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2140 /* Compressed FinderInfo */
2141 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2142 } else if (!was_8_3
&& check_mangled_names
) {
2143 char mangled_name
[13]; /* mangled 8.3 name. */
2144 if (!name_to_8_3(fname
,mangled_name
,True
,
2146 /* Error - mangle failed ! */
2147 memset(mangled_name
,'\0',12);
2149 mangled_name
[12] = 0;
2150 status
= srvstr_push(base_data
, flags2
,
2151 p
+2, mangled_name
, 24,
2152 STR_UPPER
|STR_UNICODE
, &len
);
2153 if (!NT_STATUS_IS_OK(status
)) {
2158 memset(p
+ 2 + len
,'\0',24 - len
);
2162 /* Clear the short name buffer. This is
2163 * IMPORTANT as not doing so will trigger
2164 * a Win2k client bug. JRA.
2171 if (readdir_attr_data
&&
2172 readdir_attr_data
->type
== RDATTR_AAPL
) {
2174 * OS X specific SMB2 extension negotiated via
2175 * AAPL create context: return UNIX mode in
2178 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2179 SSVAL(p
, 0, aapl_mode
);
2185 SBVAL(p
,0,file_index
); p
+= 8;
2186 status
= srvstr_push(base_data
, flags2
, p
,
2187 fname
, PTR_DIFF(end_data
, p
),
2188 STR_TERMINATE_ASCII
, &len
);
2189 if (!NT_STATUS_IS_OK(status
)) {
2195 len
= PTR_DIFF(p
, pdata
);
2196 pad
= (len
+ (align
-1)) & ~(align
-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2204 * set padding to zero
2207 memset(p
, 0, pad
- len
);
2214 /* CIFS UNIX Extension. */
2216 case SMB_FIND_FILE_UNIX
:
2217 case SMB_FIND_FILE_UNIX_INFO2
:
2219 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2221 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (info_level
== SMB_FIND_FILE_UNIX
) {
2224 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2225 p
= store_file_unix_basic(conn
, p
,
2226 NULL
, &smb_fname
->st
);
2227 status
= srvstr_push(base_data
, flags2
, p
,
2228 fname
, PTR_DIFF(end_data
, p
),
2229 STR_TERMINATE
, &len
);
2230 if (!NT_STATUS_IS_OK(status
)) {
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2235 p
= store_file_unix_basic_info2(conn
, p
,
2236 NULL
, &smb_fname
->st
);
2239 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2240 PTR_DIFF(end_data
, p
), 0, &len
);
2241 if (!NT_STATUS_IS_OK(status
)) {
2244 SIVAL(nameptr
, 0, len
);
2249 len
= PTR_DIFF(p
, pdata
);
2250 pad
= (len
+ (align
-1)) & ~(align
-1);
2252 * offset to the next entry, the caller
2253 * will overwrite it for the last entry
2254 * that's why we always include the padding
2258 * set padding to zero
2261 memset(p
, 0, pad
- len
);
2266 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2271 return NT_STATUS_INVALID_LEVEL
;
2274 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2275 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2276 "(wanted %u, had %d)\n",
2277 (unsigned int)PTR_DIFF(p
,pdata
),
2279 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2282 /* Setup the last entry pointer, as an offset from base_data */
2283 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2284 /* Advance the data pointer to the next slot */
2287 return NT_STATUS_OK
;
2290 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2291 connection_struct
*conn
,
2292 struct dptr_struct
*dirptr
,
2294 const char *path_mask
,
2297 int requires_resume_key
,
2305 int space_remaining
,
2306 bool *got_exact_match
,
2307 int *_last_entry_off
,
2308 struct ea_list
*name_list
)
2311 const char *mask
= NULL
;
2312 long prev_dirpos
= 0;
2315 struct smb_filename
*smb_fname
= NULL
;
2316 struct smbd_dirptr_lanman2_state state
;
2318 uint64_t last_entry_off
= 0;
2323 state
.info_level
= info_level
;
2324 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2325 state
.has_wild
= dptr_has_wild(dirptr
);
2326 state
.got_exact_match
= false;
2328 *got_exact_match
= false;
2330 p
= strrchr_m(path_mask
,'/');
2341 ok
= smbd_dirptr_get_entry(ctx
,
2347 smbd_dirptr_lanman2_match_fn
,
2348 smbd_dirptr_lanman2_mode_fn
,
2355 return NT_STATUS_END_OF_FILE
;
2358 *got_exact_match
= state
.got_exact_match
;
2360 status
= smbd_marshall_dir_entry(ctx
,
2365 state
.check_mangled_names
,
2366 requires_resume_key
,
2378 TALLOC_FREE(smb_fname
);
2379 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2380 dptr_SeekDir(dirptr
, prev_dirpos
);
2383 if (!NT_STATUS_IS_OK(status
)) {
2387 *_last_entry_off
= last_entry_off
;
2388 return NT_STATUS_OK
;
2391 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2392 connection_struct
*conn
,
2393 struct dptr_struct
*dirptr
,
2395 const char *path_mask
,
2398 bool requires_resume_key
,
2404 int space_remaining
,
2405 bool *got_exact_match
,
2406 int *last_entry_off
,
2407 struct ea_list
*name_list
)
2410 const bool do_pad
= true;
2412 if (info_level
>= 1 && info_level
<= 3) {
2413 /* No alignment on earlier info levels. */
2417 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2418 path_mask
, dirtype
, info_level
,
2419 requires_resume_key
, dont_descend
, ask_sharemode
,
2421 ppdata
, base_data
, end_data
,
2424 last_entry_off
, name_list
);
2427 /****************************************************************************
2428 Reply to a TRANS2_FINDFIRST.
2429 ****************************************************************************/
2431 static void call_trans2findfirst(connection_struct
*conn
,
2432 struct smb_request
*req
,
2433 char **pparams
, int total_params
,
2434 char **ppdata
, int total_data
,
2435 unsigned int max_data_bytes
)
2437 /* We must be careful here that we don't return more than the
2438 allowed number of data bytes. If this means returning fewer than
2439 maxentries then so be it. We assume that the redirector has
2440 enough room for the fixed number of parameter bytes it has
2442 struct smb_filename
*smb_dname
= NULL
;
2443 char *params
= *pparams
;
2444 char *pdata
= *ppdata
;
2448 uint16_t findfirst_flags
;
2449 bool close_after_first
;
2451 bool requires_resume_key
;
2453 char *directory
= NULL
;
2456 int last_entry_off
=0;
2460 bool finished
= False
;
2461 bool dont_descend
= False
;
2462 bool out_of_space
= False
;
2463 int space_remaining
;
2464 bool mask_contains_wcard
= False
;
2465 struct ea_list
*ea_list
= NULL
;
2466 NTSTATUS ntstatus
= NT_STATUS_OK
;
2467 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2468 TALLOC_CTX
*ctx
= talloc_tos();
2469 struct dptr_struct
*dirptr
= NULL
;
2470 struct smbd_server_connection
*sconn
= req
->sconn
;
2471 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2472 bool backup_priv
= false;
2474 if (total_params
< 13) {
2475 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2479 dirtype
= SVAL(params
,0);
2480 maxentries
= SVAL(params
,2);
2481 findfirst_flags
= SVAL(params
,4);
2482 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2483 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2484 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2485 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2486 security_token_has_privilege(get_current_nttok(conn
),
2489 info_level
= SVAL(params
,6);
2491 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2492 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2493 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2495 info_level
, max_data_bytes
));
2498 /* W2K3 seems to treat zero as 1. */
2502 switch (info_level
) {
2503 case SMB_FIND_INFO_STANDARD
:
2504 case SMB_FIND_EA_SIZE
:
2505 case SMB_FIND_EA_LIST
:
2506 case SMB_FIND_FILE_DIRECTORY_INFO
:
2507 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2508 case SMB_FIND_FILE_NAMES_INFO
:
2509 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2510 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2511 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2513 case SMB_FIND_FILE_UNIX
:
2514 case SMB_FIND_FILE_UNIX_INFO2
:
2515 /* Always use filesystem for UNIX mtime query. */
2516 ask_sharemode
= false;
2517 if (!lp_unix_extensions()) {
2518 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2521 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2524 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2528 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2529 params
+12, total_params
- 12,
2530 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2531 if (!NT_STATUS_IS_OK(ntstatus
)) {
2532 reply_nterror(req
, ntstatus
);
2538 ntstatus
= filename_convert_with_privilege(ctx
,
2543 &mask_contains_wcard
,
2546 ntstatus
= filename_convert(ctx
, conn
,
2547 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2550 &mask_contains_wcard
,
2554 if (!NT_STATUS_IS_OK(ntstatus
)) {
2555 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2556 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2557 ERRSRV
, ERRbadpath
);
2560 reply_nterror(req
, ntstatus
);
2564 mask
= smb_dname
->original_lcomp
;
2566 directory
= smb_dname
->base_name
;
2568 p
= strrchr_m(directory
,'/');
2570 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2571 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2572 mask
= talloc_strdup(ctx
,"*");
2574 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2577 mask_contains_wcard
= True
;
2583 if (p
== NULL
|| p
== directory
) {
2584 /* Ensure we don't have a directory name of "". */
2585 directory
= talloc_strdup(talloc_tos(), ".");
2587 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2592 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2594 if (info_level
== SMB_FIND_EA_LIST
) {
2597 if (total_data
< 4) {
2598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2602 ea_size
= IVAL(pdata
,0);
2603 if (ea_size
!= total_data
) {
2604 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2605 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2606 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2610 if (!lp_ea_support(SNUM(conn
))) {
2611 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2615 /* Pull out the list of names. */
2616 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2618 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2623 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2624 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2628 *ppdata
= (char *)SMB_REALLOC(
2629 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2630 if(*ppdata
== NULL
) {
2631 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2635 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2637 /* Realloc the params space */
2638 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2639 if (*pparams
== NULL
) {
2640 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2645 /* Save the wildcard match and attribs we are using on this directory -
2646 needed as lanman2 assumes these are being saved between calls */
2648 ntstatus
= dptr_create(conn
,
2656 mask_contains_wcard
,
2660 if (!NT_STATUS_IS_OK(ntstatus
)) {
2661 reply_nterror(req
, ntstatus
);
2666 /* Remember this in case we have
2667 to do a findnext. */
2668 dptr_set_priv(dirptr
);
2671 dptr_num
= dptr_dnum(dirptr
);
2672 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2674 /* Initialize per TRANS2_FIND_FIRST operation data */
2675 dptr_init_search_op(dirptr
);
2677 /* We don't need to check for VOL here as this is returned by
2678 a different TRANS2 call. */
2680 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2681 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2682 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2683 dont_descend
= True
;
2686 space_remaining
= max_data_bytes
;
2687 out_of_space
= False
;
2689 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2690 bool got_exact_match
= False
;
2692 /* this is a heuristic to avoid seeking the dirptr except when
2693 absolutely necessary. It allows for a filename of about 40 chars */
2694 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2695 out_of_space
= True
;
2698 ntstatus
= get_lanman2_dir_entry(ctx
,
2702 mask
,dirtype
,info_level
,
2703 requires_resume_key
,dont_descend
,
2708 &last_entry_off
, ea_list
);
2709 if (NT_STATUS_EQUAL(ntstatus
,
2710 NT_STATUS_ILLEGAL_CHARACTER
)) {
2712 * Bad character conversion on name. Ignore this
2717 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2718 out_of_space
= true;
2720 finished
= !NT_STATUS_IS_OK(ntstatus
);
2724 if (!finished
&& !out_of_space
)
2728 * As an optimisation if we know we aren't looking
2729 * for a wildcard name (ie. the name matches the wildcard exactly)
2730 * then we can finish on any (first) match.
2731 * This speeds up large directory searches. JRA.
2737 /* Ensure space_remaining never goes -ve. */
2738 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2739 space_remaining
= 0;
2740 out_of_space
= true;
2742 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2746 /* Check if we can close the dirptr */
2747 if(close_after_first
|| (finished
&& close_if_end
)) {
2748 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2749 dptr_close(sconn
, &dptr_num
);
2753 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2754 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2755 * the protocol level is less than NT1. Tested with smbclient. JRA.
2756 * This should fix the OS/2 client bug #2335.
2759 if(numentries
== 0) {
2760 dptr_close(sconn
, &dptr_num
);
2761 if (get_Protocol() < PROTOCOL_NT1
) {
2762 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2765 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2766 ERRDOS
, ERRbadfile
);
2771 /* At this point pdata points to numentries directory entries. */
2773 /* Set up the return parameter block */
2774 SSVAL(params
,0,dptr_num
);
2775 SSVAL(params
,2,numentries
);
2776 SSVAL(params
,4,finished
);
2777 SSVAL(params
,6,0); /* Never an EA error */
2778 SSVAL(params
,8,last_entry_off
);
2780 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2783 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2784 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2786 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2790 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2791 smb_fn_name(req
->cmd
),
2792 mask
, directory
, dirtype
, numentries
) );
2795 * Force a name mangle here to ensure that the
2796 * mask as an 8.3 name is top of the mangled cache.
2797 * The reasons for this are subtle. Don't remove
2798 * this code unless you know what you are doing
2799 * (see PR#13758). JRA.
2802 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2803 char mangled_name
[13];
2804 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2812 TALLOC_FREE(smb_dname
);
2816 /****************************************************************************
2817 Reply to a TRANS2_FINDNEXT.
2818 ****************************************************************************/
2820 static void call_trans2findnext(connection_struct
*conn
,
2821 struct smb_request
*req
,
2822 char **pparams
, int total_params
,
2823 char **ppdata
, int total_data
,
2824 unsigned int max_data_bytes
)
2826 /* We must be careful here that we don't return more than the
2827 allowed number of data bytes. If this means returning fewer than
2828 maxentries then so be it. We assume that the redirector has
2829 enough room for the fixed number of parameter bytes it has
2831 char *params
= *pparams
;
2832 char *pdata
= *ppdata
;
2836 uint16_t info_level
;
2837 uint32_t resume_key
;
2838 uint16_t findnext_flags
;
2839 bool close_after_request
;
2841 bool requires_resume_key
;
2843 bool mask_contains_wcard
= False
;
2844 char *resume_name
= NULL
;
2845 const char *mask
= NULL
;
2846 const char *directory
= NULL
;
2850 int i
, last_entry_off
=0;
2851 bool finished
= False
;
2852 bool dont_descend
= False
;
2853 bool out_of_space
= False
;
2854 int space_remaining
;
2855 struct ea_list
*ea_list
= NULL
;
2856 NTSTATUS ntstatus
= NT_STATUS_OK
;
2857 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2858 TALLOC_CTX
*ctx
= talloc_tos();
2859 struct dptr_struct
*dirptr
;
2860 struct smbd_server_connection
*sconn
= req
->sconn
;
2861 bool backup_priv
= false;
2863 if (total_params
< 13) {
2864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2868 dptr_num
= SVAL(params
,0);
2869 maxentries
= SVAL(params
,2);
2870 info_level
= SVAL(params
,4);
2871 resume_key
= IVAL(params
,6);
2872 findnext_flags
= SVAL(params
,10);
2873 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2874 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2875 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2876 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2878 if (!continue_bit
) {
2879 /* We only need resume_name if continue_bit is zero. */
2880 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2882 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2883 &mask_contains_wcard
);
2884 if (!NT_STATUS_IS_OK(ntstatus
)) {
2885 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2886 complain (it thinks we're asking for the directory above the shared
2887 path or an invalid name). Catch this as the resume name is only compared, never used in
2888 a file access. JRA. */
2889 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2890 &resume_name
, params
+12,
2894 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2895 reply_nterror(req
, ntstatus
);
2901 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2902 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2903 resume_key = %d resume name = %s continue=%d level = %d\n",
2904 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2905 requires_resume_key
, resume_key
,
2906 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2909 /* W2K3 seems to treat zero as 1. */
2913 switch (info_level
) {
2914 case SMB_FIND_INFO_STANDARD
:
2915 case SMB_FIND_EA_SIZE
:
2916 case SMB_FIND_EA_LIST
:
2917 case SMB_FIND_FILE_DIRECTORY_INFO
:
2918 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2919 case SMB_FIND_FILE_NAMES_INFO
:
2920 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2921 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2922 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2924 case SMB_FIND_FILE_UNIX
:
2925 case SMB_FIND_FILE_UNIX_INFO2
:
2926 /* Always use filesystem for UNIX mtime query. */
2927 ask_sharemode
= false;
2928 if (!lp_unix_extensions()) {
2929 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2934 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2938 if (info_level
== SMB_FIND_EA_LIST
) {
2941 if (total_data
< 4) {
2942 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2946 ea_size
= IVAL(pdata
,0);
2947 if (ea_size
!= total_data
) {
2948 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2949 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2950 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2954 if (!lp_ea_support(SNUM(conn
))) {
2955 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2959 /* Pull out the list of names. */
2960 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2967 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2968 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2972 *ppdata
= (char *)SMB_REALLOC(
2973 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2974 if(*ppdata
== NULL
) {
2975 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2980 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2982 /* Realloc the params space */
2983 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2984 if(*pparams
== NULL
) {
2985 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2991 /* Check that the dptr is valid */
2992 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2993 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2997 directory
= dptr_path(sconn
, dptr_num
);
2999 /* Get the wildcard mask from the dptr */
3000 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3001 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3002 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3006 /* Get the attr mask from the dptr */
3007 dirtype
= dptr_attr(sconn
, dptr_num
);
3009 backup_priv
= dptr_get_priv(dirptr
);
3011 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3012 "backup_priv = %d\n",
3013 dptr_num
, mask
, dirtype
,
3015 dptr_TellDir(dirptr
),
3018 /* Initialize per TRANS2_FIND_NEXT operation data */
3019 dptr_init_search_op(dirptr
);
3021 /* We don't need to check for VOL here as this is returned by
3022 a different TRANS2 call. */
3024 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3025 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3026 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3027 dont_descend
= True
;
3030 space_remaining
= max_data_bytes
;
3031 out_of_space
= False
;
3038 * Seek to the correct position. We no longer use the resume key but
3039 * depend on the last file name instead.
3042 if(!continue_bit
&& resume_name
&& *resume_name
) {
3045 long current_pos
= 0;
3047 * Remember, name_to_8_3 is called by
3048 * get_lanman2_dir_entry(), so the resume name
3049 * could be mangled. Ensure we check the unmangled name.
3052 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3053 char *new_resume_name
= NULL
;
3054 mangle_lookup_name_from_8_3(ctx
,
3058 if (new_resume_name
) {
3059 resume_name
= new_resume_name
;
3064 * Fix for NT redirector problem triggered by resume key indexes
3065 * changing between directory scans. We now return a resume key of 0
3066 * and instead look for the filename to continue from (also given
3067 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3068 * findfirst/findnext (as is usual) then the directory pointer
3069 * should already be at the correct place.
3072 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3073 } /* end if resume_name && !continue_bit */
3075 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3076 bool got_exact_match
= False
;
3078 /* this is a heuristic to avoid seeking the dirptr except when
3079 absolutely necessary. It allows for a filename of about 40 chars */
3080 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3081 out_of_space
= True
;
3084 ntstatus
= get_lanman2_dir_entry(ctx
,
3088 mask
,dirtype
,info_level
,
3089 requires_resume_key
,dont_descend
,
3094 &last_entry_off
, ea_list
);
3095 if (NT_STATUS_EQUAL(ntstatus
,
3096 NT_STATUS_ILLEGAL_CHARACTER
)) {
3098 * Bad character conversion on name. Ignore this
3103 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3104 out_of_space
= true;
3106 finished
= !NT_STATUS_IS_OK(ntstatus
);
3110 if (!finished
&& !out_of_space
)
3114 * As an optimisation if we know we aren't looking
3115 * for a wildcard name (ie. the name matches the wildcard exactly)
3116 * then we can finish on any (first) match.
3117 * This speeds up large directory searches. JRA.
3123 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3126 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3127 smb_fn_name(req
->cmd
),
3128 mask
, directory
, dirtype
, numentries
) );
3130 /* Check if we can close the dirptr */
3131 if(close_after_request
|| (finished
&& close_if_end
)) {
3132 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3133 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3140 /* Set up the return parameter block */
3141 SSVAL(params
,0,numentries
);
3142 SSVAL(params
,2,finished
);
3143 SSVAL(params
,4,0); /* Never an EA error */
3144 SSVAL(params
,6,last_entry_off
);
3146 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3152 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3154 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3158 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3160 SMB_ASSERT(extended_info
!= NULL
);
3162 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3163 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3164 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3165 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3166 #ifdef SAMBA_VERSION_REVISION
3167 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3169 extended_info
->samba_subversion
= 0;
3170 #ifdef SAMBA_VERSION_RC_RELEASE
3171 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3173 #ifdef SAMBA_VERSION_PRE_RELEASE
3174 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3177 #ifdef SAMBA_VERSION_VENDOR_PATCH
3178 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3180 extended_info
->samba_gitcommitdate
= 0;
3181 #ifdef SAMBA_VERSION_COMMIT_TIME
3182 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3185 memset(extended_info
->samba_version_string
, 0,
3186 sizeof(extended_info
->samba_version_string
));
3188 snprintf (extended_info
->samba_version_string
,
3189 sizeof(extended_info
->samba_version_string
),
3190 "%s", samba_version_string());
3193 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3194 connection_struct
*conn
,
3195 TALLOC_CTX
*mem_ctx
,
3196 uint16_t info_level
,
3198 unsigned int max_data_bytes
,
3199 size_t *fixed_portion
,
3200 struct smb_filename
*fname
,
3204 char *pdata
, *end_data
;
3207 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3208 int snum
= SNUM(conn
);
3209 const char *fstype
= lp_fstype(SNUM(conn
));
3210 const char *filename
= NULL
;
3211 const uint64_t bytes_per_sector
= 512;
3212 uint32_t additional_flags
= 0;
3213 struct smb_filename smb_fname
;
3215 NTSTATUS status
= NT_STATUS_OK
;
3218 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3221 filename
= fname
->base_name
;
3225 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3226 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3227 "info level (0x%x) on IPC$.\n",
3228 (unsigned int)info_level
));
3229 return NT_STATUS_ACCESS_DENIED
;
3233 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3235 ZERO_STRUCT(smb_fname
);
3236 smb_fname
.base_name
= discard_const_p(char, filename
);
3238 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3239 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3240 return map_nt_error_from_unix(errno
);
3245 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3246 return NT_STATUS_INVALID_PARAMETER
;
3249 *ppdata
= (char *)SMB_REALLOC(
3250 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3251 if (*ppdata
== NULL
) {
3252 return NT_STATUS_NO_MEMORY
;
3256 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3257 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3261 switch (info_level
) {
3262 case SMB_INFO_ALLOCATION
:
3264 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3266 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3268 if (df_ret
== (uint64_t)-1) {
3269 return map_nt_error_from_unix(errno
);
3272 block_size
= lp_block_size(snum
);
3273 if (bsize
< block_size
) {
3274 uint64_t factor
= block_size
/bsize
;
3279 if (bsize
> block_size
) {
3280 uint64_t factor
= bsize
/block_size
;
3285 sectors_per_unit
= bsize
/bytes_per_sector
;
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3289 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3291 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3292 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3293 SIVAL(pdata
,l1_cUnit
,dsize
);
3294 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3295 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3299 case SMB_INFO_VOLUME
:
3300 /* Return volume name */
3302 * Add volume serial number - hash of a combination of
3303 * the called hostname and the service name.
3305 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3307 * Win2k3 and previous mess this up by sending a name length
3308 * one byte short. I believe only older clients (OS/2 Win9x) use
3309 * this call so try fixing this by adding a terminating null to
3310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3312 status
= srvstr_push(
3314 pdata
+l2_vol_szVolLabel
, vname
,
3315 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3316 STR_NOALIGN
|STR_TERMINATE
, &len
);
3317 if (!NT_STATUS_IS_OK(status
)) {
3320 SCVAL(pdata
,l2_vol_cch
,len
);
3321 data_len
= l2_vol_szVolLabel
+ len
;
3322 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3323 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3324 (unsigned)len
, vname
));
3327 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3328 case SMB_FS_ATTRIBUTE_INFORMATION
:
3330 additional_flags
= 0;
3331 #if defined(HAVE_SYS_QUOTAS)
3332 additional_flags
|= FILE_VOLUME_QUOTAS
;
3335 if(lp_nt_acl_support(SNUM(conn
))) {
3336 additional_flags
|= FILE_PERSISTENT_ACLS
;
3339 /* Capabilities are filled in at connection time through STATVFS call */
3340 additional_flags
|= conn
->fs_capabilities
;
3341 additional_flags
|= lp_parm_int(conn
->params
->service
,
3342 "share", "fake_fscaps",
3345 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3346 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3347 additional_flags
); /* FS ATTRIBUTES */
3349 SIVAL(pdata
,4,255); /* Max filename component length */
3350 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3351 and will think we can't do long filenames */
3352 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3353 PTR_DIFF(end_data
, pdata
+12),
3355 if (!NT_STATUS_IS_OK(status
)) {
3359 data_len
= 12 + len
;
3360 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3361 /* the client only requested a portion of the
3363 data_len
= max_data_bytes
;
3364 status
= STATUS_BUFFER_OVERFLOW
;
3366 *fixed_portion
= 16;
3369 case SMB_QUERY_FS_LABEL_INFO
:
3370 case SMB_FS_LABEL_INFORMATION
:
3371 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3372 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3373 if (!NT_STATUS_IS_OK(status
)) {
3380 case SMB_QUERY_FS_VOLUME_INFO
:
3381 case SMB_FS_VOLUME_INFORMATION
:
3384 * Add volume serial number - hash of a combination of
3385 * the called hostname and the service name.
3387 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3388 (str_checksum(get_local_machine_name())<<16));
3390 /* Max label len is 32 characters. */
3391 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3392 PTR_DIFF(end_data
, pdata
+18),
3394 if (!NT_STATUS_IS_OK(status
)) {
3397 SIVAL(pdata
,12,len
);
3400 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3401 (int)strlen(vname
),vname
,
3402 lp_servicename(talloc_tos(), snum
)));
3403 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3404 /* the client only requested a portion of the
3406 data_len
= max_data_bytes
;
3407 status
= STATUS_BUFFER_OVERFLOW
;
3409 *fixed_portion
= 24;
3412 case SMB_QUERY_FS_SIZE_INFO
:
3413 case SMB_FS_SIZE_INFORMATION
:
3415 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3417 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3419 if (df_ret
== (uint64_t)-1) {
3420 return map_nt_error_from_unix(errno
);
3422 block_size
= lp_block_size(snum
);
3423 if (bsize
< block_size
) {
3424 uint64_t factor
= block_size
/bsize
;
3429 if (bsize
> block_size
) {
3430 uint64_t factor
= bsize
/block_size
;
3435 sectors_per_unit
= bsize
/bytes_per_sector
;
3436 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3437 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3438 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3439 SBIG_UINT(pdata
,0,dsize
);
3440 SBIG_UINT(pdata
,8,dfree
);
3441 SIVAL(pdata
,16,sectors_per_unit
);
3442 SIVAL(pdata
,20,bytes_per_sector
);
3443 *fixed_portion
= 24;
3447 case SMB_FS_FULL_SIZE_INFORMATION
:
3449 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3451 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3453 if (df_ret
== (uint64_t)-1) {
3454 return map_nt_error_from_unix(errno
);
3456 block_size
= lp_block_size(snum
);
3457 if (bsize
< block_size
) {
3458 uint64_t factor
= block_size
/bsize
;
3463 if (bsize
> block_size
) {
3464 uint64_t factor
= bsize
/block_size
;
3469 sectors_per_unit
= bsize
/bytes_per_sector
;
3470 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3471 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3472 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3473 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3474 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3475 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3476 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3477 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3478 *fixed_portion
= 32;
3482 case SMB_QUERY_FS_DEVICE_INFO
:
3483 case SMB_FS_DEVICE_INFORMATION
:
3485 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3487 if (!CAN_WRITE(conn
)) {
3488 characteristics
|= FILE_READ_ONLY_DEVICE
;
3491 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3492 SIVAL(pdata
,4,characteristics
);
3497 #ifdef HAVE_SYS_QUOTAS
3498 case SMB_FS_QUOTA_INFORMATION
:
3500 * what we have to send --metze:
3502 * Unknown1: 24 NULL bytes
3503 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3504 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3505 * Quota Flags: 2 byte :
3506 * Unknown3: 6 NULL bytes
3510 * details for Quota Flags:
3512 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3513 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3514 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3515 * 0x0001 Enable Quotas: enable quota for this fs
3519 /* we need to fake up a fsp here,
3520 * because its not send in this call
3523 SMB_NTQUOTA_STRUCT quotas
;
3526 ZERO_STRUCT(quotas
);
3529 fsp
.fnum
= FNUM_FIELD_INVALID
;
3532 if (get_current_uid(conn
) != 0) {
3533 DEBUG(0,("get_user_quota: access_denied "
3534 "service [%s] user [%s]\n",
3535 lp_servicename(talloc_tos(), SNUM(conn
)),
3536 conn
->session_info
->unix_info
->unix_name
));
3537 return NT_STATUS_ACCESS_DENIED
;
3540 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3541 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3542 return map_nt_error_from_unix(errno
);
3547 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3548 lp_servicename(talloc_tos(), SNUM(conn
))));
3550 /* Unknown1 24 NULL bytes*/
3551 SBIG_UINT(pdata
,0,(uint64_t)0);
3552 SBIG_UINT(pdata
,8,(uint64_t)0);
3553 SBIG_UINT(pdata
,16,(uint64_t)0);
3555 /* Default Soft Quota 8 bytes */
3556 SBIG_UINT(pdata
,24,quotas
.softlim
);
3558 /* Default Hard Quota 8 bytes */
3559 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3561 /* Quota flag 2 bytes */
3562 SSVAL(pdata
,40,quotas
.qflags
);
3564 /* Unknown3 6 NULL bytes */
3570 #endif /* HAVE_SYS_QUOTAS */
3571 case SMB_FS_OBJECTID_INFORMATION
:
3573 unsigned char objid
[16];
3574 struct smb_extended_info extended_info
;
3575 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3576 samba_extended_info_version (&extended_info
);
3577 SIVAL(pdata
,16,extended_info
.samba_magic
);
3578 SIVAL(pdata
,20,extended_info
.samba_version
);
3579 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3580 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3581 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3586 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3590 * These values match a physical Windows Server 2012
3591 * share backed by NTFS atop spinning rust.
3593 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3594 /* logical_bytes_per_sector */
3595 SIVAL(pdata
, 0, bytes_per_sector
);
3596 /* phys_bytes_per_sector_atomic */
3597 SIVAL(pdata
, 4, bytes_per_sector
);
3598 /* phys_bytes_per_sector_perf */
3599 SIVAL(pdata
, 8, bytes_per_sector
);
3600 /* fs_effective_phys_bytes_per_sector_atomic */
3601 SIVAL(pdata
, 12, bytes_per_sector
);
3603 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3604 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3605 /* byte_off_sector_align */
3606 SIVAL(pdata
, 20, 0);
3607 /* byte_off_partition_align */
3608 SIVAL(pdata
, 24, 0);
3609 *fixed_portion
= 28;
3615 * Query the version and capabilities of the CIFS UNIX extensions
3619 case SMB_QUERY_CIFS_UNIX_INFO
:
3621 bool large_write
= lp_min_receive_file_size() &&
3622 !srv_is_signing_active(xconn
);
3623 bool large_read
= !srv_is_signing_active(xconn
);
3624 int encrypt_caps
= 0;
3626 if (!lp_unix_extensions()) {
3627 return NT_STATUS_INVALID_LEVEL
;
3630 switch (conn
->encrypt_level
) {
3631 case SMB_SIGNING_OFF
:
3634 case SMB_SIGNING_IF_REQUIRED
:
3635 case SMB_SIGNING_DEFAULT
:
3636 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3638 case SMB_SIGNING_REQUIRED
:
3639 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3640 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3641 large_write
= false;
3647 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3648 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3650 /* We have POSIX ACLs, pathname, encryption,
3651 * large read/write, and locking capability. */
3653 SBIG_UINT(pdata
,4,((uint64_t)(
3654 CIFS_UNIX_POSIX_ACLS_CAP
|
3655 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3656 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3657 CIFS_UNIX_EXTATTR_CAP
|
3658 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3660 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3662 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3666 case SMB_QUERY_POSIX_FS_INFO
:
3669 vfs_statvfs_struct svfs
;
3671 if (!lp_unix_extensions()) {
3672 return NT_STATUS_INVALID_LEVEL
;
3675 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3679 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3680 SIVAL(pdata
,4,svfs
.BlockSize
);
3681 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3682 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3683 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3684 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3685 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3686 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3687 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3689 } else if (rc
== EOPNOTSUPP
) {
3690 return NT_STATUS_INVALID_LEVEL
;
3691 #endif /* EOPNOTSUPP */
3693 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3694 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3699 case SMB_QUERY_POSIX_WHOAMI
:
3705 if (!lp_unix_extensions()) {
3706 return NT_STATUS_INVALID_LEVEL
;
3709 if (max_data_bytes
< 40) {
3710 return NT_STATUS_BUFFER_TOO_SMALL
;
3713 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3714 flags
|= SMB_WHOAMI_GUEST
;
3717 /* NOTE: 8 bytes for UID/GID, irrespective of native
3718 * platform size. This matches
3719 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3721 data_len
= 4 /* flags */
3728 + 4 /* pad/reserved */
3729 + (conn
->session_info
->unix_token
->ngroups
* 8)
3731 + (conn
->session_info
->security_token
->num_sids
*
3735 SIVAL(pdata
, 0, flags
);
3736 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3738 (uint64_t)conn
->session_info
->unix_token
->uid
);
3739 SBIG_UINT(pdata
, 16,
3740 (uint64_t)conn
->session_info
->unix_token
->gid
);
3743 if (data_len
>= max_data_bytes
) {
3744 /* Potential overflow, skip the GIDs and SIDs. */
3746 SIVAL(pdata
, 24, 0); /* num_groups */
3747 SIVAL(pdata
, 28, 0); /* num_sids */
3748 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3749 SIVAL(pdata
, 36, 0); /* reserved */
3755 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3756 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3758 /* We walk the SID list twice, but this call is fairly
3759 * infrequent, and I don't expect that it's performance
3760 * sensitive -- jpeach
3762 for (i
= 0, sid_bytes
= 0;
3763 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3764 sid_bytes
+= ndr_size_dom_sid(
3765 &conn
->session_info
->security_token
->sids
[i
],
3769 /* SID list byte count */
3770 SIVAL(pdata
, 32, sid_bytes
);
3772 /* 4 bytes pad/reserved - must be zero */
3773 SIVAL(pdata
, 36, 0);
3777 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3778 SBIG_UINT(pdata
, data_len
,
3779 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3785 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3786 int sid_len
= ndr_size_dom_sid(
3787 &conn
->session_info
->security_token
->sids
[i
],
3790 sid_linearize(pdata
+ data_len
, sid_len
,
3791 &conn
->session_info
->security_token
->sids
[i
]);
3792 data_len
+= sid_len
;
3798 case SMB_MAC_QUERY_FS_INFO
:
3800 * Thursby MAC extension... ONLY on NTFS filesystems
3801 * once we do streams then we don't need this
3803 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3805 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3810 return NT_STATUS_INVALID_LEVEL
;
3813 *ret_data_len
= data_len
;
3817 /****************************************************************************
3818 Reply to a TRANS2_QFSINFO (query filesystem info).
3819 ****************************************************************************/
3821 static void call_trans2qfsinfo(connection_struct
*conn
,
3822 struct smb_request
*req
,
3823 char **pparams
, int total_params
,
3824 char **ppdata
, int total_data
,
3825 unsigned int max_data_bytes
)
3827 char *params
= *pparams
;
3828 uint16_t info_level
;
3830 size_t fixed_portion
;
3833 if (total_params
< 2) {
3834 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3838 info_level
= SVAL(params
,0);
3840 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3841 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3842 DEBUG(0,("call_trans2qfsinfo: encryption required "
3843 "and info level 0x%x sent.\n",
3844 (unsigned int)info_level
));
3845 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3850 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3852 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3859 if (!NT_STATUS_IS_OK(status
)) {
3860 reply_nterror(req
, status
);
3864 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3867 DEBUG( 4, ( "%s info_level = %d\n",
3868 smb_fn_name(req
->cmd
), info_level
) );
3873 /****************************************************************************
3874 Reply to a TRANS2_SETFSINFO (set filesystem info).
3875 ****************************************************************************/
3877 static void call_trans2setfsinfo(connection_struct
*conn
,
3878 struct smb_request
*req
,
3879 char **pparams
, int total_params
,
3880 char **ppdata
, int total_data
,
3881 unsigned int max_data_bytes
)
3883 struct smbXsrv_connection
*xconn
= req
->xconn
;
3884 char *pdata
= *ppdata
;
3885 char *params
= *pparams
;
3886 uint16_t info_level
;
3888 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3889 lp_servicename(talloc_tos(), SNUM(conn
))));
3892 if (total_params
< 4) {
3893 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3895 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3899 info_level
= SVAL(params
,2);
3902 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3903 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3904 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3905 "info level (0x%x) on IPC$.\n",
3906 (unsigned int)info_level
));
3907 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3912 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3913 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3914 DEBUG(0,("call_trans2setfsinfo: encryption required "
3915 "and info level 0x%x sent.\n",
3916 (unsigned int)info_level
));
3917 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3922 switch(info_level
) {
3923 case SMB_SET_CIFS_UNIX_INFO
:
3924 if (!lp_unix_extensions()) {
3925 DEBUG(2,("call_trans2setfsinfo: "
3926 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3927 "unix extensions off\n"));
3929 NT_STATUS_INVALID_LEVEL
);
3933 /* There should be 12 bytes of capabilities set. */
3934 if (total_data
< 12) {
3937 NT_STATUS_INVALID_PARAMETER
);
3940 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3941 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3942 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3943 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3944 /* Just print these values for now. */
3945 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3946 "major = %u, minor = %u cap_low = 0x%x, "
3948 (unsigned int)xconn
->
3949 smb1
.unix_info
.client_major
,
3950 (unsigned int)xconn
->
3951 smb1
.unix_info
.client_minor
,
3952 (unsigned int)xconn
->
3953 smb1
.unix_info
.client_cap_low
,
3954 (unsigned int)xconn
->
3955 smb1
.unix_info
.client_cap_high
));
3957 /* Here is where we must switch to posix pathname processing... */
3958 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3959 lp_set_posix_pathnames();
3960 mangle_change_to_posix();
3963 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3964 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3965 /* Client that knows how to do posix locks,
3966 * but not posix open/mkdir operations. Set a
3967 * default type for read/write checks. */
3969 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3974 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3977 size_t param_len
= 0;
3978 size_t data_len
= total_data
;
3980 if (!lp_unix_extensions()) {
3983 NT_STATUS_INVALID_LEVEL
);
3987 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3990 NT_STATUS_NOT_SUPPORTED
);
3994 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3995 DEBUG( 2,("call_trans2setfsinfo: "
3996 "request transport encryption disabled"
3997 "with 'fork echo handler = yes'\n"));
4000 NT_STATUS_NOT_SUPPORTED
);
4004 DEBUG( 4,("call_trans2setfsinfo: "
4005 "request transport encryption.\n"));
4007 status
= srv_request_encryption_setup(conn
,
4008 (unsigned char **)ppdata
,
4010 (unsigned char **)pparams
,
4013 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4014 !NT_STATUS_IS_OK(status
)) {
4015 reply_nterror(req
, status
);
4019 send_trans2_replies(conn
, req
,
4027 if (NT_STATUS_IS_OK(status
)) {
4028 /* Server-side transport
4029 * encryption is now *on*. */
4030 status
= srv_encryption_start(conn
);
4031 if (!NT_STATUS_IS_OK(status
)) {
4032 char *reason
= talloc_asprintf(talloc_tos(),
4033 "Failure in setting "
4034 "up encrypted transport: %s",
4036 exit_server_cleanly(reason
);
4042 case SMB_FS_QUOTA_INFORMATION
:
4044 files_struct
*fsp
= NULL
;
4045 SMB_NTQUOTA_STRUCT quotas
;
4047 ZERO_STRUCT(quotas
);
4050 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4051 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4052 lp_servicename(talloc_tos(), SNUM(conn
)),
4053 conn
->session_info
->unix_info
->unix_name
));
4054 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4058 /* note: normally there're 48 bytes,
4059 * but we didn't use the last 6 bytes for now
4062 fsp
= file_fsp(req
, SVAL(params
,0));
4064 if (!check_fsp_ntquota_handle(conn
, req
,
4066 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4068 req
, NT_STATUS_INVALID_HANDLE
);
4072 if (total_data
< 42) {
4073 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4077 NT_STATUS_INVALID_PARAMETER
);
4081 /* unknown_1 24 NULL bytes in pdata*/
4083 /* the soft quotas 8 bytes (uint64_t)*/
4084 quotas
.softlim
= BVAL(pdata
,24);
4086 /* the hard quotas 8 bytes (uint64_t)*/
4087 quotas
.hardlim
= BVAL(pdata
,32);
4089 /* quota_flags 2 bytes **/
4090 quotas
.qflags
= SVAL(pdata
,40);
4092 /* unknown_2 6 NULL bytes follow*/
4094 /* now set the quotas */
4095 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4096 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4097 reply_nterror(req
, map_nt_error_from_unix(errno
));
4104 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4106 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4112 * sending this reply works fine,
4113 * but I'm not sure it's the same
4114 * like windows do...
4117 reply_outbuf(req
, 10, 0);
4120 #if defined(HAVE_POSIX_ACLS)
4121 /****************************************************************************
4122 Utility function to count the number of entries in a POSIX acl.
4123 ****************************************************************************/
4125 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4127 unsigned int ace_count
= 0;
4128 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4129 SMB_ACL_ENTRY_T entry
;
4131 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4133 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4134 entry_id
= SMB_ACL_NEXT_ENTRY
;
4141 /****************************************************************************
4142 Utility function to marshall a POSIX acl into wire format.
4143 ****************************************************************************/
4145 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4147 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4148 SMB_ACL_ENTRY_T entry
;
4150 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4151 SMB_ACL_TAG_T tagtype
;
4152 SMB_ACL_PERMSET_T permset
;
4153 unsigned char perms
= 0;
4154 unsigned int own_grp
;
4157 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4158 entry_id
= SMB_ACL_NEXT_ENTRY
;
4161 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4162 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4166 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4167 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4171 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4172 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4173 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4175 SCVAL(pdata
,1,perms
);
4178 case SMB_ACL_USER_OBJ
:
4179 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4180 own_grp
= (unsigned int)pst
->st_ex_uid
;
4181 SIVAL(pdata
,2,own_grp
);
4186 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4188 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4191 own_grp
= (unsigned int)*puid
;
4192 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4193 SIVAL(pdata
,2,own_grp
);
4197 case SMB_ACL_GROUP_OBJ
:
4198 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4199 own_grp
= (unsigned int)pst
->st_ex_gid
;
4200 SIVAL(pdata
,2,own_grp
);
4205 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4207 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4210 own_grp
= (unsigned int)*pgid
;
4211 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4212 SIVAL(pdata
,2,own_grp
);
4217 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4218 SIVAL(pdata
,2,0xFFFFFFFF);
4219 SIVAL(pdata
,6,0xFFFFFFFF);
4222 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4223 SIVAL(pdata
,2,0xFFFFFFFF);
4224 SIVAL(pdata
,6,0xFFFFFFFF);
4227 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4230 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4237 /****************************************************************************
4238 Store the FILE_UNIX_BASIC info.
4239 ****************************************************************************/
4241 static char *store_file_unix_basic(connection_struct
*conn
,
4244 const SMB_STRUCT_STAT
*psbuf
)
4246 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4249 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4250 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4252 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4255 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4258 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4259 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4260 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4263 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4267 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4271 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4274 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4275 devno
= psbuf
->st_ex_rdev
;
4277 devno
= psbuf
->st_ex_dev
;
4280 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4284 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4288 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4291 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4295 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4302 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4303 * the chflags(2) (or equivalent) flags.
4305 * XXX: this really should be behind the VFS interface. To do this, we would
4306 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4307 * Each VFS module could then implement its own mapping as appropriate for the
4308 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4310 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4314 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4318 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4322 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4326 { UF_HIDDEN
, EXT_HIDDEN
},
4329 /* Do not remove. We need to guarantee that this array has at least one
4330 * entry to build on HP-UX.
4336 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4337 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4341 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4342 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4343 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4344 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4349 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4350 const uint32_t smb_fflags
,
4351 const uint32_t smb_fmask
,
4354 uint32_t max_fmask
= 0;
4357 *stat_fflags
= psbuf
->st_ex_flags
;
4359 /* For each flags requested in smb_fmask, check the state of the
4360 * corresponding flag in smb_fflags and set or clear the matching
4364 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4365 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4366 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4367 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4368 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4370 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4375 /* If smb_fmask is asking to set any bits that are not supported by
4376 * our flag mappings, we should fail.
4378 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4386 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4387 * of file flags and birth (create) time.
4389 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4392 const SMB_STRUCT_STAT
*psbuf
)
4394 uint32_t file_flags
= 0;
4395 uint32_t flags_mask
= 0;
4397 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4399 /* Create (birth) time 64 bit */
4400 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4403 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4404 SIVAL(pdata
, 0, file_flags
); /* flags */
4405 SIVAL(pdata
, 4, flags_mask
); /* mask */
4411 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4412 const struct stream_struct
*streams
,
4414 unsigned int max_data_bytes
,
4415 unsigned int *data_size
)
4418 unsigned int ofs
= 0;
4420 if (max_data_bytes
< 32) {
4421 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4424 for (i
= 0; i
< num_streams
; i
++) {
4425 unsigned int next_offset
;
4427 smb_ucs2_t
*namebuf
;
4429 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4430 streams
[i
].name
, &namelen
) ||
4433 return NT_STATUS_INVALID_PARAMETER
;
4437 * name_buf is now null-terminated, we need to marshall as not
4444 * We cannot overflow ...
4446 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4447 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4449 TALLOC_FREE(namebuf
);
4450 return STATUS_BUFFER_OVERFLOW
;
4453 SIVAL(data
, ofs
+4, namelen
);
4454 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4455 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4456 memcpy(data
+ofs
+24, namebuf
, namelen
);
4457 TALLOC_FREE(namebuf
);
4459 next_offset
= ofs
+ 24 + namelen
;
4461 if (i
== num_streams
-1) {
4462 SIVAL(data
, ofs
, 0);
4465 unsigned int align
= ndr_align_size(next_offset
, 8);
4467 if ((next_offset
+ align
) > max_data_bytes
) {
4468 DEBUG(10, ("refusing to overflow align "
4469 "reply at stream %u\n",
4471 TALLOC_FREE(namebuf
);
4472 return STATUS_BUFFER_OVERFLOW
;
4475 memset(data
+next_offset
, 0, align
);
4476 next_offset
+= align
;
4478 SIVAL(data
, ofs
, next_offset
- ofs
);
4485 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4489 return NT_STATUS_OK
;
4492 /****************************************************************************
4493 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4494 ****************************************************************************/
4496 static void call_trans2qpipeinfo(connection_struct
*conn
,
4497 struct smb_request
*req
,
4498 unsigned int tran_call
,
4499 char **pparams
, int total_params
,
4500 char **ppdata
, int total_data
,
4501 unsigned int max_data_bytes
)
4503 char *params
= *pparams
;
4504 char *pdata
= *ppdata
;
4505 unsigned int data_size
= 0;
4506 unsigned int param_size
= 2;
4507 uint16_t info_level
;
4511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4515 if (total_params
< 4) {
4516 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4520 fsp
= file_fsp(req
, SVAL(params
,0));
4521 if (!fsp_is_np(fsp
)) {
4522 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4526 info_level
= SVAL(params
,2);
4528 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4529 if (*pparams
== NULL
) {
4530 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4535 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4539 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4540 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4541 if (*ppdata
== NULL
) {
4542 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4547 switch (info_level
) {
4548 case SMB_FILE_STANDARD_INFORMATION
:
4550 SOFF_T(pdata
,0,4096LL);
4557 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4561 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4567 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4568 TALLOC_CTX
*mem_ctx
,
4569 uint16_t info_level
,
4571 struct smb_filename
*smb_fname
,
4572 bool delete_pending
,
4573 struct timespec write_time_ts
,
4574 struct ea_list
*ea_list
,
4575 int lock_data_count
,
4578 unsigned int max_data_bytes
,
4579 size_t *fixed_portion
,
4581 unsigned int *pdata_size
)
4583 char *pdata
= *ppdata
;
4584 char *dstart
, *dend
;
4585 unsigned int data_size
;
4586 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4587 time_t create_time
, mtime
, atime
, c_time
;
4588 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4595 uint64_t file_size
= 0;
4597 uint64_t allocation_size
= 0;
4598 uint64_t file_index
= 0;
4599 uint32_t access_mask
= 0;
4602 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4603 return NT_STATUS_INVALID_LEVEL
;
4606 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4607 smb_fname_str_dbg(smb_fname
),
4609 info_level
, max_data_bytes
));
4611 mode
= dos_mode(conn
, smb_fname
);
4612 nlink
= psbuf
->st_ex_nlink
;
4614 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4618 if ((nlink
> 0) && delete_pending
) {
4622 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4623 return NT_STATUS_INVALID_PARAMETER
;
4626 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4627 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4628 if (*ppdata
== NULL
) {
4629 return NT_STATUS_NO_MEMORY
;
4633 dend
= dstart
+ data_size
- 1;
4635 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4636 update_stat_ex_mtime(psbuf
, write_time_ts
);
4639 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4640 mtime_ts
= psbuf
->st_ex_mtime
;
4641 atime_ts
= psbuf
->st_ex_atime
;
4642 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4644 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4645 dos_filetime_timespec(&create_time_ts
);
4646 dos_filetime_timespec(&mtime_ts
);
4647 dos_filetime_timespec(&atime_ts
);
4648 dos_filetime_timespec(&ctime_ts
);
4651 create_time
= convert_timespec_to_time_t(create_time_ts
);
4652 mtime
= convert_timespec_to_time_t(mtime_ts
);
4653 atime
= convert_timespec_to_time_t(atime_ts
);
4654 c_time
= convert_timespec_to_time_t(ctime_ts
);
4656 p
= strrchr_m(smb_fname
->base_name
,'/');
4658 base_name
= smb_fname
->base_name
;
4662 /* NT expects the name to be in an exact form of the *full*
4663 filename. See the trans2 torture test */
4664 if (ISDOT(base_name
)) {
4665 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4667 return NT_STATUS_NO_MEMORY
;
4670 dos_fname
= talloc_asprintf(mem_ctx
,
4672 smb_fname
->base_name
);
4674 return NT_STATUS_NO_MEMORY
;
4676 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4677 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4678 smb_fname
->stream_name
);
4680 return NT_STATUS_NO_MEMORY
;
4684 string_replace(dos_fname
, '/', '\\');
4687 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4690 /* Do we have this path open ? */
4692 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4693 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4694 if (fsp1
&& fsp1
->initial_allocation_size
) {
4695 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4699 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4700 file_size
= get_file_size_stat(psbuf
);
4704 pos
= fsp
->fh
->position_information
;
4708 access_mask
= fsp
->access_mask
;
4710 /* GENERIC_EXECUTE mapping from Windows */
4711 access_mask
= 0x12019F;
4714 /* This should be an index number - looks like
4717 I think this causes us to fail the IFSKIT
4718 BasicFileInformationTest. -tpot */
4719 file_index
= get_FileIndex(conn
, psbuf
);
4723 switch (info_level
) {
4724 case SMB_INFO_STANDARD
:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4727 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4728 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4729 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4730 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4731 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4732 SSVAL(pdata
,l1_attrFile
,mode
);
4735 case SMB_INFO_QUERY_EA_SIZE
:
4737 unsigned int ea_size
=
4738 estimate_ea_size(conn
, fsp
,
4740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4742 srv_put_dos_date2(pdata
,0,create_time
);
4743 srv_put_dos_date2(pdata
,4,atime
);
4744 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4745 SIVAL(pdata
,12,(uint32_t)file_size
);
4746 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4747 SSVAL(pdata
,20,mode
);
4748 SIVAL(pdata
,22,ea_size
);
4752 case SMB_INFO_IS_NAME_VALID
:
4753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4755 /* os/2 needs this ? really ?*/
4756 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4758 /* This is only reached for qpathinfo */
4762 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4764 size_t total_ea_len
= 0;
4765 struct ea_list
*ea_file_list
= NULL
;
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4769 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4771 &total_ea_len
, &ea_file_list
);
4772 if (!NT_STATUS_IS_OK(status
)) {
4776 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4778 if (!ea_list
|| (total_ea_len
> data_size
)) {
4780 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4784 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4788 case SMB_INFO_QUERY_ALL_EAS
:
4790 /* We have data_size bytes to put EA's into. */
4791 size_t total_ea_len
= 0;
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4794 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4796 &total_ea_len
, &ea_list
);
4797 if (!NT_STATUS_IS_OK(status
)) {
4801 if (!ea_list
|| (total_ea_len
> data_size
)) {
4803 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4807 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4811 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4813 /* This is FileFullEaInformation - 0xF which maps to
4814 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4816 /* We have data_size bytes to put EA's into. */
4817 size_t total_ea_len
= 0;
4818 struct ea_list
*ea_file_list
= NULL
;
4820 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4822 /*TODO: add filtering and index handling */
4825 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4827 &total_ea_len
, &ea_file_list
);
4828 if (!NT_STATUS_IS_OK(status
)) {
4831 if (!ea_file_list
) {
4832 return NT_STATUS_NO_EAS_ON_FILE
;
4835 status
= fill_ea_chained_buffer(mem_ctx
,
4839 conn
, ea_file_list
);
4840 if (!NT_STATUS_IS_OK(status
)) {
4846 case SMB_FILE_BASIC_INFORMATION
:
4847 case SMB_QUERY_FILE_BASIC_INFO
:
4849 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4851 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4853 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4857 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4858 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4859 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4860 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4861 SIVAL(pdata
,32,mode
);
4863 DEBUG(5,("SMB_QFBI - "));
4864 DEBUG(5,("create: %s ", ctime(&create_time
)));
4865 DEBUG(5,("access: %s ", ctime(&atime
)));
4866 DEBUG(5,("write: %s ", ctime(&mtime
)));
4867 DEBUG(5,("change: %s ", ctime(&c_time
)));
4868 DEBUG(5,("mode: %x\n", mode
));
4869 *fixed_portion
= data_size
;
4872 case SMB_FILE_STANDARD_INFORMATION
:
4873 case SMB_QUERY_FILE_STANDARD_INFO
:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4877 SOFF_T(pdata
,0,allocation_size
);
4878 SOFF_T(pdata
,8,file_size
);
4879 SIVAL(pdata
,16,nlink
);
4880 SCVAL(pdata
,20,delete_pending
?1:0);
4881 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4882 SSVAL(pdata
,22,0); /* Padding. */
4883 *fixed_portion
= 24;
4886 case SMB_FILE_EA_INFORMATION
:
4887 case SMB_QUERY_FILE_EA_INFO
:
4889 unsigned int ea_size
=
4890 estimate_ea_size(conn
, fsp
, smb_fname
);
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4894 SIVAL(pdata
,0,ea_size
);
4898 /* Get the 8.3 name - used if NT SMB was negotiated. */
4899 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4900 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4902 char mangled_name
[13];
4903 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4904 if (!name_to_8_3(base_name
,mangled_name
,
4905 True
,conn
->params
)) {
4906 return NT_STATUS_NO_MEMORY
;
4908 status
= srvstr_push(dstart
, flags2
,
4909 pdata
+4, mangled_name
,
4910 PTR_DIFF(dend
, pdata
+4),
4912 if (!NT_STATUS_IS_OK(status
)) {
4915 data_size
= 4 + len
;
4921 case SMB_QUERY_FILE_NAME_INFO
:
4924 this must be *exactly* right for ACLs on mapped drives to work
4926 status
= srvstr_push(dstart
, flags2
,
4928 PTR_DIFF(dend
, pdata
+4),
4930 if (!NT_STATUS_IS_OK(status
)) {
4933 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4934 data_size
= 4 + len
;
4939 case SMB_FILE_ALLOCATION_INFORMATION
:
4940 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4941 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4943 SOFF_T(pdata
,0,allocation_size
);
4946 case SMB_FILE_END_OF_FILE_INFORMATION
:
4947 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4948 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4950 SOFF_T(pdata
,0,file_size
);
4953 case SMB_QUERY_FILE_ALL_INFO
:
4954 case SMB_FILE_ALL_INFORMATION
:
4956 unsigned int ea_size
=
4957 estimate_ea_size(conn
, fsp
, smb_fname
);
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4959 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4960 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4961 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4962 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4963 SIVAL(pdata
,32,mode
);
4964 SIVAL(pdata
,36,0); /* padding. */
4966 SOFF_T(pdata
,0,allocation_size
);
4967 SOFF_T(pdata
,8,file_size
);
4968 SIVAL(pdata
,16,nlink
);
4969 SCVAL(pdata
,20,delete_pending
);
4970 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4973 SIVAL(pdata
,0,ea_size
);
4974 pdata
+= 4; /* EA info */
4975 status
= srvstr_push(dstart
, flags2
,
4977 PTR_DIFF(dend
, pdata
+4),
4979 if (!NT_STATUS_IS_OK(status
)) {
4984 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4985 *fixed_portion
= 10;
4989 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4991 unsigned int ea_size
=
4992 estimate_ea_size(conn
, fsp
, smb_fname
);
4993 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4994 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4995 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4996 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4997 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4998 SIVAL(pdata
, 0x20, mode
);
4999 SIVAL(pdata
, 0x24, 0); /* padding. */
5000 SBVAL(pdata
, 0x28, allocation_size
);
5001 SBVAL(pdata
, 0x30, file_size
);
5002 SIVAL(pdata
, 0x38, nlink
);
5003 SCVAL(pdata
, 0x3C, delete_pending
);
5004 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5005 SSVAL(pdata
, 0x3E, 0); /* padding */
5006 SBVAL(pdata
, 0x40, file_index
);
5007 SIVAL(pdata
, 0x48, ea_size
);
5008 SIVAL(pdata
, 0x4C, access_mask
);
5009 SBVAL(pdata
, 0x50, pos
);
5010 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5011 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5015 status
= srvstr_push(dstart
, flags2
,
5017 PTR_DIFF(dend
, pdata
+4),
5019 if (!NT_STATUS_IS_OK(status
)) {
5024 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5025 *fixed_portion
= 104;
5028 case SMB_FILE_INTERNAL_INFORMATION
:
5030 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5031 SBVAL(pdata
, 0, file_index
);
5036 case SMB_FILE_ACCESS_INFORMATION
:
5037 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5038 SIVAL(pdata
, 0, access_mask
);
5043 case SMB_FILE_NAME_INFORMATION
:
5044 /* Pathname with leading '\'. */
5047 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5048 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5049 SIVAL(pdata
,0,byte_len
);
5050 data_size
= 4 + byte_len
;
5054 case SMB_FILE_DISPOSITION_INFORMATION
:
5055 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5057 SCVAL(pdata
,0,delete_pending
);
5061 case SMB_FILE_POSITION_INFORMATION
:
5062 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5064 SOFF_T(pdata
,0,pos
);
5068 case SMB_FILE_MODE_INFORMATION
:
5069 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5070 SIVAL(pdata
,0,mode
);
5075 case SMB_FILE_ALIGNMENT_INFORMATION
:
5076 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5077 SIVAL(pdata
,0,0); /* No alignment needed. */
5083 * NT4 server just returns "invalid query" to this - if we try
5084 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5087 /* The first statement above is false - verified using Thursby
5088 * client against NT4 -- gcolley.
5090 case SMB_QUERY_FILE_STREAM_INFO
:
5091 case SMB_FILE_STREAM_INFORMATION
: {
5092 unsigned int num_streams
= 0;
5093 struct stream_struct
*streams
= NULL
;
5095 DEBUG(10,("smbd_do_qfilepathinfo: "
5096 "SMB_FILE_STREAM_INFORMATION\n"));
5098 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5099 return NT_STATUS_INVALID_PARAMETER
;
5102 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5103 talloc_tos(), &num_streams
, &streams
);
5105 if (!NT_STATUS_IS_OK(status
)) {
5106 DEBUG(10, ("could not get stream info: %s\n",
5107 nt_errstr(status
)));
5111 status
= marshall_stream_info(num_streams
, streams
,
5112 pdata
, max_data_bytes
,
5115 if (!NT_STATUS_IS_OK(status
)) {
5116 DEBUG(10, ("marshall_stream_info failed: %s\n",
5117 nt_errstr(status
)));
5118 TALLOC_FREE(streams
);
5122 TALLOC_FREE(streams
);
5124 *fixed_portion
= 32;
5128 case SMB_QUERY_COMPRESSION_INFO
:
5129 case SMB_FILE_COMPRESSION_INFORMATION
:
5130 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5131 SOFF_T(pdata
,0,file_size
);
5132 SIVAL(pdata
,8,0); /* ??? */
5133 SIVAL(pdata
,12,0); /* ??? */
5135 *fixed_portion
= 16;
5138 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5140 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5141 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5142 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5143 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5144 SOFF_T(pdata
,32,allocation_size
);
5145 SOFF_T(pdata
,40,file_size
);
5146 SIVAL(pdata
,48,mode
);
5147 SIVAL(pdata
,52,0); /* ??? */
5149 *fixed_portion
= 56;
5152 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5153 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5154 SIVAL(pdata
,0,mode
);
5161 * CIFS UNIX Extensions.
5164 case SMB_QUERY_FILE_UNIX_BASIC
:
5166 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5167 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5169 DEBUG(4,("smbd_do_qfilepathinfo: "
5170 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5171 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5175 case SMB_QUERY_FILE_UNIX_INFO2
:
5177 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5178 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5182 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5184 for (i
=0; i
<100; i
++)
5185 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5191 case SMB_QUERY_FILE_UNIX_LINK
:
5194 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5197 return NT_STATUS_NO_MEMORY
;
5200 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5202 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5203 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5206 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5208 link_len
= SMB_VFS_READLINK(conn
,
5209 smb_fname
->base_name
,
5211 if (link_len
== -1) {
5212 return map_nt_error_from_unix(errno
);
5214 buffer
[link_len
] = 0;
5215 status
= srvstr_push(dstart
, flags2
,
5217 PTR_DIFF(dend
, pdata
),
5218 STR_TERMINATE
, &len
);
5219 if (!NT_STATUS_IS_OK(status
)) {
5223 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5228 #if defined(HAVE_POSIX_ACLS)
5229 case SMB_QUERY_POSIX_ACL
:
5231 SMB_ACL_T file_acl
= NULL
;
5232 SMB_ACL_T def_acl
= NULL
;
5233 uint16_t num_file_acls
= 0;
5234 uint16_t num_def_acls
= 0;
5236 if (fsp
&& fsp
->fh
->fd
!= -1) {
5237 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5241 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5242 smb_fname
->base_name
,
5243 SMB_ACL_TYPE_ACCESS
,
5247 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5248 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5249 "not implemented on "
5250 "filesystem containing %s\n",
5251 smb_fname
->base_name
));
5252 return NT_STATUS_NOT_IMPLEMENTED
;
5255 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5256 if (fsp
&& fsp
->is_directory
) {
5258 SMB_VFS_SYS_ACL_GET_FILE(
5260 fsp
->fsp_name
->base_name
,
5261 SMB_ACL_TYPE_DEFAULT
,
5265 SMB_VFS_SYS_ACL_GET_FILE(
5267 smb_fname
->base_name
,
5268 SMB_ACL_TYPE_DEFAULT
,
5271 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5274 num_file_acls
= count_acl_entries(conn
, file_acl
);
5275 num_def_acls
= count_acl_entries(conn
, def_acl
);
5277 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5278 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5280 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5281 SMB_POSIX_ACL_HEADER_SIZE
) ));
5283 TALLOC_FREE(file_acl
);
5286 TALLOC_FREE(def_acl
);
5288 return NT_STATUS_BUFFER_TOO_SMALL
;
5291 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5292 SSVAL(pdata
,2,num_file_acls
);
5293 SSVAL(pdata
,4,num_def_acls
);
5294 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5296 TALLOC_FREE(file_acl
);
5299 TALLOC_FREE(def_acl
);
5301 return NT_STATUS_INTERNAL_ERROR
;
5303 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5305 TALLOC_FREE(file_acl
);
5308 TALLOC_FREE(def_acl
);
5310 return NT_STATUS_INTERNAL_ERROR
;
5314 TALLOC_FREE(file_acl
);
5317 TALLOC_FREE(def_acl
);
5319 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5325 case SMB_QUERY_POSIX_LOCK
:
5330 enum brl_type lock_type
;
5332 /* We need an open file with a real fd for this. */
5333 if (!fsp
|| fsp
->fh
->fd
== -1) {
5334 return NT_STATUS_INVALID_LEVEL
;
5337 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5338 return NT_STATUS_INVALID_PARAMETER
;
5341 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5342 case POSIX_LOCK_TYPE_READ
:
5343 lock_type
= READ_LOCK
;
5345 case POSIX_LOCK_TYPE_WRITE
:
5346 lock_type
= WRITE_LOCK
;
5348 case POSIX_LOCK_TYPE_UNLOCK
:
5350 /* There's no point in asking for an unlock... */
5351 return NT_STATUS_INVALID_PARAMETER
;
5354 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5355 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5356 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5358 status
= query_lock(fsp
,
5365 if (ERROR_WAS_LOCK_DENIED(status
)) {
5366 /* Here we need to report who has it locked... */
5367 data_size
= POSIX_LOCK_DATA_SIZE
;
5369 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5370 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5371 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5372 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5373 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5375 } else if (NT_STATUS_IS_OK(status
)) {
5376 /* For success we just return a copy of what we sent
5377 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5378 data_size
= POSIX_LOCK_DATA_SIZE
;
5379 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5380 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5388 return NT_STATUS_INVALID_LEVEL
;
5391 *pdata_size
= data_size
;
5392 return NT_STATUS_OK
;
5395 /****************************************************************************
5396 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5397 file name or file id).
5398 ****************************************************************************/
5400 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5401 struct smb_request
*req
,
5402 unsigned int tran_call
,
5403 char **pparams
, int total_params
,
5404 char **ppdata
, int total_data
,
5405 unsigned int max_data_bytes
)
5407 char *params
= *pparams
;
5408 char *pdata
= *ppdata
;
5409 uint16_t info_level
;
5410 unsigned int data_size
= 0;
5411 unsigned int param_size
= 2;
5412 struct smb_filename
*smb_fname
= NULL
;
5413 bool delete_pending
= False
;
5414 struct timespec write_time_ts
;
5415 files_struct
*fsp
= NULL
;
5416 struct file_id fileid
;
5417 struct ea_list
*ea_list
= NULL
;
5418 int lock_data_count
= 0;
5419 char *lock_data
= NULL
;
5420 size_t fixed_portion
;
5421 NTSTATUS status
= NT_STATUS_OK
;
5424 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5428 ZERO_STRUCT(write_time_ts
);
5430 if (tran_call
== TRANSACT2_QFILEINFO
) {
5431 if (total_params
< 4) {
5432 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5437 call_trans2qpipeinfo(conn
, req
, tran_call
,
5438 pparams
, total_params
,
5444 fsp
= file_fsp(req
, SVAL(params
,0));
5445 info_level
= SVAL(params
,2);
5447 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5449 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5450 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5454 /* Initial check for valid fsp ptr. */
5455 if (!check_fsp_open(conn
, req
, fsp
)) {
5459 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5460 if (smb_fname
== NULL
) {
5461 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5465 if(fsp
->fake_file_handle
) {
5467 * This is actually for the QUOTA_FAKE_FILE --metze
5470 /* We know this name is ok, it's already passed the checks. */
5472 } else if(fsp
->fh
->fd
== -1) {
5474 * This is actually a QFILEINFO on a directory
5475 * handle (returned from an NT SMB). NT5.0 seems
5476 * to do this call. JRA.
5479 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5480 /* Always do lstat for UNIX calls. */
5481 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5482 DEBUG(3,("call_trans2qfilepathinfo: "
5483 "SMB_VFS_LSTAT of %s failed "
5485 smb_fname_str_dbg(smb_fname
),
5488 map_nt_error_from_unix(errno
));
5491 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5492 DEBUG(3,("call_trans2qfilepathinfo: "
5493 "SMB_VFS_STAT of %s failed (%s)\n",
5494 smb_fname_str_dbg(smb_fname
),
5497 map_nt_error_from_unix(errno
));
5501 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5502 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5505 * Original code - this is an open file.
5507 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5508 DEBUG(3, ("fstat of %s failed (%s)\n",
5509 fsp_fnum_dbg(fsp
), strerror(errno
)));
5511 map_nt_error_from_unix(errno
));
5514 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5515 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5521 uint32_t ucf_flags
= 0;
5524 if (total_params
< 7) {
5525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5529 info_level
= SVAL(params
,0);
5531 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5533 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5534 if (!lp_unix_extensions()) {
5535 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5538 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5539 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5540 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5541 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5545 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5547 STR_TERMINATE
, &status
);
5548 if (!NT_STATUS_IS_OK(status
)) {
5549 reply_nterror(req
, status
);
5553 status
= filename_convert(req
,
5555 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5560 if (!NT_STATUS_IS_OK(status
)) {
5561 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5562 reply_botherror(req
,
5563 NT_STATUS_PATH_NOT_COVERED
,
5564 ERRSRV
, ERRbadpath
);
5567 reply_nterror(req
, status
);
5571 /* If this is a stream, check if there is a delete_pending. */
5572 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5573 && is_ntfs_stream_smb_fname(smb_fname
)) {
5574 struct smb_filename
*smb_fname_base
;
5576 /* Create an smb_filename with stream_name == NULL. */
5577 smb_fname_base
= synthetic_smb_fname(
5578 talloc_tos(), smb_fname
->base_name
,
5580 if (smb_fname_base
== NULL
) {
5581 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5585 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5586 /* Always do lstat for UNIX calls. */
5587 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5588 DEBUG(3,("call_trans2qfilepathinfo: "
5589 "SMB_VFS_LSTAT of %s failed "
5591 smb_fname_str_dbg(smb_fname_base
),
5593 TALLOC_FREE(smb_fname_base
);
5595 map_nt_error_from_unix(errno
));
5599 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5600 DEBUG(3,("call_trans2qfilepathinfo: "
5601 "fileinfo of %s failed "
5603 smb_fname_str_dbg(smb_fname_base
),
5605 TALLOC_FREE(smb_fname_base
);
5607 map_nt_error_from_unix(errno
));
5612 status
= file_name_hash(conn
,
5613 smb_fname_str_dbg(smb_fname_base
),
5615 if (!NT_STATUS_IS_OK(status
)) {
5616 TALLOC_FREE(smb_fname_base
);
5617 reply_nterror(req
, status
);
5621 fileid
= vfs_file_id_from_sbuf(conn
,
5622 &smb_fname_base
->st
);
5623 TALLOC_FREE(smb_fname_base
);
5624 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5625 if (delete_pending
) {
5626 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5631 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5632 /* Always do lstat for UNIX calls. */
5633 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5634 DEBUG(3,("call_trans2qfilepathinfo: "
5635 "SMB_VFS_LSTAT of %s failed (%s)\n",
5636 smb_fname_str_dbg(smb_fname
),
5639 map_nt_error_from_unix(errno
));
5644 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5645 DEBUG(3,("call_trans2qfilepathinfo: "
5646 "SMB_VFS_STAT of %s failed (%s)\n",
5647 smb_fname_str_dbg(smb_fname
),
5650 map_nt_error_from_unix(errno
));
5655 status
= file_name_hash(conn
,
5656 smb_fname_str_dbg(smb_fname
),
5658 if (!NT_STATUS_IS_OK(status
)) {
5659 reply_nterror(req
, status
);
5663 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5664 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5665 if (delete_pending
) {
5666 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5671 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5672 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5674 info_level
,tran_call
,total_data
));
5676 /* Pull out any data sent here before we realloc. */
5677 switch (info_level
) {
5678 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5680 /* Pull any EA list from the data portion. */
5683 if (total_data
< 4) {
5685 req
, NT_STATUS_INVALID_PARAMETER
);
5688 ea_size
= IVAL(pdata
,0);
5690 if (total_data
> 0 && ea_size
!= total_data
) {
5691 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5692 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5694 req
, NT_STATUS_INVALID_PARAMETER
);
5698 if (!lp_ea_support(SNUM(conn
))) {
5699 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5703 /* Pull out the list of names. */
5704 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5707 req
, NT_STATUS_INVALID_PARAMETER
);
5713 case SMB_QUERY_POSIX_LOCK
:
5715 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5716 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5720 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5722 req
, NT_STATUS_INVALID_PARAMETER
);
5726 /* Copy the lock range data. */
5727 lock_data
= (char *)talloc_memdup(
5728 req
, pdata
, total_data
);
5730 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5733 lock_data_count
= total_data
;
5739 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5740 if (*pparams
== NULL
) {
5741 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5748 * draft-leach-cifs-v1-spec-02.txt
5749 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5752 * The requested information is placed in the Data portion of the
5753 * transaction response. For the information levels greater than 0x100,
5754 * the transaction response has 1 parameter word which should be
5755 * ignored by the client.
5757 * However Windows only follows this rule for the IS_NAME_VALID call.
5759 switch (info_level
) {
5760 case SMB_INFO_IS_NAME_VALID
:
5765 if ((info_level
& 0xFF00) == 0xFF00) {
5767 * We use levels that start with 0xFF00
5768 * internally to represent SMB2 specific levels
5770 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5774 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5776 delete_pending
, write_time_ts
,
5778 lock_data_count
, lock_data
,
5779 req
->flags2
, max_data_bytes
,
5781 ppdata
, &data_size
);
5782 if (!NT_STATUS_IS_OK(status
)) {
5783 reply_nterror(req
, status
);
5786 if (fixed_portion
> max_data_bytes
) {
5787 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5791 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5797 /****************************************************************************
5798 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5800 ****************************************************************************/
5802 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5803 connection_struct
*conn
,
5804 struct smb_request
*req
,
5805 bool overwrite_if_exists
,
5806 const struct smb_filename
*smb_fname_old
,
5807 struct smb_filename
*smb_fname_new
)
5809 NTSTATUS status
= NT_STATUS_OK
;
5811 /* source must already exist. */
5812 if (!VALID_STAT(smb_fname_old
->st
)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5816 if (VALID_STAT(smb_fname_new
->st
)) {
5817 if (overwrite_if_exists
) {
5818 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5819 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5821 status
= unlink_internals(conn
,
5823 FILE_ATTRIBUTE_NORMAL
,
5826 if (!NT_STATUS_IS_OK(status
)) {
5830 /* Disallow if newname already exists. */
5831 return NT_STATUS_OBJECT_NAME_COLLISION
;
5835 /* No links from a directory. */
5836 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5837 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5840 /* Setting a hardlink to/from a stream isn't currently supported. */
5841 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5842 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5843 return NT_STATUS_INVALID_PARAMETER
;
5846 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5847 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5849 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5850 smb_fname_new
->base_name
) != 0) {
5851 status
= map_nt_error_from_unix(errno
);
5852 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5853 nt_errstr(status
), smb_fname_old
->base_name
,
5854 smb_fname_new
->base_name
));
5859 /****************************************************************************
5860 Deal with setting the time from any of the setfilepathinfo functions.
5861 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5862 calling this function.
5863 ****************************************************************************/
5865 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5867 const struct smb_filename
*smb_fname
,
5868 struct smb_file_time
*ft
,
5869 bool setting_write_time
)
5871 struct smb_filename smb_fname_base
;
5873 FILE_NOTIFY_CHANGE_LAST_ACCESS
5874 |FILE_NOTIFY_CHANGE_LAST_WRITE
5875 |FILE_NOTIFY_CHANGE_CREATION
;
5877 if (!VALID_STAT(smb_fname
->st
)) {
5878 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5881 /* get some defaults (no modifications) if any info is zero or -1. */
5882 if (null_timespec(ft
->create_time
)) {
5883 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5886 if (null_timespec(ft
->atime
)) {
5887 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5890 if (null_timespec(ft
->mtime
)) {
5891 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5894 if (!setting_write_time
) {
5895 /* ft->mtime comes from change time, not write time. */
5896 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5899 /* Ensure the resolution is the correct for
5900 * what we can store on this filesystem. */
5902 round_timespec(conn
->ts_res
, &ft
->create_time
);
5903 round_timespec(conn
->ts_res
, &ft
->ctime
);
5904 round_timespec(conn
->ts_res
, &ft
->atime
);
5905 round_timespec(conn
->ts_res
, &ft
->mtime
);
5907 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5908 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5909 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5910 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5911 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5912 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5913 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5914 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5916 if (setting_write_time
) {
5918 * This was a Windows setfileinfo on an open file.
5919 * NT does this a lot. We also need to
5920 * set the time here, as it can be read by
5921 * FindFirst/FindNext and with the patch for bug #2045
5922 * in smbd/fileio.c it ensures that this timestamp is
5923 * kept sticky even after a write. We save the request
5924 * away and will set it on file close and after a write. JRA.
5927 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5928 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5931 if (fsp
->base_fsp
) {
5932 set_sticky_write_time_fsp(fsp
->base_fsp
,
5935 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5938 set_sticky_write_time_path(
5939 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5944 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5946 /* Always call ntimes on the base, even if a stream was passed in. */
5947 smb_fname_base
= *smb_fname
;
5948 smb_fname_base
.stream_name
= NULL
;
5950 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5951 return map_nt_error_from_unix(errno
);
5954 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5955 smb_fname
->base_name
);
5956 return NT_STATUS_OK
;
5959 /****************************************************************************
5960 Deal with setting the dosmode from any of the setfilepathinfo functions.
5961 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5962 done before calling this function.
5963 ****************************************************************************/
5965 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5966 const struct smb_filename
*smb_fname
,
5969 struct smb_filename
*smb_fname_base
;
5972 if (!VALID_STAT(smb_fname
->st
)) {
5973 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5976 /* Always operate on the base_name, even if a stream was passed in. */
5977 smb_fname_base
= synthetic_smb_fname(
5978 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5979 if (smb_fname_base
== NULL
) {
5980 return NT_STATUS_NO_MEMORY
;
5984 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5985 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5987 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5991 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5993 /* check the mode isn't different, before changing it */
5994 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5995 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5996 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5997 (unsigned int)dosmode
));
5999 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6001 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6003 smb_fname_str_dbg(smb_fname_base
),
6005 status
= map_nt_error_from_unix(errno
);
6009 status
= NT_STATUS_OK
;
6011 TALLOC_FREE(smb_fname_base
);
6015 /****************************************************************************
6016 Deal with setting the size from any of the setfilepathinfo functions.
6017 ****************************************************************************/
6019 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6020 struct smb_request
*req
,
6022 const struct smb_filename
*smb_fname
,
6023 const SMB_STRUCT_STAT
*psbuf
,
6025 bool fail_after_createfile
)
6027 NTSTATUS status
= NT_STATUS_OK
;
6028 struct smb_filename
*smb_fname_tmp
= NULL
;
6029 files_struct
*new_fsp
= NULL
;
6031 if (!VALID_STAT(*psbuf
)) {
6032 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6035 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6037 if (size
== get_file_size_stat(psbuf
)) {
6038 return NT_STATUS_OK
;
6041 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6042 smb_fname_str_dbg(smb_fname
), (double)size
));
6044 if (fsp
&& fsp
->fh
->fd
!= -1) {
6045 /* Handle based call. */
6046 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6047 return NT_STATUS_ACCESS_DENIED
;
6050 if (vfs_set_filelen(fsp
, size
) == -1) {
6051 return map_nt_error_from_unix(errno
);
6053 trigger_write_time_update_immediate(fsp
);
6054 return NT_STATUS_OK
;
6057 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6058 if (smb_fname_tmp
== NULL
) {
6059 return NT_STATUS_NO_MEMORY
;
6062 smb_fname_tmp
->st
= *psbuf
;
6064 status
= SMB_VFS_CREATE_FILE(
6067 0, /* root_dir_fid */
6068 smb_fname_tmp
, /* fname */
6069 FILE_WRITE_DATA
, /* access_mask */
6070 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6072 FILE_OPEN
, /* create_disposition*/
6073 0, /* create_options */
6074 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6075 0, /* oplock_request */
6077 0, /* allocation_size */
6078 0, /* private_flags */
6081 &new_fsp
, /* result */
6083 NULL
, NULL
); /* create context */
6085 TALLOC_FREE(smb_fname_tmp
);
6087 if (!NT_STATUS_IS_OK(status
)) {
6088 /* NB. We check for open_was_deferred in the caller. */
6092 /* See RAW-SFILEINFO-END-OF-FILE */
6093 if (fail_after_createfile
) {
6094 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6095 return NT_STATUS_INVALID_LEVEL
;
6098 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6099 status
= map_nt_error_from_unix(errno
);
6100 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6104 trigger_write_time_update_immediate(new_fsp
);
6105 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6106 return NT_STATUS_OK
;
6109 /****************************************************************************
6110 Deal with SMB_INFO_SET_EA.
6111 ****************************************************************************/
6113 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6117 const struct smb_filename
*smb_fname
)
6119 struct ea_list
*ea_list
= NULL
;
6120 TALLOC_CTX
*ctx
= NULL
;
6121 NTSTATUS status
= NT_STATUS_OK
;
6123 if (total_data
< 10) {
6125 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6126 length. They seem to have no effect. Bug #3212. JRA */
6128 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6129 /* We're done. We only get EA info in this call. */
6130 return NT_STATUS_OK
;
6133 return NT_STATUS_INVALID_PARAMETER
;
6136 if (IVAL(pdata
,0) > total_data
) {
6137 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6138 IVAL(pdata
,0), (unsigned int)total_data
));
6139 return NT_STATUS_INVALID_PARAMETER
;
6143 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6145 return NT_STATUS_INVALID_PARAMETER
;
6148 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6153 /****************************************************************************
6154 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6155 ****************************************************************************/
6157 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6162 struct ea_list
*ea_list
= NULL
;
6166 return NT_STATUS_INVALID_HANDLE
;
6169 if (!lp_ea_support(SNUM(conn
))) {
6170 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6171 "EA's not supported.\n",
6172 (unsigned int)total_data
));
6173 return NT_STATUS_EAS_NOT_SUPPORTED
;
6176 if (total_data
< 10) {
6177 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6179 (unsigned int)total_data
));
6180 return NT_STATUS_INVALID_PARAMETER
;
6183 ea_list
= read_nttrans_ea_list(talloc_tos(),
6188 return NT_STATUS_INVALID_PARAMETER
;
6191 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6193 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6194 smb_fname_str_dbg(fsp
->fsp_name
),
6195 nt_errstr(status
) ));
6201 /****************************************************************************
6202 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6203 ****************************************************************************/
6205 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6209 struct smb_filename
*smb_fname
)
6211 NTSTATUS status
= NT_STATUS_OK
;
6212 bool delete_on_close
;
6213 uint32_t dosmode
= 0;
6215 if (total_data
< 1) {
6216 return NT_STATUS_INVALID_PARAMETER
;
6220 return NT_STATUS_INVALID_HANDLE
;
6223 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6224 dosmode
= dos_mode(conn
, smb_fname
);
6226 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6227 "delete_on_close = %u\n",
6228 smb_fname_str_dbg(smb_fname
),
6229 (unsigned int)dosmode
,
6230 (unsigned int)delete_on_close
));
6232 if (delete_on_close
) {
6233 status
= can_set_delete_on_close(fsp
, dosmode
);
6234 if (!NT_STATUS_IS_OK(status
)) {
6239 /* The set is across all open files on this dev/inode pair. */
6240 if (!set_delete_on_close(fsp
, delete_on_close
,
6241 conn
->session_info
->security_token
,
6242 conn
->session_info
->unix_token
)) {
6243 return NT_STATUS_ACCESS_DENIED
;
6245 return NT_STATUS_OK
;
6248 /****************************************************************************
6249 Deal with SMB_FILE_POSITION_INFORMATION.
6250 ****************************************************************************/
6252 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6257 uint64_t position_information
;
6259 if (total_data
< 8) {
6260 return NT_STATUS_INVALID_PARAMETER
;
6264 /* Ignore on pathname based set. */
6265 return NT_STATUS_OK
;
6268 position_information
= (uint64_t)IVAL(pdata
,0);
6269 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6271 DEBUG(10,("smb_file_position_information: Set file position "
6272 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6273 (double)position_information
));
6274 fsp
->fh
->position_information
= position_information
;
6275 return NT_STATUS_OK
;
6278 /****************************************************************************
6279 Deal with SMB_FILE_MODE_INFORMATION.
6280 ****************************************************************************/
6282 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6288 if (total_data
< 4) {
6289 return NT_STATUS_INVALID_PARAMETER
;
6291 mode
= IVAL(pdata
,0);
6292 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6293 return NT_STATUS_INVALID_PARAMETER
;
6295 return NT_STATUS_OK
;
6298 /****************************************************************************
6299 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6300 ****************************************************************************/
6302 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6303 struct smb_request
*req
,
6306 const struct smb_filename
*smb_fname
)
6308 char *link_target
= NULL
;
6309 const char *newname
= smb_fname
->base_name
;
6310 TALLOC_CTX
*ctx
= talloc_tos();
6312 /* Set a symbolic link. */
6313 /* Don't allow this if follow links is false. */
6315 if (total_data
== 0) {
6316 return NT_STATUS_INVALID_PARAMETER
;
6319 if (!lp_follow_symlinks(SNUM(conn
))) {
6320 return NT_STATUS_ACCESS_DENIED
;
6323 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6324 total_data
, STR_TERMINATE
);
6327 return NT_STATUS_INVALID_PARAMETER
;
6330 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6331 newname
, link_target
));
6333 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6334 return map_nt_error_from_unix(errno
);
6337 return NT_STATUS_OK
;
6340 /****************************************************************************
6341 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6342 ****************************************************************************/
6344 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6345 struct smb_request
*req
,
6346 const char *pdata
, int total_data
,
6347 struct smb_filename
*smb_fname_new
)
6349 char *oldname
= NULL
;
6350 struct smb_filename
*smb_fname_old
= NULL
;
6351 TALLOC_CTX
*ctx
= talloc_tos();
6352 NTSTATUS status
= NT_STATUS_OK
;
6354 /* Set a hard link. */
6355 if (total_data
== 0) {
6356 return NT_STATUS_INVALID_PARAMETER
;
6359 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6360 total_data
, STR_TERMINATE
, &status
);
6361 if (!NT_STATUS_IS_OK(status
)) {
6365 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6366 smb_fname_str_dbg(smb_fname_new
), oldname
));
6368 status
= filename_convert(ctx
,
6370 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6375 if (!NT_STATUS_IS_OK(status
)) {
6379 return hardlink_internals(ctx
, conn
, req
, false,
6380 smb_fname_old
, smb_fname_new
);
6383 /****************************************************************************
6384 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6385 ****************************************************************************/
6387 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6388 struct smb_request
*req
,
6392 struct smb_filename
*smb_fname_src
)
6396 char *newname
= NULL
;
6397 struct smb_filename
*smb_fname_dst
= NULL
;
6398 NTSTATUS status
= NT_STATUS_OK
;
6399 TALLOC_CTX
*ctx
= talloc_tos();
6402 return NT_STATUS_INVALID_HANDLE
;
6405 if (total_data
< 20) {
6406 return NT_STATUS_INVALID_PARAMETER
;
6409 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6410 len
= IVAL(pdata
,16);
6412 if (len
> (total_data
- 20) || (len
== 0)) {
6413 return NT_STATUS_INVALID_PARAMETER
;
6416 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6417 &pdata
[20], len
, STR_TERMINATE
,
6419 if (!NT_STATUS_IS_OK(status
)) {
6423 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6426 status
= filename_convert(ctx
,
6428 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6433 if (!NT_STATUS_IS_OK(status
)) {
6437 if (fsp
->base_fsp
) {
6438 /* newname must be a stream name. */
6439 if (newname
[0] != ':') {
6440 return NT_STATUS_NOT_SUPPORTED
;
6443 /* Create an smb_fname to call rename_internals_fsp() with. */
6444 smb_fname_dst
= synthetic_smb_fname(
6445 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6447 if (smb_fname_dst
== NULL
) {
6448 status
= NT_STATUS_NO_MEMORY
;
6453 * Set the original last component, since
6454 * rename_internals_fsp() requires it.
6456 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6458 if (smb_fname_dst
->original_lcomp
== NULL
) {
6459 status
= NT_STATUS_NO_MEMORY
;
6465 DEBUG(10,("smb2_file_rename_information: "
6466 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6467 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6468 smb_fname_str_dbg(smb_fname_dst
)));
6469 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6470 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6474 TALLOC_FREE(smb_fname_dst
);
6478 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6479 struct smb_request
*req
,
6483 struct smb_filename
*smb_fname_src
)
6487 char *newname
= NULL
;
6488 struct smb_filename
*smb_fname_dst
= NULL
;
6489 NTSTATUS status
= NT_STATUS_OK
;
6490 TALLOC_CTX
*ctx
= talloc_tos();
6493 return NT_STATUS_INVALID_HANDLE
;
6496 if (total_data
< 20) {
6497 return NT_STATUS_INVALID_PARAMETER
;
6500 overwrite
= (CVAL(pdata
,0) ? true : false);
6501 len
= IVAL(pdata
,16);
6503 if (len
> (total_data
- 20) || (len
== 0)) {
6504 return NT_STATUS_INVALID_PARAMETER
;
6507 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6508 &pdata
[20], len
, STR_TERMINATE
,
6510 if (!NT_STATUS_IS_OK(status
)) {
6514 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6517 status
= filename_convert(ctx
,
6519 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6524 if (!NT_STATUS_IS_OK(status
)) {
6528 if (fsp
->base_fsp
) {
6529 /* No stream names. */
6530 return NT_STATUS_NOT_SUPPORTED
;
6533 DEBUG(10,("smb_file_link_information: "
6534 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6535 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6536 smb_fname_str_dbg(smb_fname_dst
)));
6537 status
= hardlink_internals(ctx
,
6544 TALLOC_FREE(smb_fname_dst
);
6548 /****************************************************************************
6549 Deal with SMB_FILE_RENAME_INFORMATION.
6550 ****************************************************************************/
6552 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6553 struct smb_request
*req
,
6557 struct smb_filename
*smb_fname_src
)
6562 char *newname
= NULL
;
6563 struct smb_filename
*smb_fname_dst
= NULL
;
6564 bool dest_has_wcard
= False
;
6565 NTSTATUS status
= NT_STATUS_OK
;
6567 TALLOC_CTX
*ctx
= talloc_tos();
6569 if (total_data
< 13) {
6570 return NT_STATUS_INVALID_PARAMETER
;
6573 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6574 root_fid
= IVAL(pdata
,4);
6575 len
= IVAL(pdata
,8);
6577 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6578 return NT_STATUS_INVALID_PARAMETER
;
6581 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6584 if (!NT_STATUS_IS_OK(status
)) {
6588 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6591 status
= resolve_dfspath_wcard(ctx
, conn
,
6592 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6595 !conn
->sconn
->using_smb2
,
6598 if (!NT_STATUS_IS_OK(status
)) {
6602 /* Check the new name has no '/' characters. */
6603 if (strchr_m(newname
, '/')) {
6604 return NT_STATUS_NOT_SUPPORTED
;
6607 if (fsp
&& fsp
->base_fsp
) {
6608 /* newname must be a stream name. */
6609 if (newname
[0] != ':') {
6610 return NT_STATUS_NOT_SUPPORTED
;
6613 /* Create an smb_fname to call rename_internals_fsp() with. */
6614 smb_fname_dst
= synthetic_smb_fname(
6615 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6617 if (smb_fname_dst
== NULL
) {
6618 status
= NT_STATUS_NO_MEMORY
;
6623 * Set the original last component, since
6624 * rename_internals_fsp() requires it.
6626 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6628 if (smb_fname_dst
->original_lcomp
== NULL
) {
6629 status
= NT_STATUS_NO_MEMORY
;
6635 * Build up an smb_fname_dst based on the filename passed in.
6636 * We basically just strip off the last component, and put on
6637 * the newname instead.
6639 char *base_name
= NULL
;
6641 /* newname must *not* be a stream name. */
6642 if (newname
[0] == ':') {
6643 return NT_STATUS_NOT_SUPPORTED
;
6647 * Strip off the last component (filename) of the path passed
6650 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6652 return NT_STATUS_NO_MEMORY
;
6654 p
= strrchr_m(base_name
, '/');
6658 base_name
= talloc_strdup(ctx
, "");
6660 return NT_STATUS_NO_MEMORY
;
6663 /* Append the new name. */
6664 base_name
= talloc_asprintf_append(base_name
,
6668 return NT_STATUS_NO_MEMORY
;
6671 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6674 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6677 /* If an error we expect this to be
6678 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6680 if (!NT_STATUS_IS_OK(status
)) {
6681 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6685 /* Create an smb_fname to call rename_internals_fsp() */
6686 smb_fname_dst
= synthetic_smb_fname(
6687 ctx
, base_name
, NULL
, NULL
);
6688 if (smb_fname_dst
== NULL
) {
6689 status
= NT_STATUS_NO_MEMORY
;
6696 DEBUG(10,("smb_file_rename_information: "
6697 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6698 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6699 smb_fname_str_dbg(smb_fname_dst
)));
6700 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6703 DEBUG(10,("smb_file_rename_information: "
6704 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6705 smb_fname_str_dbg(smb_fname_src
),
6706 smb_fname_str_dbg(smb_fname_dst
)));
6707 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6708 smb_fname_dst
, 0, overwrite
, false,
6710 FILE_WRITE_ATTRIBUTES
);
6713 TALLOC_FREE(smb_fname_dst
);
6717 /****************************************************************************
6718 Deal with SMB_SET_POSIX_ACL.
6719 ****************************************************************************/
6721 #if defined(HAVE_POSIX_ACLS)
6722 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6726 const struct smb_filename
*smb_fname
)
6728 uint16_t posix_acl_version
;
6729 uint16_t num_file_acls
;
6730 uint16_t num_def_acls
;
6731 bool valid_file_acls
= True
;
6732 bool valid_def_acls
= True
;
6734 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6735 return NT_STATUS_INVALID_PARAMETER
;
6737 posix_acl_version
= SVAL(pdata
,0);
6738 num_file_acls
= SVAL(pdata
,2);
6739 num_def_acls
= SVAL(pdata
,4);
6741 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6742 valid_file_acls
= False
;
6746 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6747 valid_def_acls
= False
;
6751 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6752 return NT_STATUS_INVALID_PARAMETER
;
6755 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6756 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6757 return NT_STATUS_INVALID_PARAMETER
;
6760 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6761 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6762 (unsigned int)num_file_acls
,
6763 (unsigned int)num_def_acls
));
6765 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6766 smb_fname
->base_name
, num_file_acls
,
6767 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6768 return map_nt_error_from_unix(errno
);
6771 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6772 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6773 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6774 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6775 return map_nt_error_from_unix(errno
);
6777 return NT_STATUS_OK
;
6781 /****************************************************************************
6782 Deal with SMB_SET_POSIX_LOCK.
6783 ****************************************************************************/
6785 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6786 struct smb_request
*req
,
6794 bool blocking_lock
= False
;
6795 enum brl_type lock_type
;
6797 NTSTATUS status
= NT_STATUS_OK
;
6799 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6800 return NT_STATUS_INVALID_HANDLE
;
6803 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6804 return NT_STATUS_INVALID_PARAMETER
;
6807 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6808 case POSIX_LOCK_TYPE_READ
:
6809 lock_type
= READ_LOCK
;
6811 case POSIX_LOCK_TYPE_WRITE
:
6812 /* Return the right POSIX-mappable error code for files opened read-only. */
6813 if (!fsp
->can_write
) {
6814 return NT_STATUS_INVALID_HANDLE
;
6816 lock_type
= WRITE_LOCK
;
6818 case POSIX_LOCK_TYPE_UNLOCK
:
6819 lock_type
= UNLOCK_LOCK
;
6822 return NT_STATUS_INVALID_PARAMETER
;
6825 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6826 blocking_lock
= False
;
6827 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6828 blocking_lock
= True
;
6830 return NT_STATUS_INVALID_PARAMETER
;
6833 if (!lp_blocking_locks(SNUM(conn
))) {
6834 blocking_lock
= False
;
6837 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6838 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6839 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6840 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6841 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6843 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6844 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6846 (unsigned int)lock_type
,
6847 (unsigned long long)smblctx
,
6851 if (lock_type
== UNLOCK_LOCK
) {
6852 status
= do_unlock(req
->sconn
->msg_ctx
,
6859 uint64_t block_smblctx
;
6861 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6872 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6874 * A blocking lock was requested. Package up
6875 * this smb into a queued request and push it
6876 * onto the blocking lock queue.
6878 if(push_blocking_lock_request(br_lck
,
6881 -1, /* infinite timeout. */
6889 TALLOC_FREE(br_lck
);
6893 TALLOC_FREE(br_lck
);
6899 /****************************************************************************
6900 Deal with SMB_SET_FILE_BASIC_INFO.
6901 ****************************************************************************/
6903 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6907 const struct smb_filename
*smb_fname
)
6909 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6910 struct smb_file_time ft
;
6911 uint32_t dosmode
= 0;
6912 NTSTATUS status
= NT_STATUS_OK
;
6916 if (total_data
< 36) {
6917 return NT_STATUS_INVALID_PARAMETER
;
6920 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6921 if (!NT_STATUS_IS_OK(status
)) {
6925 /* Set the attributes */
6926 dosmode
= IVAL(pdata
,32);
6927 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6928 if (!NT_STATUS_IS_OK(status
)) {
6933 ft
.create_time
= interpret_long_date(pdata
);
6936 ft
.atime
= interpret_long_date(pdata
+8);
6939 ft
.mtime
= interpret_long_date(pdata
+16);
6942 ft
.ctime
= interpret_long_date(pdata
+24);
6944 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6945 smb_fname_str_dbg(smb_fname
)));
6947 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6951 /****************************************************************************
6952 Deal with SMB_INFO_STANDARD.
6953 ****************************************************************************/
6955 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6959 const struct smb_filename
*smb_fname
)
6962 struct smb_file_time ft
;
6966 if (total_data
< 12) {
6967 return NT_STATUS_INVALID_PARAMETER
;
6971 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6973 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6975 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6977 DEBUG(10,("smb_set_info_standard: file %s\n",
6978 smb_fname_str_dbg(smb_fname
)));
6980 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6981 if (!NT_STATUS_IS_OK(status
)) {
6985 return smb_set_file_time(conn
,
6992 /****************************************************************************
6993 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6994 ****************************************************************************/
6996 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6997 struct smb_request
*req
,
7001 struct smb_filename
*smb_fname
)
7003 uint64_t allocation_size
= 0;
7004 NTSTATUS status
= NT_STATUS_OK
;
7005 files_struct
*new_fsp
= NULL
;
7007 if (!VALID_STAT(smb_fname
->st
)) {
7008 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7011 if (total_data
< 8) {
7012 return NT_STATUS_INVALID_PARAMETER
;
7015 allocation_size
= (uint64_t)IVAL(pdata
,0);
7016 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7017 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7018 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7019 (double)allocation_size
));
7021 if (allocation_size
) {
7022 allocation_size
= smb_roundup(conn
, allocation_size
);
7025 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7026 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7027 (double)allocation_size
));
7029 if (fsp
&& fsp
->fh
->fd
!= -1) {
7030 /* Open file handle. */
7031 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7032 return NT_STATUS_ACCESS_DENIED
;
7035 /* Only change if needed. */
7036 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7037 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7038 return map_nt_error_from_unix(errno
);
7041 /* But always update the time. */
7043 * This is equivalent to a write. Ensure it's seen immediately
7044 * if there are no pending writes.
7046 trigger_write_time_update_immediate(fsp
);
7047 return NT_STATUS_OK
;
7050 /* Pathname or stat or directory file. */
7051 status
= SMB_VFS_CREATE_FILE(
7054 0, /* root_dir_fid */
7055 smb_fname
, /* fname */
7056 FILE_WRITE_DATA
, /* access_mask */
7057 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7059 FILE_OPEN
, /* create_disposition*/
7060 0, /* create_options */
7061 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7062 0, /* oplock_request */
7064 0, /* allocation_size */
7065 0, /* private_flags */
7068 &new_fsp
, /* result */
7070 NULL
, NULL
); /* create context */
7072 if (!NT_STATUS_IS_OK(status
)) {
7073 /* NB. We check for open_was_deferred in the caller. */
7077 /* Only change if needed. */
7078 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7079 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7080 status
= map_nt_error_from_unix(errno
);
7081 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7086 /* Changing the allocation size should set the last mod time. */
7088 * This is equivalent to a write. Ensure it's seen immediately
7089 * if there are no pending writes.
7091 trigger_write_time_update_immediate(new_fsp
);
7092 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7093 return NT_STATUS_OK
;
7096 /****************************************************************************
7097 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7098 ****************************************************************************/
7100 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7101 struct smb_request
*req
,
7105 const struct smb_filename
*smb_fname
,
7106 bool fail_after_createfile
)
7110 if (total_data
< 8) {
7111 return NT_STATUS_INVALID_PARAMETER
;
7114 size
= IVAL(pdata
,0);
7115 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7116 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7117 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7120 return smb_set_file_size(conn
, req
,
7125 fail_after_createfile
);
7128 /****************************************************************************
7129 Allow a UNIX info mknod.
7130 ****************************************************************************/
7132 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7135 const struct smb_filename
*smb_fname
)
7137 uint32_t file_type
= IVAL(pdata
,56);
7138 #if defined(HAVE_MAKEDEV)
7139 uint32_t dev_major
= IVAL(pdata
,60);
7140 uint32_t dev_minor
= IVAL(pdata
,68);
7142 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7143 uint32_t raw_unixmode
= IVAL(pdata
,84);
7147 if (total_data
< 100) {
7148 return NT_STATUS_INVALID_PARAMETER
;
7151 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7152 PERM_NEW_FILE
, &unixmode
);
7153 if (!NT_STATUS_IS_OK(status
)) {
7157 #if defined(HAVE_MAKEDEV)
7158 dev
= makedev(dev_major
, dev_minor
);
7161 switch (file_type
) {
7162 #if defined(S_IFIFO)
7163 case UNIX_TYPE_FIFO
:
7164 unixmode
|= S_IFIFO
;
7167 #if defined(S_IFSOCK)
7168 case UNIX_TYPE_SOCKET
:
7169 unixmode
|= S_IFSOCK
;
7172 #if defined(S_IFCHR)
7173 case UNIX_TYPE_CHARDEV
:
7174 unixmode
|= S_IFCHR
;
7177 #if defined(S_IFBLK)
7178 case UNIX_TYPE_BLKDEV
:
7179 unixmode
|= S_IFBLK
;
7183 return NT_STATUS_INVALID_PARAMETER
;
7186 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7187 "%.0f mode 0%o for file %s\n", (double)dev
,
7188 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7190 /* Ok - do the mknod. */
7191 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7192 return map_nt_error_from_unix(errno
);
7195 /* If any of the other "set" calls fail we
7196 * don't want to end up with a half-constructed mknod.
7199 if (lp_inherit_permissions(SNUM(conn
))) {
7201 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7203 return NT_STATUS_NO_MEMORY
;
7205 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7207 TALLOC_FREE(parent
);
7210 return NT_STATUS_OK
;
7213 /****************************************************************************
7214 Deal with SMB_SET_FILE_UNIX_BASIC.
7215 ****************************************************************************/
7217 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7218 struct smb_request
*req
,
7222 const struct smb_filename
*smb_fname
)
7224 struct smb_file_time ft
;
7225 uint32_t raw_unixmode
;
7228 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7229 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7230 NTSTATUS status
= NT_STATUS_OK
;
7231 bool delete_on_fail
= False
;
7232 enum perm_type ptype
;
7233 files_struct
*all_fsps
= NULL
;
7234 bool modify_mtime
= true;
7236 struct smb_filename
*smb_fname_tmp
= NULL
;
7237 SMB_STRUCT_STAT sbuf
;
7241 if (total_data
< 100) {
7242 return NT_STATUS_INVALID_PARAMETER
;
7245 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7246 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7247 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7248 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7251 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7252 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7253 set_owner
= (uid_t
)IVAL(pdata
,40);
7254 set_grp
= (gid_t
)IVAL(pdata
,48);
7255 raw_unixmode
= IVAL(pdata
,84);
7257 if (VALID_STAT(smb_fname
->st
)) {
7258 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7259 ptype
= PERM_EXISTING_DIR
;
7261 ptype
= PERM_EXISTING_FILE
;
7264 ptype
= PERM_NEW_FILE
;
7267 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7269 if (!NT_STATUS_IS_OK(status
)) {
7273 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7274 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7275 smb_fname_str_dbg(smb_fname
), (double)size
,
7276 (unsigned int)set_owner
, (unsigned int)set_grp
,
7277 (int)raw_unixmode
));
7279 sbuf
= smb_fname
->st
;
7281 if (!VALID_STAT(sbuf
)) {
7283 * The only valid use of this is to create character and block
7284 * devices, and named pipes. This is deprecated (IMHO) and
7285 * a new info level should be used for mknod. JRA.
7288 status
= smb_unix_mknod(conn
,
7292 if (!NT_STATUS_IS_OK(status
)) {
7296 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7297 if (smb_fname_tmp
== NULL
) {
7298 return NT_STATUS_NO_MEMORY
;
7301 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7302 status
= map_nt_error_from_unix(errno
);
7303 TALLOC_FREE(smb_fname_tmp
);
7304 SMB_VFS_UNLINK(conn
, smb_fname
);
7308 sbuf
= smb_fname_tmp
->st
;
7309 smb_fname
= smb_fname_tmp
;
7311 /* Ensure we don't try and change anything else. */
7312 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7313 size
= get_file_size_stat(&sbuf
);
7314 ft
.atime
= sbuf
.st_ex_atime
;
7315 ft
.mtime
= sbuf
.st_ex_mtime
;
7317 * We continue here as we might want to change the
7320 delete_on_fail
= True
;
7324 /* Horrible backwards compatibility hack as an old server bug
7325 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7329 size
= get_file_size_stat(&sbuf
);
7334 * Deal with the UNIX specific mode set.
7337 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7340 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7341 "setting mode 0%o for file %s\n",
7342 (unsigned int)unixmode
,
7343 smb_fname_str_dbg(smb_fname
)));
7344 if (fsp
&& fsp
->fh
->fd
!= -1) {
7345 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7347 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7350 return map_nt_error_from_unix(errno
);
7355 * Deal with the UNIX specific uid set.
7358 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7359 (sbuf
.st_ex_uid
!= set_owner
)) {
7362 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7363 "changing owner %u for path %s\n",
7364 (unsigned int)set_owner
,
7365 smb_fname_str_dbg(smb_fname
)));
7367 if (fsp
&& fsp
->fh
->fd
!= -1) {
7368 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7371 * UNIX extensions calls must always operate
7374 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7375 set_owner
, (gid_t
)-1);
7379 status
= map_nt_error_from_unix(errno
);
7380 if (delete_on_fail
) {
7381 SMB_VFS_UNLINK(conn
, smb_fname
);
7388 * Deal with the UNIX specific gid set.
7391 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7392 (sbuf
.st_ex_gid
!= set_grp
)) {
7395 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7396 "changing group %u for file %s\n",
7397 (unsigned int)set_owner
,
7398 smb_fname_str_dbg(smb_fname
)));
7399 if (fsp
&& fsp
->fh
->fd
!= -1) {
7400 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7403 * UNIX extensions calls must always operate
7406 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7410 status
= map_nt_error_from_unix(errno
);
7411 if (delete_on_fail
) {
7412 SMB_VFS_UNLINK(conn
, smb_fname
);
7418 /* Deal with any size changes. */
7420 status
= smb_set_file_size(conn
, req
,
7426 if (!NT_STATUS_IS_OK(status
)) {
7430 /* Deal with any time changes. */
7431 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7432 /* No change, don't cancel anything. */
7436 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7437 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7438 all_fsps
= file_find_di_next(all_fsps
)) {
7440 * We're setting the time explicitly for UNIX.
7441 * Cancel any pending changes over all handles.
7443 all_fsps
->update_write_time_on_close
= false;
7444 TALLOC_FREE(all_fsps
->update_write_time_event
);
7448 * Override the "setting_write_time"
7449 * parameter here as it almost does what
7450 * we need. Just remember if we modified
7451 * mtime and send the notify ourselves.
7453 if (null_timespec(ft
.mtime
)) {
7454 modify_mtime
= false;
7457 status
= smb_set_file_time(conn
,
7463 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7464 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7469 /****************************************************************************
7470 Deal with SMB_SET_FILE_UNIX_INFO2.
7471 ****************************************************************************/
7473 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7474 struct smb_request
*req
,
7478 const struct smb_filename
*smb_fname
)
7481 uint32_t smb_fflags
;
7484 if (total_data
< 116) {
7485 return NT_STATUS_INVALID_PARAMETER
;
7488 /* Start by setting all the fields that are common between UNIX_BASIC
7491 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7493 if (!NT_STATUS_IS_OK(status
)) {
7497 smb_fflags
= IVAL(pdata
, 108);
7498 smb_fmask
= IVAL(pdata
, 112);
7500 /* NB: We should only attempt to alter the file flags if the client
7501 * sends a non-zero mask.
7503 if (smb_fmask
!= 0) {
7504 int stat_fflags
= 0;
7506 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7507 smb_fmask
, &stat_fflags
)) {
7508 /* Client asked to alter a flag we don't understand. */
7509 return NT_STATUS_INVALID_PARAMETER
;
7512 if (fsp
&& fsp
->fh
->fd
!= -1) {
7513 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7514 return NT_STATUS_NOT_SUPPORTED
;
7516 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7517 stat_fflags
) != 0) {
7518 return map_nt_error_from_unix(errno
);
7523 /* XXX: need to add support for changing the create_time here. You
7524 * can do this for paths on Darwin with setattrlist(2). The right way
7525 * to hook this up is probably by extending the VFS utimes interface.
7528 return NT_STATUS_OK
;
7531 /****************************************************************************
7532 Create a directory with POSIX semantics.
7533 ****************************************************************************/
7535 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7536 struct smb_request
*req
,
7539 struct smb_filename
*smb_fname
,
7540 int *pdata_return_size
)
7542 NTSTATUS status
= NT_STATUS_OK
;
7543 uint32_t raw_unixmode
= 0;
7544 uint32_t mod_unixmode
= 0;
7545 mode_t unixmode
= (mode_t
)0;
7546 files_struct
*fsp
= NULL
;
7547 uint16_t info_level_return
= 0;
7549 char *pdata
= *ppdata
;
7551 if (total_data
< 18) {
7552 return NT_STATUS_INVALID_PARAMETER
;
7555 raw_unixmode
= IVAL(pdata
,8);
7556 /* Next 4 bytes are not yet defined. */
7558 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7559 PERM_NEW_DIR
, &unixmode
);
7560 if (!NT_STATUS_IS_OK(status
)) {
7564 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7566 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7567 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7569 status
= SMB_VFS_CREATE_FILE(
7572 0, /* root_dir_fid */
7573 smb_fname
, /* fname */
7574 FILE_READ_ATTRIBUTES
, /* access_mask */
7575 FILE_SHARE_NONE
, /* share_access */
7576 FILE_CREATE
, /* create_disposition*/
7577 FILE_DIRECTORY_FILE
, /* create_options */
7578 mod_unixmode
, /* file_attributes */
7579 0, /* oplock_request */
7581 0, /* allocation_size */
7582 0, /* private_flags */
7587 NULL
, NULL
); /* create context */
7589 if (NT_STATUS_IS_OK(status
)) {
7590 close_file(req
, fsp
, NORMAL_CLOSE
);
7593 info_level_return
= SVAL(pdata
,16);
7595 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7596 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7597 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7598 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7600 *pdata_return_size
= 12;
7603 /* Realloc the data size */
7604 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7605 if (*ppdata
== NULL
) {
7606 *pdata_return_size
= 0;
7607 return NT_STATUS_NO_MEMORY
;
7611 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7612 SSVAL(pdata
,2,0); /* No fnum. */
7613 SIVAL(pdata
,4,info
); /* Was directory created. */
7615 switch (info_level_return
) {
7616 case SMB_QUERY_FILE_UNIX_BASIC
:
7617 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7618 SSVAL(pdata
,10,0); /* Padding. */
7619 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7622 case SMB_QUERY_FILE_UNIX_INFO2
:
7623 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7624 SSVAL(pdata
,10,0); /* Padding. */
7625 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7629 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7630 SSVAL(pdata
,10,0); /* Padding. */
7637 /****************************************************************************
7638 Open/Create a file with POSIX semantics.
7639 ****************************************************************************/
7641 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7642 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7644 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7645 struct smb_request
*req
,
7648 struct smb_filename
*smb_fname
,
7649 int *pdata_return_size
)
7651 bool extended_oplock_granted
= False
;
7652 char *pdata
= *ppdata
;
7654 uint32_t wire_open_mode
= 0;
7655 uint32_t raw_unixmode
= 0;
7656 uint32_t mod_unixmode
= 0;
7657 uint32_t create_disp
= 0;
7658 uint32_t access_mask
= 0;
7659 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7660 NTSTATUS status
= NT_STATUS_OK
;
7661 mode_t unixmode
= (mode_t
)0;
7662 files_struct
*fsp
= NULL
;
7663 int oplock_request
= 0;
7665 uint16_t info_level_return
= 0;
7667 if (total_data
< 18) {
7668 return NT_STATUS_INVALID_PARAMETER
;
7671 flags
= IVAL(pdata
,0);
7672 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7673 if (oplock_request
) {
7674 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7677 wire_open_mode
= IVAL(pdata
,4);
7679 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7680 return smb_posix_mkdir(conn
, req
,
7687 switch (wire_open_mode
& SMB_ACCMODE
) {
7689 access_mask
= SMB_O_RDONLY_MAPPING
;
7692 access_mask
= SMB_O_WRONLY_MAPPING
;
7695 access_mask
= (SMB_O_RDONLY_MAPPING
|
7696 SMB_O_WRONLY_MAPPING
);
7699 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7700 (unsigned int)wire_open_mode
));
7701 return NT_STATUS_INVALID_PARAMETER
;
7704 wire_open_mode
&= ~SMB_ACCMODE
;
7706 /* First take care of O_CREAT|O_EXCL interactions. */
7707 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7708 case (SMB_O_CREAT
| SMB_O_EXCL
):
7709 /* File exists fail. File not exist create. */
7710 create_disp
= FILE_CREATE
;
7713 /* File exists open. File not exist create. */
7714 create_disp
= FILE_OPEN_IF
;
7717 /* O_EXCL on its own without O_CREAT is undefined.
7718 We deliberately ignore it as some versions of
7719 Linux CIFSFS can send a bare O_EXCL on the
7720 wire which other filesystems in the kernel
7721 ignore. See bug 9519 for details. */
7726 /* File exists open. File not exist fail. */
7727 create_disp
= FILE_OPEN
;
7730 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7731 (unsigned int)wire_open_mode
));
7732 return NT_STATUS_INVALID_PARAMETER
;
7735 /* Next factor in the effects of O_TRUNC. */
7736 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7738 if (wire_open_mode
& SMB_O_TRUNC
) {
7739 switch (create_disp
) {
7741 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7742 /* Leave create_disp alone as
7743 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7745 /* File exists fail. File not exist create. */
7748 /* SMB_O_CREAT | SMB_O_TRUNC */
7749 /* File exists overwrite. File not exist create. */
7750 create_disp
= FILE_OVERWRITE_IF
;
7754 /* File exists overwrite. File not exist fail. */
7755 create_disp
= FILE_OVERWRITE
;
7758 /* Cannot get here. */
7759 smb_panic("smb_posix_open: logic error");
7760 return NT_STATUS_INVALID_PARAMETER
;
7764 raw_unixmode
= IVAL(pdata
,8);
7765 /* Next 4 bytes are not yet defined. */
7767 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7768 (VALID_STAT(smb_fname
->st
) ?
7769 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7772 if (!NT_STATUS_IS_OK(status
)) {
7776 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7778 if (wire_open_mode
& SMB_O_SYNC
) {
7779 create_options
|= FILE_WRITE_THROUGH
;
7781 if (wire_open_mode
& SMB_O_APPEND
) {
7782 access_mask
|= FILE_APPEND_DATA
;
7784 if (wire_open_mode
& SMB_O_DIRECT
) {
7785 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7788 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7789 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7790 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7791 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7793 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7794 create_options
|= FILE_DIRECTORY_FILE
;
7797 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7798 smb_fname_str_dbg(smb_fname
),
7799 (unsigned int)wire_open_mode
,
7800 (unsigned int)unixmode
));
7802 status
= SMB_VFS_CREATE_FILE(
7805 0, /* root_dir_fid */
7806 smb_fname
, /* fname */
7807 access_mask
, /* access_mask */
7808 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7810 create_disp
, /* create_disposition*/
7811 create_options
, /* create_options */
7812 mod_unixmode
, /* file_attributes */
7813 oplock_request
, /* oplock_request */
7815 0, /* allocation_size */
7816 0, /* private_flags */
7821 NULL
, NULL
); /* create context */
7823 if (!NT_STATUS_IS_OK(status
)) {
7827 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7828 extended_oplock_granted
= True
;
7831 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7832 extended_oplock_granted
= True
;
7835 info_level_return
= SVAL(pdata
,16);
7837 /* Allocate the correct return size. */
7839 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7840 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7841 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7842 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7844 *pdata_return_size
= 12;
7847 /* Realloc the data size */
7848 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7849 if (*ppdata
== NULL
) {
7850 close_file(req
, fsp
, ERROR_CLOSE
);
7851 *pdata_return_size
= 0;
7852 return NT_STATUS_NO_MEMORY
;
7856 if (extended_oplock_granted
) {
7857 if (flags
& REQUEST_BATCH_OPLOCK
) {
7858 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7860 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7862 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7863 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7865 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7868 SSVAL(pdata
,2,fsp
->fnum
);
7869 SIVAL(pdata
,4,info
); /* Was file created etc. */
7871 switch (info_level_return
) {
7872 case SMB_QUERY_FILE_UNIX_BASIC
:
7873 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7874 SSVAL(pdata
,10,0); /* padding. */
7875 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7878 case SMB_QUERY_FILE_UNIX_INFO2
:
7879 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7880 SSVAL(pdata
,10,0); /* padding. */
7881 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7885 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7886 SSVAL(pdata
,10,0); /* padding. */
7889 return NT_STATUS_OK
;
7892 /****************************************************************************
7893 Delete a file with POSIX semantics.
7894 ****************************************************************************/
7896 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7897 struct smb_request
*req
,
7900 struct smb_filename
*smb_fname
)
7902 NTSTATUS status
= NT_STATUS_OK
;
7903 files_struct
*fsp
= NULL
;
7907 int create_options
= 0;
7909 struct share_mode_lock
*lck
= NULL
;
7911 if (total_data
< 2) {
7912 return NT_STATUS_INVALID_PARAMETER
;
7915 flags
= SVAL(pdata
,0);
7917 if (!VALID_STAT(smb_fname
->st
)) {
7918 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7921 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7922 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7923 return NT_STATUS_NOT_A_DIRECTORY
;
7926 DEBUG(10,("smb_posix_unlink: %s %s\n",
7927 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7928 smb_fname_str_dbg(smb_fname
)));
7930 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7931 create_options
|= FILE_DIRECTORY_FILE
;
7934 status
= SMB_VFS_CREATE_FILE(
7937 0, /* root_dir_fid */
7938 smb_fname
, /* fname */
7939 DELETE_ACCESS
, /* access_mask */
7940 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7942 FILE_OPEN
, /* create_disposition*/
7943 create_options
, /* create_options */
7944 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7945 0, /* oplock_request */
7947 0, /* allocation_size */
7948 0, /* private_flags */
7953 NULL
, NULL
); /* create context */
7955 if (!NT_STATUS_IS_OK(status
)) {
7960 * Don't lie to client. If we can't really delete due to
7961 * non-POSIX opens return SHARING_VIOLATION.
7964 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7966 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7967 "lock for file %s\n", fsp_str_dbg(fsp
)));
7968 close_file(req
, fsp
, NORMAL_CLOSE
);
7969 return NT_STATUS_INVALID_PARAMETER
;
7973 * See if others still have the file open. If this is the case, then
7974 * don't delete. If all opens are POSIX delete we can set the delete
7975 * on close disposition.
7977 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7978 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7979 if (is_valid_share_mode_entry(e
)) {
7980 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7983 if (share_mode_stale_pid(lck
->data
, i
)) {
7986 /* Fail with sharing violation. */
7988 close_file(req
, fsp
, NORMAL_CLOSE
);
7989 return NT_STATUS_SHARING_VIOLATION
;
7994 * Set the delete on close.
7996 status
= smb_set_file_disposition_info(conn
,
8004 if (!NT_STATUS_IS_OK(status
)) {
8005 close_file(req
, fsp
, NORMAL_CLOSE
);
8008 return close_file(req
, fsp
, NORMAL_CLOSE
);
8011 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8012 struct smb_request
*req
,
8013 TALLOC_CTX
*mem_ctx
,
8014 uint16_t info_level
,
8016 struct smb_filename
*smb_fname
,
8017 char **ppdata
, int total_data
,
8020 char *pdata
= *ppdata
;
8021 NTSTATUS status
= NT_STATUS_OK
;
8022 int data_return_size
= 0;
8026 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8027 return NT_STATUS_INVALID_LEVEL
;
8030 if (!CAN_WRITE(conn
)) {
8031 /* Allow POSIX opens. The open path will deny
8032 * any non-readonly opens. */
8033 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8034 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8038 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8039 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8041 info_level
, total_data
));
8043 switch (info_level
) {
8045 case SMB_INFO_STANDARD
:
8047 status
= smb_set_info_standard(conn
,
8055 case SMB_INFO_SET_EA
:
8057 status
= smb_info_set_ea(conn
,
8065 case SMB_SET_FILE_BASIC_INFO
:
8066 case SMB_FILE_BASIC_INFORMATION
:
8068 status
= smb_set_file_basic_info(conn
,
8076 case SMB_FILE_ALLOCATION_INFORMATION
:
8077 case SMB_SET_FILE_ALLOCATION_INFO
:
8079 status
= smb_set_file_allocation_info(conn
, req
,
8087 case SMB_FILE_END_OF_FILE_INFORMATION
:
8088 case SMB_SET_FILE_END_OF_FILE_INFO
:
8091 * XP/Win7 both fail after the createfile with
8092 * SMB_SET_FILE_END_OF_FILE_INFO but not
8093 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8094 * The level is known here, so pass it down
8098 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8100 status
= smb_set_file_end_of_file_info(conn
, req
,
8109 case SMB_FILE_DISPOSITION_INFORMATION
:
8110 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8113 /* JRA - We used to just ignore this on a path ?
8114 * Shouldn't this be invalid level on a pathname
8117 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8118 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8121 status
= smb_set_file_disposition_info(conn
,
8129 case SMB_FILE_POSITION_INFORMATION
:
8131 status
= smb_file_position_information(conn
,
8138 case SMB_FILE_FULL_EA_INFORMATION
:
8140 status
= smb_set_file_full_ea_info(conn
,
8147 /* From tridge Samba4 :
8148 * MODE_INFORMATION in setfileinfo (I have no
8149 * idea what "mode information" on a file is - it takes a value of 0,
8150 * 2, 4 or 6. What could it be?).
8153 case SMB_FILE_MODE_INFORMATION
:
8155 status
= smb_file_mode_information(conn
,
8162 * CIFS UNIX extensions.
8165 case SMB_SET_FILE_UNIX_BASIC
:
8167 status
= smb_set_file_unix_basic(conn
, req
,
8175 case SMB_SET_FILE_UNIX_INFO2
:
8177 status
= smb_set_file_unix_info2(conn
, req
,
8185 case SMB_SET_FILE_UNIX_LINK
:
8188 /* We must have a pathname for this. */
8189 return NT_STATUS_INVALID_LEVEL
;
8191 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8192 total_data
, smb_fname
);
8196 case SMB_SET_FILE_UNIX_HLINK
:
8199 /* We must have a pathname for this. */
8200 return NT_STATUS_INVALID_LEVEL
;
8202 status
= smb_set_file_unix_hlink(conn
, req
,
8208 case SMB_FILE_RENAME_INFORMATION
:
8210 status
= smb_file_rename_information(conn
, req
,
8216 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8218 /* SMB2 rename information. */
8219 status
= smb2_file_rename_information(conn
, req
,
8225 case SMB_FILE_LINK_INFORMATION
:
8227 status
= smb_file_link_information(conn
, req
,
8233 #if defined(HAVE_POSIX_ACLS)
8234 case SMB_SET_POSIX_ACL
:
8236 status
= smb_set_posix_acl(conn
,
8245 case SMB_SET_POSIX_LOCK
:
8248 return NT_STATUS_INVALID_LEVEL
;
8250 status
= smb_set_posix_lock(conn
, req
,
8251 pdata
, total_data
, fsp
);
8255 case SMB_POSIX_PATH_OPEN
:
8258 /* We must have a pathname for this. */
8259 return NT_STATUS_INVALID_LEVEL
;
8262 status
= smb_posix_open(conn
, req
,
8270 case SMB_POSIX_PATH_UNLINK
:
8273 /* We must have a pathname for this. */
8274 return NT_STATUS_INVALID_LEVEL
;
8277 status
= smb_posix_unlink(conn
, req
,
8285 return NT_STATUS_INVALID_LEVEL
;
8288 if (!NT_STATUS_IS_OK(status
)) {
8292 *ret_data_size
= data_return_size
;
8293 return NT_STATUS_OK
;
8296 /****************************************************************************
8297 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8298 ****************************************************************************/
8300 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8301 struct smb_request
*req
,
8302 unsigned int tran_call
,
8303 char **pparams
, int total_params
,
8304 char **ppdata
, int total_data
,
8305 unsigned int max_data_bytes
)
8307 char *params
= *pparams
;
8308 char *pdata
= *ppdata
;
8309 uint16_t info_level
;
8310 struct smb_filename
*smb_fname
= NULL
;
8311 files_struct
*fsp
= NULL
;
8312 NTSTATUS status
= NT_STATUS_OK
;
8313 int data_return_size
= 0;
8316 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8320 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8321 if (total_params
< 4) {
8322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8326 fsp
= file_fsp(req
, SVAL(params
,0));
8327 /* Basic check for non-null fsp. */
8328 if (!check_fsp_open(conn
, req
, fsp
)) {
8331 info_level
= SVAL(params
,2);
8333 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8334 if (smb_fname
== NULL
) {
8335 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8339 if(fsp
->fh
->fd
== -1) {
8341 * This is actually a SETFILEINFO on a directory
8342 * handle (returned from an NT SMB). NT5.0 seems
8343 * to do this call. JRA.
8345 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8346 /* Always do lstat for UNIX calls. */
8347 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8348 DEBUG(3,("call_trans2setfilepathinfo: "
8349 "SMB_VFS_LSTAT of %s failed "
8351 smb_fname_str_dbg(smb_fname
),
8353 reply_nterror(req
, map_nt_error_from_unix(errno
));
8357 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8358 DEBUG(3,("call_trans2setfilepathinfo: "
8359 "fileinfo of %s failed (%s)\n",
8360 smb_fname_str_dbg(smb_fname
),
8362 reply_nterror(req
, map_nt_error_from_unix(errno
));
8366 } else if (fsp
->print_file
) {
8368 * Doing a DELETE_ON_CLOSE should cancel a print job.
8370 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8371 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8373 DEBUG(3,("call_trans2setfilepathinfo: "
8374 "Cancelling print job (%s)\n",
8378 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8384 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8389 * Original code - this is an open file.
8391 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8392 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8393 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8395 reply_nterror(req
, map_nt_error_from_unix(errno
));
8401 uint32_t ucf_flags
= 0;
8404 if (total_params
< 7) {
8405 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8409 info_level
= SVAL(params
,0);
8410 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8411 total_params
- 6, STR_TERMINATE
,
8413 if (!NT_STATUS_IS_OK(status
)) {
8414 reply_nterror(req
, status
);
8418 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8419 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8420 info_level
== SMB_FILE_RENAME_INFORMATION
||
8421 info_level
== SMB_POSIX_PATH_UNLINK
) {
8422 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8425 status
= filename_convert(req
, conn
,
8426 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8431 if (!NT_STATUS_IS_OK(status
)) {
8432 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8433 reply_botherror(req
,
8434 NT_STATUS_PATH_NOT_COVERED
,
8435 ERRSRV
, ERRbadpath
);
8438 reply_nterror(req
, status
);
8442 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8444 * For CIFS UNIX extensions the target name may not exist.
8447 /* Always do lstat for UNIX calls. */
8448 SMB_VFS_LSTAT(conn
, smb_fname
);
8450 } else if (!VALID_STAT(smb_fname
->st
) &&
8451 SMB_VFS_STAT(conn
, smb_fname
)) {
8452 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8454 smb_fname_str_dbg(smb_fname
),
8456 reply_nterror(req
, map_nt_error_from_unix(errno
));
8461 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8462 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8464 info_level
,total_data
));
8466 /* Realloc the parameter size */
8467 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8468 if (*pparams
== NULL
) {
8469 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8476 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8482 if (!NT_STATUS_IS_OK(status
)) {
8483 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8484 /* We have re-scheduled this call. */
8487 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8488 /* We have re-scheduled this call. */
8491 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8492 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8493 ERRSRV
, ERRbadpath
);
8496 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8497 reply_openerror(req
, status
);
8502 * Invalid EA name needs to return 2 param bytes,
8503 * not a zero-length error packet.
8505 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8506 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8509 reply_nterror(req
, status
);
8514 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8520 /****************************************************************************
8521 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8522 ****************************************************************************/
8524 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8525 char **pparams
, int total_params
,
8526 char **ppdata
, int total_data
,
8527 unsigned int max_data_bytes
)
8529 struct smb_filename
*smb_dname
= NULL
;
8530 char *params
= *pparams
;
8531 char *pdata
= *ppdata
;
8532 char *directory
= NULL
;
8533 NTSTATUS status
= NT_STATUS_OK
;
8534 struct ea_list
*ea_list
= NULL
;
8535 TALLOC_CTX
*ctx
= talloc_tos();
8537 if (!CAN_WRITE(conn
)) {
8538 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8542 if (total_params
< 5) {
8543 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8547 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8548 total_params
- 4, STR_TERMINATE
,
8550 if (!NT_STATUS_IS_OK(status
)) {
8551 reply_nterror(req
, status
);
8555 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8557 status
= filename_convert(ctx
,
8559 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8565 if (!NT_STATUS_IS_OK(status
)) {
8566 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8567 reply_botherror(req
,
8568 NT_STATUS_PATH_NOT_COVERED
,
8569 ERRSRV
, ERRbadpath
);
8572 reply_nterror(req
, status
);
8577 * OS/2 workplace shell seems to send SET_EA requests of "null"
8578 * length (4 bytes containing IVAL 4).
8579 * They seem to have no effect. Bug #3212. JRA.
8582 if (total_data
&& (total_data
!= 4)) {
8583 /* Any data in this call is an EA list. */
8584 if (total_data
< 10) {
8585 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8589 if (IVAL(pdata
,0) > total_data
) {
8590 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8591 IVAL(pdata
,0), (unsigned int)total_data
));
8592 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8596 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8599 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8603 if (!lp_ea_support(SNUM(conn
))) {
8604 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8608 /* If total_data == 4 Windows doesn't care what values
8609 * are placed in that field, it just ignores them.
8610 * The System i QNTC IBM SMB client puts bad values here,
8611 * so ignore them. */
8613 status
= create_directory(conn
, req
, smb_dname
);
8615 if (!NT_STATUS_IS_OK(status
)) {
8616 reply_nterror(req
, status
);
8620 /* Try and set any given EA. */
8622 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8623 if (!NT_STATUS_IS_OK(status
)) {
8624 reply_nterror(req
, status
);
8629 /* Realloc the parameter and data sizes */
8630 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8631 if(*pparams
== NULL
) {
8632 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8639 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8642 TALLOC_FREE(smb_dname
);
8646 /****************************************************************************
8647 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8648 We don't actually do this - we just send a null response.
8649 ****************************************************************************/
8651 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8652 struct smb_request
*req
,
8653 char **pparams
, int total_params
,
8654 char **ppdata
, int total_data
,
8655 unsigned int max_data_bytes
)
8657 char *params
= *pparams
;
8658 uint16_t info_level
;
8660 if (total_params
< 6) {
8661 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8665 info_level
= SVAL(params
,4);
8666 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8668 switch (info_level
) {
8673 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8677 /* Realloc the parameter and data sizes */
8678 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8679 if (*pparams
== NULL
) {
8680 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8685 SSVAL(params
,0,fnf_handle
);
8686 SSVAL(params
,2,0); /* No changes */
8687 SSVAL(params
,4,0); /* No EA errors */
8694 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8699 /****************************************************************************
8700 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8701 changes). Currently this does nothing.
8702 ****************************************************************************/
8704 static void call_trans2findnotifynext(connection_struct
*conn
,
8705 struct smb_request
*req
,
8706 char **pparams
, int total_params
,
8707 char **ppdata
, int total_data
,
8708 unsigned int max_data_bytes
)
8710 char *params
= *pparams
;
8712 DEBUG(3,("call_trans2findnotifynext\n"));
8714 /* Realloc the parameter and data sizes */
8715 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8716 if (*pparams
== NULL
) {
8717 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8722 SSVAL(params
,0,0); /* No changes */
8723 SSVAL(params
,2,0); /* No EA errors */
8725 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8730 /****************************************************************************
8731 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8732 ****************************************************************************/
8734 static void call_trans2getdfsreferral(connection_struct
*conn
,
8735 struct smb_request
*req
,
8736 char **pparams
, int total_params
,
8737 char **ppdata
, int total_data
,
8738 unsigned int max_data_bytes
)
8740 char *params
= *pparams
;
8741 char *pathname
= NULL
;
8743 int max_referral_level
;
8744 NTSTATUS status
= NT_STATUS_OK
;
8745 TALLOC_CTX
*ctx
= talloc_tos();
8747 DEBUG(10,("call_trans2getdfsreferral\n"));
8749 if (total_params
< 3) {
8750 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8754 max_referral_level
= SVAL(params
,0);
8756 if(!lp_host_msdfs()) {
8757 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8761 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8762 total_params
- 2, STR_TERMINATE
);
8764 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8767 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8768 ppdata
,&status
)) < 0) {
8769 reply_nterror(req
, status
);
8773 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8774 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8775 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8780 #define LMCAT_SPL 0x53
8781 #define LMFUNC_GETJOBID 0x60
8783 /****************************************************************************
8784 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8785 ****************************************************************************/
8787 static void call_trans2ioctl(connection_struct
*conn
,
8788 struct smb_request
*req
,
8789 char **pparams
, int total_params
,
8790 char **ppdata
, int total_data
,
8791 unsigned int max_data_bytes
)
8793 char *pdata
= *ppdata
;
8794 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8798 /* check for an invalid fid before proceeding */
8801 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8805 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8806 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8807 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8808 if (*ppdata
== NULL
) {
8809 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8814 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8815 CAN ACCEPT THIS IN UNICODE. JRA. */
8818 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8820 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8821 lp_netbios_name(), 15,
8822 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8823 if (!NT_STATUS_IS_OK(status
)) {
8824 reply_nterror(req
, status
);
8827 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8828 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8829 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8830 if (!NT_STATUS_IS_OK(status
)) {
8831 reply_nterror(req
, status
);
8834 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8839 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8840 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8843 /****************************************************************************
8844 Reply to a SMBfindclose (stop trans2 directory search).
8845 ****************************************************************************/
8847 void reply_findclose(struct smb_request
*req
)
8850 struct smbd_server_connection
*sconn
= req
->sconn
;
8852 START_PROFILE(SMBfindclose
);
8855 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8856 END_PROFILE(SMBfindclose
);
8860 dptr_num
= SVALS(req
->vwv
+0, 0);
8862 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8864 dptr_close(sconn
, &dptr_num
);
8866 reply_outbuf(req
, 0, 0);
8868 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8870 END_PROFILE(SMBfindclose
);
8874 /****************************************************************************
8875 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8876 ****************************************************************************/
8878 void reply_findnclose(struct smb_request
*req
)
8882 START_PROFILE(SMBfindnclose
);
8885 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8886 END_PROFILE(SMBfindnclose
);
8890 dptr_num
= SVAL(req
->vwv
+0, 0);
8892 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8894 /* We never give out valid handles for a
8895 findnotifyfirst - so any dptr_num is ok here.
8898 reply_outbuf(req
, 0, 0);
8900 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8902 END_PROFILE(SMBfindnclose
);
8906 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8907 struct trans_state
*state
)
8909 if (get_Protocol() >= PROTOCOL_NT1
) {
8910 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8911 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8914 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8915 if (state
->call
!= TRANSACT2_QFSINFO
&&
8916 state
->call
!= TRANSACT2_SETFSINFO
) {
8917 DEBUG(0,("handle_trans2: encryption required "
8919 (unsigned int)state
->call
));
8920 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8925 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8927 /* Now we must call the relevant TRANS2 function */
8928 switch(state
->call
) {
8929 case TRANSACT2_OPEN
:
8931 START_PROFILE(Trans2_open
);
8932 call_trans2open(conn
, req
,
8933 &state
->param
, state
->total_param
,
8934 &state
->data
, state
->total_data
,
8935 state
->max_data_return
);
8936 END_PROFILE(Trans2_open
);
8940 case TRANSACT2_FINDFIRST
:
8942 START_PROFILE(Trans2_findfirst
);
8943 call_trans2findfirst(conn
, req
,
8944 &state
->param
, state
->total_param
,
8945 &state
->data
, state
->total_data
,
8946 state
->max_data_return
);
8947 END_PROFILE(Trans2_findfirst
);
8951 case TRANSACT2_FINDNEXT
:
8953 START_PROFILE(Trans2_findnext
);
8954 call_trans2findnext(conn
, req
,
8955 &state
->param
, state
->total_param
,
8956 &state
->data
, state
->total_data
,
8957 state
->max_data_return
);
8958 END_PROFILE(Trans2_findnext
);
8962 case TRANSACT2_QFSINFO
:
8964 START_PROFILE(Trans2_qfsinfo
);
8965 call_trans2qfsinfo(conn
, req
,
8966 &state
->param
, state
->total_param
,
8967 &state
->data
, state
->total_data
,
8968 state
->max_data_return
);
8969 END_PROFILE(Trans2_qfsinfo
);
8973 case TRANSACT2_SETFSINFO
:
8975 START_PROFILE(Trans2_setfsinfo
);
8976 call_trans2setfsinfo(conn
, req
,
8977 &state
->param
, state
->total_param
,
8978 &state
->data
, state
->total_data
,
8979 state
->max_data_return
);
8980 END_PROFILE(Trans2_setfsinfo
);
8984 case TRANSACT2_QPATHINFO
:
8985 case TRANSACT2_QFILEINFO
:
8987 START_PROFILE(Trans2_qpathinfo
);
8988 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8989 &state
->param
, state
->total_param
,
8990 &state
->data
, state
->total_data
,
8991 state
->max_data_return
);
8992 END_PROFILE(Trans2_qpathinfo
);
8996 case TRANSACT2_SETPATHINFO
:
8997 case TRANSACT2_SETFILEINFO
:
8999 START_PROFILE(Trans2_setpathinfo
);
9000 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9001 &state
->param
, state
->total_param
,
9002 &state
->data
, state
->total_data
,
9003 state
->max_data_return
);
9004 END_PROFILE(Trans2_setpathinfo
);
9008 case TRANSACT2_FINDNOTIFYFIRST
:
9010 START_PROFILE(Trans2_findnotifyfirst
);
9011 call_trans2findnotifyfirst(conn
, req
,
9012 &state
->param
, state
->total_param
,
9013 &state
->data
, state
->total_data
,
9014 state
->max_data_return
);
9015 END_PROFILE(Trans2_findnotifyfirst
);
9019 case TRANSACT2_FINDNOTIFYNEXT
:
9021 START_PROFILE(Trans2_findnotifynext
);
9022 call_trans2findnotifynext(conn
, req
,
9023 &state
->param
, state
->total_param
,
9024 &state
->data
, state
->total_data
,
9025 state
->max_data_return
);
9026 END_PROFILE(Trans2_findnotifynext
);
9030 case TRANSACT2_MKDIR
:
9032 START_PROFILE(Trans2_mkdir
);
9033 call_trans2mkdir(conn
, req
,
9034 &state
->param
, state
->total_param
,
9035 &state
->data
, state
->total_data
,
9036 state
->max_data_return
);
9037 END_PROFILE(Trans2_mkdir
);
9041 case TRANSACT2_GET_DFS_REFERRAL
:
9043 START_PROFILE(Trans2_get_dfs_referral
);
9044 call_trans2getdfsreferral(conn
, req
,
9045 &state
->param
, state
->total_param
,
9046 &state
->data
, state
->total_data
,
9047 state
->max_data_return
);
9048 END_PROFILE(Trans2_get_dfs_referral
);
9052 case TRANSACT2_IOCTL
:
9054 START_PROFILE(Trans2_ioctl
);
9055 call_trans2ioctl(conn
, req
,
9056 &state
->param
, state
->total_param
,
9057 &state
->data
, state
->total_data
,
9058 state
->max_data_return
);
9059 END_PROFILE(Trans2_ioctl
);
9064 /* Error in request */
9065 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9066 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9070 /****************************************************************************
9071 Reply to a SMBtrans2.
9072 ****************************************************************************/
9074 void reply_trans2(struct smb_request
*req
)
9076 connection_struct
*conn
= req
->conn
;
9081 unsigned int tran_call
;
9082 struct trans_state
*state
;
9085 START_PROFILE(SMBtrans2
);
9087 if (req
->wct
< 14) {
9088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9089 END_PROFILE(SMBtrans2
);
9093 dsoff
= SVAL(req
->vwv
+12, 0);
9094 dscnt
= SVAL(req
->vwv
+11, 0);
9095 psoff
= SVAL(req
->vwv
+10, 0);
9096 pscnt
= SVAL(req
->vwv
+9, 0);
9097 tran_call
= SVAL(req
->vwv
+14, 0);
9099 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9100 if (!NT_STATUS_IS_OK(result
)) {
9101 DEBUG(2, ("Got invalid trans2 request: %s\n",
9102 nt_errstr(result
)));
9103 reply_nterror(req
, result
);
9104 END_PROFILE(SMBtrans2
);
9109 switch (tran_call
) {
9110 /* List the allowed trans2 calls on IPC$ */
9111 case TRANSACT2_OPEN
:
9112 case TRANSACT2_GET_DFS_REFERRAL
:
9113 case TRANSACT2_QFILEINFO
:
9114 case TRANSACT2_QFSINFO
:
9115 case TRANSACT2_SETFSINFO
:
9118 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9119 END_PROFILE(SMBtrans2
);
9124 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9125 DEBUG(0, ("talloc failed\n"));
9126 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9127 END_PROFILE(SMBtrans2
);
9131 state
->cmd
= SMBtrans2
;
9133 state
->mid
= req
->mid
;
9134 state
->vuid
= req
->vuid
;
9135 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9136 state
->setup
= NULL
;
9137 state
->total_param
= SVAL(req
->vwv
+0, 0);
9138 state
->param
= NULL
;
9139 state
->total_data
= SVAL(req
->vwv
+1, 0);
9141 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9142 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9143 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9144 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9145 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9147 state
->call
= tran_call
;
9149 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9150 is so as a sanity check */
9151 if (state
->setup_count
!= 1) {
9153 * Need to have rc=0 for ioctl to get job id for OS/2.
9154 * Network printing will fail if function is not successful.
9155 * Similar function in reply.c will be used if protocol
9156 * is LANMAN1.0 instead of LM1.2X002.
9157 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9158 * outbuf doesn't have to be set(only job id is used).
9160 if ( (state
->setup_count
== 4)
9161 && (tran_call
== TRANSACT2_IOCTL
)
9162 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9163 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9164 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9166 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9167 DEBUG(2,("Transaction is %d\n",tran_call
));
9169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9170 END_PROFILE(SMBtrans2
);
9175 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9178 if (state
->total_data
) {
9180 if (trans_oob(state
->total_data
, 0, dscnt
)
9181 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9185 /* Can't use talloc here, the core routines do realloc on the
9186 * params and data. */
9187 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9188 if (state
->data
== NULL
) {
9189 DEBUG(0,("reply_trans2: data malloc fail for %u "
9190 "bytes !\n", (unsigned int)state
->total_data
));
9192 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9193 END_PROFILE(SMBtrans2
);
9197 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9200 if (state
->total_param
) {
9202 if (trans_oob(state
->total_param
, 0, pscnt
)
9203 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9207 /* Can't use talloc here, the core routines do realloc on the
9208 * params and data. */
9209 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9210 if (state
->param
== NULL
) {
9211 DEBUG(0,("reply_trans: param malloc fail for %u "
9212 "bytes !\n", (unsigned int)state
->total_param
));
9213 SAFE_FREE(state
->data
);
9215 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9216 END_PROFILE(SMBtrans2
);
9220 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9223 state
->received_data
= dscnt
;
9224 state
->received_param
= pscnt
;
9226 if ((state
->received_param
== state
->total_param
) &&
9227 (state
->received_data
== state
->total_data
)) {
9229 handle_trans2(conn
, req
, state
);
9231 SAFE_FREE(state
->data
);
9232 SAFE_FREE(state
->param
);
9234 END_PROFILE(SMBtrans2
);
9238 DLIST_ADD(conn
->pending_trans
, state
);
9240 /* We need to send an interim response then receive the rest
9241 of the parameter/data bytes */
9242 reply_outbuf(req
, 0, 0);
9243 show_msg((char *)req
->outbuf
);
9244 END_PROFILE(SMBtrans2
);
9249 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9250 SAFE_FREE(state
->data
);
9251 SAFE_FREE(state
->param
);
9253 END_PROFILE(SMBtrans2
);
9254 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9258 /****************************************************************************
9259 Reply to a SMBtranss2
9260 ****************************************************************************/
9262 void reply_transs2(struct smb_request
*req
)
9264 connection_struct
*conn
= req
->conn
;
9265 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9266 struct trans_state
*state
;
9268 START_PROFILE(SMBtranss2
);
9270 show_msg((const char *)req
->inbuf
);
9272 /* Windows clients expect all replies to
9273 a transact secondary (SMBtranss2 0x33)
9274 to have a command code of transact
9275 (SMBtrans2 0x32). See bug #8989
9276 and also [MS-CIFS] section 2.2.4.47.2
9279 req
->cmd
= SMBtrans2
;
9282 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9283 END_PROFILE(SMBtranss2
);
9287 for (state
= conn
->pending_trans
; state
!= NULL
;
9288 state
= state
->next
) {
9289 if (state
->mid
== req
->mid
) {
9294 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9295 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9296 END_PROFILE(SMBtranss2
);
9300 /* Revise state->total_param and state->total_data in case they have
9301 changed downwards */
9303 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9304 state
->total_param
= SVAL(req
->vwv
+0, 0);
9305 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9306 state
->total_data
= SVAL(req
->vwv
+1, 0);
9308 pcnt
= SVAL(req
->vwv
+2, 0);
9309 poff
= SVAL(req
->vwv
+3, 0);
9310 pdisp
= SVAL(req
->vwv
+4, 0);
9312 dcnt
= SVAL(req
->vwv
+5, 0);
9313 doff
= SVAL(req
->vwv
+6, 0);
9314 ddisp
= SVAL(req
->vwv
+7, 0);
9316 state
->received_param
+= pcnt
;
9317 state
->received_data
+= dcnt
;
9319 if ((state
->received_data
> state
->total_data
) ||
9320 (state
->received_param
> state
->total_param
))
9324 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9325 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9328 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9332 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9333 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9336 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9339 if ((state
->received_param
< state
->total_param
) ||
9340 (state
->received_data
< state
->total_data
)) {
9341 END_PROFILE(SMBtranss2
);
9345 handle_trans2(conn
, req
, state
);
9347 DLIST_REMOVE(conn
->pending_trans
, state
);
9348 SAFE_FREE(state
->data
);
9349 SAFE_FREE(state
->param
);
9352 END_PROFILE(SMBtranss2
);
9357 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9358 DLIST_REMOVE(conn
->pending_trans
, state
);
9359 SAFE_FREE(state
->data
);
9360 SAFE_FREE(state
->param
);
9362 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9363 END_PROFILE(SMBtranss2
);