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
,
2377 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2378 DEBUG(1,("Conversion error: illegal character: %s\n",
2379 smb_fname_str_dbg(smb_fname
)));
2382 TALLOC_FREE(smb_fname
);
2383 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2384 dptr_SeekDir(dirptr
, prev_dirpos
);
2387 if (!NT_STATUS_IS_OK(status
)) {
2391 *_last_entry_off
= last_entry_off
;
2392 return NT_STATUS_OK
;
2395 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2396 connection_struct
*conn
,
2397 struct dptr_struct
*dirptr
,
2399 const char *path_mask
,
2402 bool requires_resume_key
,
2408 int space_remaining
,
2409 bool *got_exact_match
,
2410 int *last_entry_off
,
2411 struct ea_list
*name_list
)
2414 const bool do_pad
= true;
2416 if (info_level
>= 1 && info_level
<= 3) {
2417 /* No alignment on earlier info levels. */
2421 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2422 path_mask
, dirtype
, info_level
,
2423 requires_resume_key
, dont_descend
, ask_sharemode
,
2425 ppdata
, base_data
, end_data
,
2428 last_entry_off
, name_list
);
2431 /****************************************************************************
2432 Reply to a TRANS2_FINDFIRST.
2433 ****************************************************************************/
2435 static void call_trans2findfirst(connection_struct
*conn
,
2436 struct smb_request
*req
,
2437 char **pparams
, int total_params
,
2438 char **ppdata
, int total_data
,
2439 unsigned int max_data_bytes
)
2441 /* We must be careful here that we don't return more than the
2442 allowed number of data bytes. If this means returning fewer than
2443 maxentries then so be it. We assume that the redirector has
2444 enough room for the fixed number of parameter bytes it has
2446 struct smb_filename
*smb_dname
= NULL
;
2447 char *params
= *pparams
;
2448 char *pdata
= *ppdata
;
2452 uint16_t findfirst_flags
;
2453 bool close_after_first
;
2455 bool requires_resume_key
;
2457 char *directory
= NULL
;
2460 int last_entry_off
=0;
2464 bool finished
= False
;
2465 bool dont_descend
= False
;
2466 bool out_of_space
= False
;
2467 int space_remaining
;
2468 bool mask_contains_wcard
= False
;
2469 struct ea_list
*ea_list
= NULL
;
2470 NTSTATUS ntstatus
= NT_STATUS_OK
;
2471 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2472 TALLOC_CTX
*ctx
= talloc_tos();
2473 struct dptr_struct
*dirptr
= NULL
;
2474 struct smbd_server_connection
*sconn
= req
->sconn
;
2475 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2476 bool backup_priv
= false;
2477 bool as_root
= false;
2479 if (total_params
< 13) {
2480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2484 dirtype
= SVAL(params
,0);
2485 maxentries
= SVAL(params
,2);
2486 findfirst_flags
= SVAL(params
,4);
2487 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2488 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2489 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2490 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2491 security_token_has_privilege(get_current_nttok(conn
),
2494 info_level
= SVAL(params
,6);
2496 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2497 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2498 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2500 info_level
, max_data_bytes
));
2503 /* W2K3 seems to treat zero as 1. */
2507 switch (info_level
) {
2508 case SMB_FIND_INFO_STANDARD
:
2509 case SMB_FIND_EA_SIZE
:
2510 case SMB_FIND_EA_LIST
:
2511 case SMB_FIND_FILE_DIRECTORY_INFO
:
2512 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2513 case SMB_FIND_FILE_NAMES_INFO
:
2514 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2515 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2516 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2518 case SMB_FIND_FILE_UNIX
:
2519 case SMB_FIND_FILE_UNIX_INFO2
:
2520 /* Always use filesystem for UNIX mtime query. */
2521 ask_sharemode
= false;
2522 if (!lp_unix_extensions()) {
2523 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2526 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2529 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2533 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2534 params
+12, total_params
- 12,
2535 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2536 if (!NT_STATUS_IS_OK(ntstatus
)) {
2537 reply_nterror(req
, ntstatus
);
2544 ntstatus
= filename_convert_with_privilege(ctx
,
2549 &mask_contains_wcard
,
2552 ntstatus
= filename_convert(ctx
, conn
,
2553 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2556 &mask_contains_wcard
,
2560 if (!NT_STATUS_IS_OK(ntstatus
)) {
2561 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2562 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2563 ERRSRV
, ERRbadpath
);
2566 reply_nterror(req
, ntstatus
);
2570 mask
= smb_dname
->original_lcomp
;
2572 directory
= smb_dname
->base_name
;
2574 p
= strrchr_m(directory
,'/');
2576 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2577 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2578 mask
= talloc_strdup(ctx
,"*");
2580 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2583 mask_contains_wcard
= True
;
2589 if (p
== NULL
|| p
== directory
) {
2590 /* Ensure we don't have a directory name of "". */
2591 directory
= talloc_strdup(talloc_tos(), ".");
2593 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2598 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2600 if (info_level
== SMB_FIND_EA_LIST
) {
2603 if (total_data
< 4) {
2604 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2608 ea_size
= IVAL(pdata
,0);
2609 if (ea_size
!= total_data
) {
2610 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2611 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2612 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2616 if (!lp_ea_support(SNUM(conn
))) {
2617 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2621 /* Pull out the list of names. */
2622 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2624 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2629 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2630 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2634 *ppdata
= (char *)SMB_REALLOC(
2635 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2636 if(*ppdata
== NULL
) {
2637 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2641 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2643 /* Realloc the params space */
2644 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2645 if (*pparams
== NULL
) {
2646 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2651 /* Save the wildcard match and attribs we are using on this directory -
2652 needed as lanman2 assumes these are being saved between calls */
2654 ntstatus
= dptr_create(conn
,
2662 mask_contains_wcard
,
2666 if (!NT_STATUS_IS_OK(ntstatus
)) {
2667 reply_nterror(req
, ntstatus
);
2672 /* Remember this in case we have
2673 to do a findnext. */
2674 dptr_set_priv(dirptr
);
2677 dptr_num
= dptr_dnum(dirptr
);
2678 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2680 /* Initialize per TRANS2_FIND_FIRST operation data */
2681 dptr_init_search_op(dirptr
);
2683 /* We don't need to check for VOL here as this is returned by
2684 a different TRANS2 call. */
2686 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2687 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2688 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2689 dont_descend
= True
;
2692 space_remaining
= max_data_bytes
;
2693 out_of_space
= False
;
2695 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2696 bool got_exact_match
= False
;
2698 /* this is a heuristic to avoid seeking the dirptr except when
2699 absolutely necessary. It allows for a filename of about 40 chars */
2700 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2701 out_of_space
= True
;
2704 ntstatus
= get_lanman2_dir_entry(ctx
,
2708 mask
,dirtype
,info_level
,
2709 requires_resume_key
,dont_descend
,
2714 &last_entry_off
, ea_list
);
2715 if (NT_STATUS_EQUAL(ntstatus
,
2716 NT_STATUS_ILLEGAL_CHARACTER
)) {
2718 * Bad character conversion on name. Ignore this
2723 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2724 out_of_space
= true;
2726 finished
= !NT_STATUS_IS_OK(ntstatus
);
2730 if (!finished
&& !out_of_space
)
2734 * As an optimisation if we know we aren't looking
2735 * for a wildcard name (ie. the name matches the wildcard exactly)
2736 * then we can finish on any (first) match.
2737 * This speeds up large directory searches. JRA.
2743 /* Ensure space_remaining never goes -ve. */
2744 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2745 space_remaining
= 0;
2746 out_of_space
= true;
2748 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2752 /* Check if we can close the dirptr */
2753 if(close_after_first
|| (finished
&& close_if_end
)) {
2754 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2755 dptr_close(sconn
, &dptr_num
);
2759 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2760 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2761 * the protocol level is less than NT1. Tested with smbclient. JRA.
2762 * This should fix the OS/2 client bug #2335.
2765 if(numentries
== 0) {
2766 dptr_close(sconn
, &dptr_num
);
2767 if (get_Protocol() < PROTOCOL_NT1
) {
2768 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2771 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2772 ERRDOS
, ERRbadfile
);
2777 /* At this point pdata points to numentries directory entries. */
2779 /* Set up the return parameter block */
2780 SSVAL(params
,0,dptr_num
);
2781 SSVAL(params
,2,numentries
);
2782 SSVAL(params
,4,finished
);
2783 SSVAL(params
,6,0); /* Never an EA error */
2784 SSVAL(params
,8,last_entry_off
);
2786 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2789 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2790 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2792 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2796 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2797 smb_fn_name(req
->cmd
),
2798 mask
, directory
, dirtype
, numentries
) );
2801 * Force a name mangle here to ensure that the
2802 * mask as an 8.3 name is top of the mangled cache.
2803 * The reasons for this are subtle. Don't remove
2804 * this code unless you know what you are doing
2805 * (see PR#13758). JRA.
2808 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2809 char mangled_name
[13];
2810 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2818 TALLOC_FREE(smb_dname
);
2822 /****************************************************************************
2823 Reply to a TRANS2_FINDNEXT.
2824 ****************************************************************************/
2826 static void call_trans2findnext(connection_struct
*conn
,
2827 struct smb_request
*req
,
2828 char **pparams
, int total_params
,
2829 char **ppdata
, int total_data
,
2830 unsigned int max_data_bytes
)
2832 /* We must be careful here that we don't return more than the
2833 allowed number of data bytes. If this means returning fewer than
2834 maxentries then so be it. We assume that the redirector has
2835 enough room for the fixed number of parameter bytes it has
2837 char *params
= *pparams
;
2838 char *pdata
= *ppdata
;
2842 uint16_t info_level
;
2843 uint32_t resume_key
;
2844 uint16_t findnext_flags
;
2845 bool close_after_request
;
2847 bool requires_resume_key
;
2849 bool mask_contains_wcard
= False
;
2850 char *resume_name
= NULL
;
2851 const char *mask
= NULL
;
2852 const char *directory
= NULL
;
2856 int i
, last_entry_off
=0;
2857 bool finished
= False
;
2858 bool dont_descend
= False
;
2859 bool out_of_space
= False
;
2860 int space_remaining
;
2861 struct ea_list
*ea_list
= NULL
;
2862 NTSTATUS ntstatus
= NT_STATUS_OK
;
2863 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2864 TALLOC_CTX
*ctx
= talloc_tos();
2865 struct dptr_struct
*dirptr
;
2866 struct smbd_server_connection
*sconn
= req
->sconn
;
2867 bool backup_priv
= false;
2868 bool as_root
= false;
2870 if (total_params
< 13) {
2871 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2875 dptr_num
= SVAL(params
,0);
2876 maxentries
= SVAL(params
,2);
2877 info_level
= SVAL(params
,4);
2878 resume_key
= IVAL(params
,6);
2879 findnext_flags
= SVAL(params
,10);
2880 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2881 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2882 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2883 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2885 if (!continue_bit
) {
2886 /* We only need resume_name if continue_bit is zero. */
2887 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2889 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2890 &mask_contains_wcard
);
2891 if (!NT_STATUS_IS_OK(ntstatus
)) {
2892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2893 complain (it thinks we're asking for the directory above the shared
2894 path or an invalid name). Catch this as the resume name is only compared, never used in
2895 a file access. JRA. */
2896 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2897 &resume_name
, params
+12,
2901 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2902 reply_nterror(req
, ntstatus
);
2908 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2909 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2910 resume_key = %d resume name = %s continue=%d level = %d\n",
2911 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2912 requires_resume_key
, resume_key
,
2913 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2916 /* W2K3 seems to treat zero as 1. */
2920 switch (info_level
) {
2921 case SMB_FIND_INFO_STANDARD
:
2922 case SMB_FIND_EA_SIZE
:
2923 case SMB_FIND_EA_LIST
:
2924 case SMB_FIND_FILE_DIRECTORY_INFO
:
2925 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2926 case SMB_FIND_FILE_NAMES_INFO
:
2927 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2928 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2929 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2931 case SMB_FIND_FILE_UNIX
:
2932 case SMB_FIND_FILE_UNIX_INFO2
:
2933 /* Always use filesystem for UNIX mtime query. */
2934 ask_sharemode
= false;
2935 if (!lp_unix_extensions()) {
2936 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2941 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2945 if (info_level
== SMB_FIND_EA_LIST
) {
2948 if (total_data
< 4) {
2949 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2953 ea_size
= IVAL(pdata
,0);
2954 if (ea_size
!= total_data
) {
2955 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2956 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2957 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2961 if (!lp_ea_support(SNUM(conn
))) {
2962 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2966 /* Pull out the list of names. */
2967 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2969 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2974 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2975 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2979 *ppdata
= (char *)SMB_REALLOC(
2980 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2981 if(*ppdata
== NULL
) {
2982 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2987 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2989 /* Realloc the params space */
2990 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2991 if(*pparams
== NULL
) {
2992 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2998 /* Check that the dptr is valid */
2999 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
3000 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3004 directory
= dptr_path(sconn
, dptr_num
);
3006 /* Get the wildcard mask from the dptr */
3007 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3008 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3009 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3013 /* Get the attr mask from the dptr */
3014 dirtype
= dptr_attr(sconn
, dptr_num
);
3016 backup_priv
= dptr_get_priv(dirptr
);
3018 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3019 "backup_priv = %d\n",
3020 dptr_num
, mask
, dirtype
,
3022 dptr_TellDir(dirptr
),
3025 /* Initialize per TRANS2_FIND_NEXT operation data */
3026 dptr_init_search_op(dirptr
);
3028 /* We don't need to check for VOL here as this is returned by
3029 a different TRANS2 call. */
3031 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3032 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3033 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3034 dont_descend
= True
;
3037 space_remaining
= max_data_bytes
;
3038 out_of_space
= False
;
3046 * Seek to the correct position. We no longer use the resume key but
3047 * depend on the last file name instead.
3050 if(!continue_bit
&& resume_name
&& *resume_name
) {
3053 long current_pos
= 0;
3055 * Remember, name_to_8_3 is called by
3056 * get_lanman2_dir_entry(), so the resume name
3057 * could be mangled. Ensure we check the unmangled name.
3060 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3061 char *new_resume_name
= NULL
;
3062 mangle_lookup_name_from_8_3(ctx
,
3066 if (new_resume_name
) {
3067 resume_name
= new_resume_name
;
3072 * Fix for NT redirector problem triggered by resume key indexes
3073 * changing between directory scans. We now return a resume key of 0
3074 * and instead look for the filename to continue from (also given
3075 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3076 * findfirst/findnext (as is usual) then the directory pointer
3077 * should already be at the correct place.
3080 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3081 } /* end if resume_name && !continue_bit */
3083 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3084 bool got_exact_match
= False
;
3086 /* this is a heuristic to avoid seeking the dirptr except when
3087 absolutely necessary. It allows for a filename of about 40 chars */
3088 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3089 out_of_space
= True
;
3092 ntstatus
= get_lanman2_dir_entry(ctx
,
3096 mask
,dirtype
,info_level
,
3097 requires_resume_key
,dont_descend
,
3102 &last_entry_off
, ea_list
);
3103 if (NT_STATUS_EQUAL(ntstatus
,
3104 NT_STATUS_ILLEGAL_CHARACTER
)) {
3106 * Bad character conversion on name. Ignore this
3111 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3112 out_of_space
= true;
3114 finished
= !NT_STATUS_IS_OK(ntstatus
);
3118 if (!finished
&& !out_of_space
)
3122 * As an optimisation if we know we aren't looking
3123 * for a wildcard name (ie. the name matches the wildcard exactly)
3124 * then we can finish on any (first) match.
3125 * This speeds up large directory searches. JRA.
3131 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3134 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3135 smb_fn_name(req
->cmd
),
3136 mask
, directory
, dirtype
, numentries
) );
3138 /* Check if we can close the dirptr */
3139 if(close_after_request
|| (finished
&& close_if_end
)) {
3140 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3141 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3148 /* Set up the return parameter block */
3149 SSVAL(params
,0,numentries
);
3150 SSVAL(params
,2,finished
);
3151 SSVAL(params
,4,0); /* Never an EA error */
3152 SSVAL(params
,6,last_entry_off
);
3154 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3160 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3162 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3166 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3168 SMB_ASSERT(extended_info
!= NULL
);
3170 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3171 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3172 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3173 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3174 #ifdef SAMBA_VERSION_REVISION
3175 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3177 extended_info
->samba_subversion
= 0;
3178 #ifdef SAMBA_VERSION_RC_RELEASE
3179 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3181 #ifdef SAMBA_VERSION_PRE_RELEASE
3182 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3185 #ifdef SAMBA_VERSION_VENDOR_PATCH
3186 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3188 extended_info
->samba_gitcommitdate
= 0;
3189 #ifdef SAMBA_VERSION_COMMIT_TIME
3190 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3193 memset(extended_info
->samba_version_string
, 0,
3194 sizeof(extended_info
->samba_version_string
));
3196 snprintf (extended_info
->samba_version_string
,
3197 sizeof(extended_info
->samba_version_string
),
3198 "%s", samba_version_string());
3201 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3202 connection_struct
*conn
,
3203 TALLOC_CTX
*mem_ctx
,
3204 uint16_t info_level
,
3206 unsigned int max_data_bytes
,
3207 size_t *fixed_portion
,
3208 struct smb_filename
*fname
,
3212 char *pdata
, *end_data
;
3215 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3216 int snum
= SNUM(conn
);
3217 const char *fstype
= lp_fstype(SNUM(conn
));
3218 const char *filename
= NULL
;
3219 const uint64_t bytes_per_sector
= 512;
3220 uint32_t additional_flags
= 0;
3221 struct smb_filename smb_fname
;
3223 NTSTATUS status
= NT_STATUS_OK
;
3226 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3229 filename
= fname
->base_name
;
3233 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3234 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3235 "info level (0x%x) on IPC$.\n",
3236 (unsigned int)info_level
));
3237 return NT_STATUS_ACCESS_DENIED
;
3241 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3243 ZERO_STRUCT(smb_fname
);
3244 smb_fname
.base_name
= discard_const_p(char, filename
);
3246 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3247 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3248 return map_nt_error_from_unix(errno
);
3253 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3254 return NT_STATUS_INVALID_PARAMETER
;
3257 *ppdata
= (char *)SMB_REALLOC(
3258 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3259 if (*ppdata
== NULL
) {
3260 return NT_STATUS_NO_MEMORY
;
3264 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3265 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3269 switch (info_level
) {
3270 case SMB_INFO_ALLOCATION
:
3272 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3274 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3276 if (df_ret
== (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno
);
3280 block_size
= lp_block_size(snum
);
3281 if (bsize
< block_size
) {
3282 uint64_t factor
= block_size
/bsize
;
3287 if (bsize
> block_size
) {
3288 uint64_t factor
= bsize
/block_size
;
3293 sectors_per_unit
= bsize
/bytes_per_sector
;
3295 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3296 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3297 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3299 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3300 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3301 SIVAL(pdata
,l1_cUnit
,dsize
);
3302 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3303 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3307 case SMB_INFO_VOLUME
:
3308 /* Return volume name */
3310 * Add volume serial number - hash of a combination of
3311 * the called hostname and the service name.
3313 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3315 * Win2k3 and previous mess this up by sending a name length
3316 * one byte short. I believe only older clients (OS/2 Win9x) use
3317 * this call so try fixing this by adding a terminating null to
3318 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3320 status
= srvstr_push(
3322 pdata
+l2_vol_szVolLabel
, vname
,
3323 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3324 STR_NOALIGN
|STR_TERMINATE
, &len
);
3325 if (!NT_STATUS_IS_OK(status
)) {
3328 SCVAL(pdata
,l2_vol_cch
,len
);
3329 data_len
= l2_vol_szVolLabel
+ len
;
3330 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3331 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3332 (unsigned)len
, vname
));
3335 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3336 case SMB_FS_ATTRIBUTE_INFORMATION
:
3338 additional_flags
= 0;
3339 #if defined(HAVE_SYS_QUOTAS)
3340 additional_flags
|= FILE_VOLUME_QUOTAS
;
3343 if(lp_nt_acl_support(SNUM(conn
))) {
3344 additional_flags
|= FILE_PERSISTENT_ACLS
;
3347 /* Capabilities are filled in at connection time through STATVFS call */
3348 additional_flags
|= conn
->fs_capabilities
;
3349 additional_flags
|= lp_parm_int(conn
->params
->service
,
3350 "share", "fake_fscaps",
3353 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3354 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3355 additional_flags
); /* FS ATTRIBUTES */
3357 SIVAL(pdata
,4,255); /* Max filename component length */
3358 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3359 and will think we can't do long filenames */
3360 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3361 PTR_DIFF(end_data
, pdata
+12),
3363 if (!NT_STATUS_IS_OK(status
)) {
3367 data_len
= 12 + len
;
3368 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3369 /* the client only requested a portion of the
3371 data_len
= max_data_bytes
;
3372 status
= STATUS_BUFFER_OVERFLOW
;
3374 *fixed_portion
= 16;
3377 case SMB_QUERY_FS_LABEL_INFO
:
3378 case SMB_FS_LABEL_INFORMATION
:
3379 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3380 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3381 if (!NT_STATUS_IS_OK(status
)) {
3388 case SMB_QUERY_FS_VOLUME_INFO
:
3389 case SMB_FS_VOLUME_INFORMATION
:
3392 * Add volume serial number - hash of a combination of
3393 * the called hostname and the service name.
3395 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3396 (str_checksum(get_local_machine_name())<<16));
3398 /* Max label len is 32 characters. */
3399 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3400 PTR_DIFF(end_data
, pdata
+18),
3402 if (!NT_STATUS_IS_OK(status
)) {
3405 SIVAL(pdata
,12,len
);
3408 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3409 (int)strlen(vname
),vname
,
3410 lp_servicename(talloc_tos(), snum
)));
3411 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3412 /* the client only requested a portion of the
3414 data_len
= max_data_bytes
;
3415 status
= STATUS_BUFFER_OVERFLOW
;
3417 *fixed_portion
= 24;
3420 case SMB_QUERY_FS_SIZE_INFO
:
3421 case SMB_FS_SIZE_INFORMATION
:
3423 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3425 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3427 if (df_ret
== (uint64_t)-1) {
3428 return map_nt_error_from_unix(errno
);
3430 block_size
= lp_block_size(snum
);
3431 if (bsize
< block_size
) {
3432 uint64_t factor
= block_size
/bsize
;
3437 if (bsize
> block_size
) {
3438 uint64_t factor
= bsize
/block_size
;
3443 sectors_per_unit
= bsize
/bytes_per_sector
;
3444 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3446 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3447 SBIG_UINT(pdata
,0,dsize
);
3448 SBIG_UINT(pdata
,8,dfree
);
3449 SIVAL(pdata
,16,sectors_per_unit
);
3450 SIVAL(pdata
,20,bytes_per_sector
);
3451 *fixed_portion
= 24;
3455 case SMB_FS_FULL_SIZE_INFORMATION
:
3457 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3459 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3461 if (df_ret
== (uint64_t)-1) {
3462 return map_nt_error_from_unix(errno
);
3464 block_size
= lp_block_size(snum
);
3465 if (bsize
< block_size
) {
3466 uint64_t factor
= block_size
/bsize
;
3471 if (bsize
> block_size
) {
3472 uint64_t factor
= bsize
/block_size
;
3477 sectors_per_unit
= bsize
/bytes_per_sector
;
3478 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3479 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3480 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3481 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3482 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3483 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3484 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3485 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3486 *fixed_portion
= 32;
3490 case SMB_QUERY_FS_DEVICE_INFO
:
3491 case SMB_FS_DEVICE_INFORMATION
:
3493 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3495 if (!CAN_WRITE(conn
)) {
3496 characteristics
|= FILE_READ_ONLY_DEVICE
;
3499 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3500 SIVAL(pdata
,4,characteristics
);
3505 #ifdef HAVE_SYS_QUOTAS
3506 case SMB_FS_QUOTA_INFORMATION
:
3508 * what we have to send --metze:
3510 * Unknown1: 24 NULL bytes
3511 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3512 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3513 * Quota Flags: 2 byte :
3514 * Unknown3: 6 NULL bytes
3518 * details for Quota Flags:
3520 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3521 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3522 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3523 * 0x0001 Enable Quotas: enable quota for this fs
3527 /* we need to fake up a fsp here,
3528 * because its not send in this call
3531 SMB_NTQUOTA_STRUCT quotas
;
3534 ZERO_STRUCT(quotas
);
3537 fsp
.fnum
= FNUM_FIELD_INVALID
;
3540 if (get_current_uid(conn
) != 0) {
3541 DEBUG(0,("get_user_quota: access_denied "
3542 "service [%s] user [%s]\n",
3543 lp_servicename(talloc_tos(), SNUM(conn
)),
3544 conn
->session_info
->unix_info
->unix_name
));
3545 return NT_STATUS_ACCESS_DENIED
;
3548 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3549 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3550 return map_nt_error_from_unix(errno
);
3555 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3556 lp_servicename(talloc_tos(), SNUM(conn
))));
3558 /* Unknown1 24 NULL bytes*/
3559 SBIG_UINT(pdata
,0,(uint64_t)0);
3560 SBIG_UINT(pdata
,8,(uint64_t)0);
3561 SBIG_UINT(pdata
,16,(uint64_t)0);
3563 /* Default Soft Quota 8 bytes */
3564 SBIG_UINT(pdata
,24,quotas
.softlim
);
3566 /* Default Hard Quota 8 bytes */
3567 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3569 /* Quota flag 2 bytes */
3570 SSVAL(pdata
,40,quotas
.qflags
);
3572 /* Unknown3 6 NULL bytes */
3578 #endif /* HAVE_SYS_QUOTAS */
3579 case SMB_FS_OBJECTID_INFORMATION
:
3581 unsigned char objid
[16];
3582 struct smb_extended_info extended_info
;
3583 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3584 samba_extended_info_version (&extended_info
);
3585 SIVAL(pdata
,16,extended_info
.samba_magic
);
3586 SIVAL(pdata
,20,extended_info
.samba_version
);
3587 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3588 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3589 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3594 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3598 * These values match a physical Windows Server 2012
3599 * share backed by NTFS atop spinning rust.
3601 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3602 /* logical_bytes_per_sector */
3603 SIVAL(pdata
, 0, bytes_per_sector
);
3604 /* phys_bytes_per_sector_atomic */
3605 SIVAL(pdata
, 4, bytes_per_sector
);
3606 /* phys_bytes_per_sector_perf */
3607 SIVAL(pdata
, 8, bytes_per_sector
);
3608 /* fs_effective_phys_bytes_per_sector_atomic */
3609 SIVAL(pdata
, 12, bytes_per_sector
);
3611 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3612 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3613 /* byte_off_sector_align */
3614 SIVAL(pdata
, 20, 0);
3615 /* byte_off_partition_align */
3616 SIVAL(pdata
, 24, 0);
3617 *fixed_portion
= 28;
3623 * Query the version and capabilities of the CIFS UNIX extensions
3627 case SMB_QUERY_CIFS_UNIX_INFO
:
3629 bool large_write
= lp_min_receive_file_size() &&
3630 !srv_is_signing_active(xconn
);
3631 bool large_read
= !srv_is_signing_active(xconn
);
3632 int encrypt_caps
= 0;
3634 if (!lp_unix_extensions()) {
3635 return NT_STATUS_INVALID_LEVEL
;
3638 switch (conn
->encrypt_level
) {
3639 case SMB_SIGNING_OFF
:
3642 case SMB_SIGNING_DESIRED
:
3643 case SMB_SIGNING_IF_REQUIRED
:
3644 case SMB_SIGNING_DEFAULT
:
3645 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3647 case SMB_SIGNING_REQUIRED
:
3648 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3649 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3650 large_write
= false;
3656 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3657 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3659 /* We have POSIX ACLs, pathname, encryption,
3660 * large read/write, and locking capability. */
3662 SBIG_UINT(pdata
,4,((uint64_t)(
3663 CIFS_UNIX_POSIX_ACLS_CAP
|
3664 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3665 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3666 CIFS_UNIX_EXTATTR_CAP
|
3667 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3669 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3671 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3675 case SMB_QUERY_POSIX_FS_INFO
:
3678 vfs_statvfs_struct svfs
;
3680 if (!lp_unix_extensions()) {
3681 return NT_STATUS_INVALID_LEVEL
;
3684 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3688 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3689 SIVAL(pdata
,4,svfs
.BlockSize
);
3690 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3691 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3692 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3693 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3694 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3695 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3696 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3698 } else if (rc
== EOPNOTSUPP
) {
3699 return NT_STATUS_INVALID_LEVEL
;
3700 #endif /* EOPNOTSUPP */
3702 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3703 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3708 case SMB_QUERY_POSIX_WHOAMI
:
3714 if (!lp_unix_extensions()) {
3715 return NT_STATUS_INVALID_LEVEL
;
3718 if (max_data_bytes
< 40) {
3719 return NT_STATUS_BUFFER_TOO_SMALL
;
3722 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3723 flags
|= SMB_WHOAMI_GUEST
;
3726 /* NOTE: 8 bytes for UID/GID, irrespective of native
3727 * platform size. This matches
3728 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3730 data_len
= 4 /* flags */
3737 + 4 /* pad/reserved */
3738 + (conn
->session_info
->unix_token
->ngroups
* 8)
3740 + (conn
->session_info
->security_token
->num_sids
*
3744 SIVAL(pdata
, 0, flags
);
3745 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3747 (uint64_t)conn
->session_info
->unix_token
->uid
);
3748 SBIG_UINT(pdata
, 16,
3749 (uint64_t)conn
->session_info
->unix_token
->gid
);
3752 if (data_len
>= max_data_bytes
) {
3753 /* Potential overflow, skip the GIDs and SIDs. */
3755 SIVAL(pdata
, 24, 0); /* num_groups */
3756 SIVAL(pdata
, 28, 0); /* num_sids */
3757 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3758 SIVAL(pdata
, 36, 0); /* reserved */
3764 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3765 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3767 /* We walk the SID list twice, but this call is fairly
3768 * infrequent, and I don't expect that it's performance
3769 * sensitive -- jpeach
3771 for (i
= 0, sid_bytes
= 0;
3772 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3773 sid_bytes
+= ndr_size_dom_sid(
3774 &conn
->session_info
->security_token
->sids
[i
],
3778 /* SID list byte count */
3779 SIVAL(pdata
, 32, sid_bytes
);
3781 /* 4 bytes pad/reserved - must be zero */
3782 SIVAL(pdata
, 36, 0);
3786 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3787 SBIG_UINT(pdata
, data_len
,
3788 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3794 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3795 int sid_len
= ndr_size_dom_sid(
3796 &conn
->session_info
->security_token
->sids
[i
],
3799 sid_linearize((uint8_t *)(pdata
+ data_len
),
3801 &conn
->session_info
->security_token
->sids
[i
]);
3802 data_len
+= sid_len
;
3808 case SMB_MAC_QUERY_FS_INFO
:
3810 * Thursby MAC extension... ONLY on NTFS filesystems
3811 * once we do streams then we don't need this
3813 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3815 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3820 return NT_STATUS_INVALID_LEVEL
;
3823 *ret_data_len
= data_len
;
3827 /****************************************************************************
3828 Reply to a TRANS2_QFSINFO (query filesystem info).
3829 ****************************************************************************/
3831 static void call_trans2qfsinfo(connection_struct
*conn
,
3832 struct smb_request
*req
,
3833 char **pparams
, int total_params
,
3834 char **ppdata
, int total_data
,
3835 unsigned int max_data_bytes
)
3837 char *params
= *pparams
;
3838 uint16_t info_level
;
3840 size_t fixed_portion
;
3843 if (total_params
< 2) {
3844 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3848 info_level
= SVAL(params
,0);
3850 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3851 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3852 DEBUG(0,("call_trans2qfsinfo: encryption required "
3853 "and info level 0x%x sent.\n",
3854 (unsigned int)info_level
));
3855 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3860 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3862 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3869 if (!NT_STATUS_IS_OK(status
)) {
3870 reply_nterror(req
, status
);
3874 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3877 DEBUG( 4, ( "%s info_level = %d\n",
3878 smb_fn_name(req
->cmd
), info_level
) );
3883 /****************************************************************************
3884 Reply to a TRANS2_SETFSINFO (set filesystem info).
3885 ****************************************************************************/
3887 static void call_trans2setfsinfo(connection_struct
*conn
,
3888 struct smb_request
*req
,
3889 char **pparams
, int total_params
,
3890 char **ppdata
, int total_data
,
3891 unsigned int max_data_bytes
)
3893 struct smbXsrv_connection
*xconn
= req
->xconn
;
3894 char *pdata
= *ppdata
;
3895 char *params
= *pparams
;
3896 uint16_t info_level
;
3898 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3899 lp_servicename(talloc_tos(), SNUM(conn
))));
3902 if (total_params
< 4) {
3903 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3905 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3909 info_level
= SVAL(params
,2);
3912 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3913 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3914 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3915 "info level (0x%x) on IPC$.\n",
3916 (unsigned int)info_level
));
3917 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3922 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3923 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3924 DEBUG(0,("call_trans2setfsinfo: encryption required "
3925 "and info level 0x%x sent.\n",
3926 (unsigned int)info_level
));
3927 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3932 switch(info_level
) {
3933 case SMB_SET_CIFS_UNIX_INFO
:
3934 if (!lp_unix_extensions()) {
3935 DEBUG(2,("call_trans2setfsinfo: "
3936 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3937 "unix extensions off\n"));
3939 NT_STATUS_INVALID_LEVEL
);
3943 /* There should be 12 bytes of capabilities set. */
3944 if (total_data
< 12) {
3947 NT_STATUS_INVALID_PARAMETER
);
3950 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3951 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3952 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3953 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3954 /* Just print these values for now. */
3955 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3956 "major = %u, minor = %u cap_low = 0x%x, "
3958 (unsigned int)xconn
->
3959 smb1
.unix_info
.client_major
,
3960 (unsigned int)xconn
->
3961 smb1
.unix_info
.client_minor
,
3962 (unsigned int)xconn
->
3963 smb1
.unix_info
.client_cap_low
,
3964 (unsigned int)xconn
->
3965 smb1
.unix_info
.client_cap_high
));
3967 /* Here is where we must switch to posix pathname processing... */
3968 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3969 lp_set_posix_pathnames();
3970 mangle_change_to_posix();
3973 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3974 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3975 /* Client that knows how to do posix locks,
3976 * but not posix open/mkdir operations. Set a
3977 * default type for read/write checks. */
3979 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3984 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3987 size_t param_len
= 0;
3988 size_t data_len
= total_data
;
3990 if (!lp_unix_extensions()) {
3993 NT_STATUS_INVALID_LEVEL
);
3997 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
4000 NT_STATUS_NOT_SUPPORTED
);
4004 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4005 DEBUG( 2,("call_trans2setfsinfo: "
4006 "request transport encryption disabled"
4007 "with 'fork echo handler = yes'\n"));
4010 NT_STATUS_NOT_SUPPORTED
);
4014 DEBUG( 4,("call_trans2setfsinfo: "
4015 "request transport encryption.\n"));
4017 status
= srv_request_encryption_setup(conn
,
4018 (unsigned char **)ppdata
,
4020 (unsigned char **)pparams
,
4023 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4024 !NT_STATUS_IS_OK(status
)) {
4025 reply_nterror(req
, status
);
4029 send_trans2_replies(conn
, req
,
4037 if (NT_STATUS_IS_OK(status
)) {
4038 /* Server-side transport
4039 * encryption is now *on*. */
4040 status
= srv_encryption_start(conn
);
4041 if (!NT_STATUS_IS_OK(status
)) {
4042 char *reason
= talloc_asprintf(talloc_tos(),
4043 "Failure in setting "
4044 "up encrypted transport: %s",
4046 exit_server_cleanly(reason
);
4052 case SMB_FS_QUOTA_INFORMATION
:
4054 files_struct
*fsp
= NULL
;
4055 SMB_NTQUOTA_STRUCT quotas
;
4057 ZERO_STRUCT(quotas
);
4060 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4061 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4062 lp_servicename(talloc_tos(), SNUM(conn
)),
4063 conn
->session_info
->unix_info
->unix_name
));
4064 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4068 /* note: normally there're 48 bytes,
4069 * but we didn't use the last 6 bytes for now
4072 fsp
= file_fsp(req
, SVAL(params
,0));
4074 if (!check_fsp_ntquota_handle(conn
, req
,
4076 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4078 req
, NT_STATUS_INVALID_HANDLE
);
4082 if (total_data
< 42) {
4083 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4087 NT_STATUS_INVALID_PARAMETER
);
4091 /* unknown_1 24 NULL bytes in pdata*/
4093 /* the soft quotas 8 bytes (uint64_t)*/
4094 quotas
.softlim
= BVAL(pdata
,24);
4096 /* the hard quotas 8 bytes (uint64_t)*/
4097 quotas
.hardlim
= BVAL(pdata
,32);
4099 /* quota_flags 2 bytes **/
4100 quotas
.qflags
= SVAL(pdata
,40);
4102 /* unknown_2 6 NULL bytes follow*/
4104 /* now set the quotas */
4105 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4106 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4107 reply_nterror(req
, map_nt_error_from_unix(errno
));
4114 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4116 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4122 * sending this reply works fine,
4123 * but I'm not sure it's the same
4124 * like windows do...
4127 reply_outbuf(req
, 10, 0);
4130 #if defined(HAVE_POSIX_ACLS)
4131 /****************************************************************************
4132 Utility function to count the number of entries in a POSIX acl.
4133 ****************************************************************************/
4135 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4137 unsigned int ace_count
= 0;
4138 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4139 SMB_ACL_ENTRY_T entry
;
4141 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4143 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4144 entry_id
= SMB_ACL_NEXT_ENTRY
;
4151 /****************************************************************************
4152 Utility function to marshall a POSIX acl into wire format.
4153 ****************************************************************************/
4155 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4157 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4158 SMB_ACL_ENTRY_T entry
;
4160 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4161 SMB_ACL_TAG_T tagtype
;
4162 SMB_ACL_PERMSET_T permset
;
4163 unsigned char perms
= 0;
4164 unsigned int own_grp
;
4167 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4168 entry_id
= SMB_ACL_NEXT_ENTRY
;
4171 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4172 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4176 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4177 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4181 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4182 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4183 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4185 SCVAL(pdata
,1,perms
);
4188 case SMB_ACL_USER_OBJ
:
4189 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4190 own_grp
= (unsigned int)pst
->st_ex_uid
;
4191 SIVAL(pdata
,2,own_grp
);
4196 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4198 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4201 own_grp
= (unsigned int)*puid
;
4202 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4203 SIVAL(pdata
,2,own_grp
);
4207 case SMB_ACL_GROUP_OBJ
:
4208 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4209 own_grp
= (unsigned int)pst
->st_ex_gid
;
4210 SIVAL(pdata
,2,own_grp
);
4215 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4217 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4220 own_grp
= (unsigned int)*pgid
;
4221 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4222 SIVAL(pdata
,2,own_grp
);
4227 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4228 SIVAL(pdata
,2,0xFFFFFFFF);
4229 SIVAL(pdata
,6,0xFFFFFFFF);
4232 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4233 SIVAL(pdata
,2,0xFFFFFFFF);
4234 SIVAL(pdata
,6,0xFFFFFFFF);
4237 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4240 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4247 /****************************************************************************
4248 Store the FILE_UNIX_BASIC info.
4249 ****************************************************************************/
4251 static char *store_file_unix_basic(connection_struct
*conn
,
4254 const SMB_STRUCT_STAT
*psbuf
)
4256 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4259 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4260 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4262 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4265 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4268 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4269 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4270 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4273 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4277 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4281 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4284 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4285 devno
= psbuf
->st_ex_rdev
;
4287 devno
= psbuf
->st_ex_dev
;
4290 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4294 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4298 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4301 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4305 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4312 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4313 * the chflags(2) (or equivalent) flags.
4315 * XXX: this really should be behind the VFS interface. To do this, we would
4316 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4317 * Each VFS module could then implement its own mapping as appropriate for the
4318 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4320 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4324 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4328 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4332 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4336 { UF_HIDDEN
, EXT_HIDDEN
},
4339 /* Do not remove. We need to guarantee that this array has at least one
4340 * entry to build on HP-UX.
4346 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4347 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4351 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4352 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4353 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4354 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4359 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4360 const uint32_t smb_fflags
,
4361 const uint32_t smb_fmask
,
4364 uint32_t max_fmask
= 0;
4367 *stat_fflags
= psbuf
->st_ex_flags
;
4369 /* For each flags requested in smb_fmask, check the state of the
4370 * corresponding flag in smb_fflags and set or clear the matching
4374 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4375 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4376 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4377 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4378 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4380 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4385 /* If smb_fmask is asking to set any bits that are not supported by
4386 * our flag mappings, we should fail.
4388 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4396 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4397 * of file flags and birth (create) time.
4399 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4402 const SMB_STRUCT_STAT
*psbuf
)
4404 uint32_t file_flags
= 0;
4405 uint32_t flags_mask
= 0;
4407 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4409 /* Create (birth) time 64 bit */
4410 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4413 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4414 SIVAL(pdata
, 0, file_flags
); /* flags */
4415 SIVAL(pdata
, 4, flags_mask
); /* mask */
4421 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4422 const struct stream_struct
*streams
,
4424 unsigned int max_data_bytes
,
4425 unsigned int *data_size
)
4428 unsigned int ofs
= 0;
4430 if (max_data_bytes
< 32) {
4431 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4434 for (i
= 0; i
< num_streams
; i
++) {
4435 unsigned int next_offset
;
4437 smb_ucs2_t
*namebuf
;
4439 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4440 streams
[i
].name
, &namelen
) ||
4443 return NT_STATUS_INVALID_PARAMETER
;
4447 * name_buf is now null-terminated, we need to marshall as not
4454 * We cannot overflow ...
4456 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4457 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4459 TALLOC_FREE(namebuf
);
4460 return STATUS_BUFFER_OVERFLOW
;
4463 SIVAL(data
, ofs
+4, namelen
);
4464 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4465 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4466 memcpy(data
+ofs
+24, namebuf
, namelen
);
4467 TALLOC_FREE(namebuf
);
4469 next_offset
= ofs
+ 24 + namelen
;
4471 if (i
== num_streams
-1) {
4472 SIVAL(data
, ofs
, 0);
4475 unsigned int align
= ndr_align_size(next_offset
, 8);
4477 if ((next_offset
+ align
) > max_data_bytes
) {
4478 DEBUG(10, ("refusing to overflow align "
4479 "reply at stream %u\n",
4481 TALLOC_FREE(namebuf
);
4482 return STATUS_BUFFER_OVERFLOW
;
4485 memset(data
+next_offset
, 0, align
);
4486 next_offset
+= align
;
4488 SIVAL(data
, ofs
, next_offset
- ofs
);
4495 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4499 return NT_STATUS_OK
;
4502 /****************************************************************************
4503 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4504 ****************************************************************************/
4506 static void call_trans2qpipeinfo(connection_struct
*conn
,
4507 struct smb_request
*req
,
4508 unsigned int tran_call
,
4509 char **pparams
, int total_params
,
4510 char **ppdata
, int total_data
,
4511 unsigned int max_data_bytes
)
4513 char *params
= *pparams
;
4514 char *pdata
= *ppdata
;
4515 unsigned int data_size
= 0;
4516 unsigned int param_size
= 2;
4517 uint16_t info_level
;
4521 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4525 if (total_params
< 4) {
4526 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4530 fsp
= file_fsp(req
, SVAL(params
,0));
4531 if (!fsp_is_np(fsp
)) {
4532 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4536 info_level
= SVAL(params
,2);
4538 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4539 if (*pparams
== NULL
) {
4540 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4545 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4546 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4549 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4550 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4551 if (*ppdata
== NULL
) {
4552 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4557 switch (info_level
) {
4558 case SMB_FILE_STANDARD_INFORMATION
:
4560 SOFF_T(pdata
,0,4096LL);
4567 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4571 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4577 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4578 TALLOC_CTX
*mem_ctx
,
4579 uint16_t info_level
,
4581 struct smb_filename
*smb_fname
,
4582 bool delete_pending
,
4583 struct timespec write_time_ts
,
4584 struct ea_list
*ea_list
,
4585 int lock_data_count
,
4588 unsigned int max_data_bytes
,
4589 size_t *fixed_portion
,
4591 unsigned int *pdata_size
)
4593 char *pdata
= *ppdata
;
4594 char *dstart
, *dend
;
4595 unsigned int data_size
;
4596 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4597 time_t create_time
, mtime
, atime
, c_time
;
4598 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4605 uint64_t file_size
= 0;
4607 uint64_t allocation_size
= 0;
4608 uint64_t file_index
= 0;
4609 uint32_t access_mask
= 0;
4612 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4613 return NT_STATUS_INVALID_LEVEL
;
4616 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4617 smb_fname_str_dbg(smb_fname
),
4619 info_level
, max_data_bytes
));
4621 mode
= dos_mode(conn
, smb_fname
);
4622 nlink
= psbuf
->st_ex_nlink
;
4624 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4628 if ((nlink
> 0) && delete_pending
) {
4632 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4633 return NT_STATUS_INVALID_PARAMETER
;
4636 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4637 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4638 if (*ppdata
== NULL
) {
4639 return NT_STATUS_NO_MEMORY
;
4643 dend
= dstart
+ data_size
- 1;
4645 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4646 update_stat_ex_mtime(psbuf
, write_time_ts
);
4649 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4650 mtime_ts
= psbuf
->st_ex_mtime
;
4651 atime_ts
= psbuf
->st_ex_atime
;
4652 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4654 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4655 dos_filetime_timespec(&create_time_ts
);
4656 dos_filetime_timespec(&mtime_ts
);
4657 dos_filetime_timespec(&atime_ts
);
4658 dos_filetime_timespec(&ctime_ts
);
4661 create_time
= convert_timespec_to_time_t(create_time_ts
);
4662 mtime
= convert_timespec_to_time_t(mtime_ts
);
4663 atime
= convert_timespec_to_time_t(atime_ts
);
4664 c_time
= convert_timespec_to_time_t(ctime_ts
);
4666 p
= strrchr_m(smb_fname
->base_name
,'/');
4668 base_name
= smb_fname
->base_name
;
4672 /* NT expects the name to be in an exact form of the *full*
4673 filename. See the trans2 torture test */
4674 if (ISDOT(base_name
)) {
4675 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4677 return NT_STATUS_NO_MEMORY
;
4680 dos_fname
= talloc_asprintf(mem_ctx
,
4682 smb_fname
->base_name
);
4684 return NT_STATUS_NO_MEMORY
;
4686 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4687 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4688 smb_fname
->stream_name
);
4690 return NT_STATUS_NO_MEMORY
;
4694 string_replace(dos_fname
, '/', '\\');
4697 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4700 /* Do we have this path open ? */
4702 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4703 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4704 if (fsp1
&& fsp1
->initial_allocation_size
) {
4705 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4709 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4710 file_size
= get_file_size_stat(psbuf
);
4714 pos
= fsp
->fh
->position_information
;
4718 access_mask
= fsp
->access_mask
;
4720 /* GENERIC_EXECUTE mapping from Windows */
4721 access_mask
= 0x12019F;
4724 /* This should be an index number - looks like
4727 I think this causes us to fail the IFSKIT
4728 BasicFileInformationTest. -tpot */
4729 file_index
= get_FileIndex(conn
, psbuf
);
4733 switch (info_level
) {
4734 case SMB_INFO_STANDARD
:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4737 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4738 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4739 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4740 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4741 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4742 SSVAL(pdata
,l1_attrFile
,mode
);
4745 case SMB_INFO_QUERY_EA_SIZE
:
4747 unsigned int ea_size
=
4748 estimate_ea_size(conn
, fsp
,
4750 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4752 srv_put_dos_date2(pdata
,0,create_time
);
4753 srv_put_dos_date2(pdata
,4,atime
);
4754 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4755 SIVAL(pdata
,12,(uint32_t)file_size
);
4756 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4757 SSVAL(pdata
,20,mode
);
4758 SIVAL(pdata
,22,ea_size
);
4762 case SMB_INFO_IS_NAME_VALID
:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4765 /* os/2 needs this ? really ?*/
4766 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4768 /* This is only reached for qpathinfo */
4772 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4774 size_t total_ea_len
= 0;
4775 struct ea_list
*ea_file_list
= NULL
;
4776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4779 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4781 &total_ea_len
, &ea_file_list
);
4782 if (!NT_STATUS_IS_OK(status
)) {
4786 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4788 if (!ea_list
|| (total_ea_len
> data_size
)) {
4790 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4794 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4798 case SMB_INFO_QUERY_ALL_EAS
:
4800 /* We have data_size bytes to put EA's into. */
4801 size_t total_ea_len
= 0;
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4804 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4806 &total_ea_len
, &ea_list
);
4807 if (!NT_STATUS_IS_OK(status
)) {
4811 if (!ea_list
|| (total_ea_len
> data_size
)) {
4813 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4817 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4821 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4823 /* This is FileFullEaInformation - 0xF which maps to
4824 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4826 /* We have data_size bytes to put EA's into. */
4827 size_t total_ea_len
= 0;
4828 struct ea_list
*ea_file_list
= NULL
;
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4832 /*TODO: add filtering and index handling */
4835 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4837 &total_ea_len
, &ea_file_list
);
4838 if (!NT_STATUS_IS_OK(status
)) {
4841 if (!ea_file_list
) {
4842 return NT_STATUS_NO_EAS_ON_FILE
;
4845 status
= fill_ea_chained_buffer(mem_ctx
,
4849 conn
, ea_file_list
);
4850 if (!NT_STATUS_IS_OK(status
)) {
4856 case SMB_FILE_BASIC_INFORMATION
:
4857 case SMB_QUERY_FILE_BASIC_INFO
:
4859 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4860 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4861 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4863 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4867 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4868 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4869 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4870 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4871 SIVAL(pdata
,32,mode
);
4873 DEBUG(5,("SMB_QFBI - "));
4874 DEBUG(5,("create: %s ", ctime(&create_time
)));
4875 DEBUG(5,("access: %s ", ctime(&atime
)));
4876 DEBUG(5,("write: %s ", ctime(&mtime
)));
4877 DEBUG(5,("change: %s ", ctime(&c_time
)));
4878 DEBUG(5,("mode: %x\n", mode
));
4879 *fixed_portion
= data_size
;
4882 case SMB_FILE_STANDARD_INFORMATION
:
4883 case SMB_QUERY_FILE_STANDARD_INFO
:
4885 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4887 SOFF_T(pdata
,0,allocation_size
);
4888 SOFF_T(pdata
,8,file_size
);
4889 SIVAL(pdata
,16,nlink
);
4890 SCVAL(pdata
,20,delete_pending
?1:0);
4891 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4892 SSVAL(pdata
,22,0); /* Padding. */
4893 *fixed_portion
= 24;
4896 case SMB_FILE_EA_INFORMATION
:
4897 case SMB_QUERY_FILE_EA_INFO
:
4899 unsigned int ea_size
=
4900 estimate_ea_size(conn
, fsp
, smb_fname
);
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4904 SIVAL(pdata
,0,ea_size
);
4908 /* Get the 8.3 name - used if NT SMB was negotiated. */
4909 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4910 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4912 char mangled_name
[13];
4913 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4914 if (!name_to_8_3(base_name
,mangled_name
,
4915 True
,conn
->params
)) {
4916 return NT_STATUS_NO_MEMORY
;
4918 status
= srvstr_push(dstart
, flags2
,
4919 pdata
+4, mangled_name
,
4920 PTR_DIFF(dend
, pdata
+4),
4922 if (!NT_STATUS_IS_OK(status
)) {
4925 data_size
= 4 + len
;
4931 case SMB_QUERY_FILE_NAME_INFO
:
4934 this must be *exactly* right for ACLs on mapped drives to work
4936 status
= srvstr_push(dstart
, flags2
,
4938 PTR_DIFF(dend
, pdata
+4),
4940 if (!NT_STATUS_IS_OK(status
)) {
4943 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4944 data_size
= 4 + len
;
4949 case SMB_FILE_ALLOCATION_INFORMATION
:
4950 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4951 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4953 SOFF_T(pdata
,0,allocation_size
);
4956 case SMB_FILE_END_OF_FILE_INFORMATION
:
4957 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4960 SOFF_T(pdata
,0,file_size
);
4963 case SMB_QUERY_FILE_ALL_INFO
:
4964 case SMB_FILE_ALL_INFORMATION
:
4966 unsigned int ea_size
=
4967 estimate_ea_size(conn
, fsp
, smb_fname
);
4968 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4969 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4970 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4971 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4972 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4973 SIVAL(pdata
,32,mode
);
4974 SIVAL(pdata
,36,0); /* padding. */
4976 SOFF_T(pdata
,0,allocation_size
);
4977 SOFF_T(pdata
,8,file_size
);
4978 SIVAL(pdata
,16,nlink
);
4979 SCVAL(pdata
,20,delete_pending
);
4980 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4983 SIVAL(pdata
,0,ea_size
);
4984 pdata
+= 4; /* EA info */
4985 status
= srvstr_push(dstart
, flags2
,
4987 PTR_DIFF(dend
, pdata
+4),
4989 if (!NT_STATUS_IS_OK(status
)) {
4994 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4995 *fixed_portion
= 10;
4999 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5001 unsigned int ea_size
=
5002 estimate_ea_size(conn
, fsp
, smb_fname
);
5003 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5004 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5005 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5006 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5007 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5008 SIVAL(pdata
, 0x20, mode
);
5009 SIVAL(pdata
, 0x24, 0); /* padding. */
5010 SBVAL(pdata
, 0x28, allocation_size
);
5011 SBVAL(pdata
, 0x30, file_size
);
5012 SIVAL(pdata
, 0x38, nlink
);
5013 SCVAL(pdata
, 0x3C, delete_pending
);
5014 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5015 SSVAL(pdata
, 0x3E, 0); /* padding */
5016 SBVAL(pdata
, 0x40, file_index
);
5017 SIVAL(pdata
, 0x48, ea_size
);
5018 SIVAL(pdata
, 0x4C, access_mask
);
5019 SBVAL(pdata
, 0x50, pos
);
5020 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5021 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5025 status
= srvstr_push(dstart
, flags2
,
5027 PTR_DIFF(dend
, pdata
+4),
5029 if (!NT_STATUS_IS_OK(status
)) {
5034 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5035 *fixed_portion
= 104;
5038 case SMB_FILE_INTERNAL_INFORMATION
:
5040 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5041 SBVAL(pdata
, 0, file_index
);
5046 case SMB_FILE_ACCESS_INFORMATION
:
5047 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5048 SIVAL(pdata
, 0, access_mask
);
5053 case SMB_FILE_NAME_INFORMATION
:
5054 /* Pathname with leading '\'. */
5057 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5058 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5059 SIVAL(pdata
,0,byte_len
);
5060 data_size
= 4 + byte_len
;
5064 case SMB_FILE_DISPOSITION_INFORMATION
:
5065 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5067 SCVAL(pdata
,0,delete_pending
);
5071 case SMB_FILE_POSITION_INFORMATION
:
5072 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5074 SOFF_T(pdata
,0,pos
);
5078 case SMB_FILE_MODE_INFORMATION
:
5079 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5080 SIVAL(pdata
,0,mode
);
5085 case SMB_FILE_ALIGNMENT_INFORMATION
:
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5087 SIVAL(pdata
,0,0); /* No alignment needed. */
5093 * NT4 server just returns "invalid query" to this - if we try
5094 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5097 /* The first statement above is false - verified using Thursby
5098 * client against NT4 -- gcolley.
5100 case SMB_QUERY_FILE_STREAM_INFO
:
5101 case SMB_FILE_STREAM_INFORMATION
: {
5102 unsigned int num_streams
= 0;
5103 struct stream_struct
*streams
= NULL
;
5105 DEBUG(10,("smbd_do_qfilepathinfo: "
5106 "SMB_FILE_STREAM_INFORMATION\n"));
5108 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5109 return NT_STATUS_INVALID_PARAMETER
;
5112 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5113 talloc_tos(), &num_streams
, &streams
);
5115 if (!NT_STATUS_IS_OK(status
)) {
5116 DEBUG(10, ("could not get stream info: %s\n",
5117 nt_errstr(status
)));
5121 status
= marshall_stream_info(num_streams
, streams
,
5122 pdata
, max_data_bytes
,
5125 if (!NT_STATUS_IS_OK(status
)) {
5126 DEBUG(10, ("marshall_stream_info failed: %s\n",
5127 nt_errstr(status
)));
5128 TALLOC_FREE(streams
);
5132 TALLOC_FREE(streams
);
5134 *fixed_portion
= 32;
5138 case SMB_QUERY_COMPRESSION_INFO
:
5139 case SMB_FILE_COMPRESSION_INFORMATION
:
5140 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5141 SOFF_T(pdata
,0,file_size
);
5142 SIVAL(pdata
,8,0); /* ??? */
5143 SIVAL(pdata
,12,0); /* ??? */
5145 *fixed_portion
= 16;
5148 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5149 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5150 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5151 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5152 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5153 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5154 SOFF_T(pdata
,32,allocation_size
);
5155 SOFF_T(pdata
,40,file_size
);
5156 SIVAL(pdata
,48,mode
);
5157 SIVAL(pdata
,52,0); /* ??? */
5159 *fixed_portion
= 56;
5162 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5164 SIVAL(pdata
,0,mode
);
5171 * CIFS UNIX Extensions.
5174 case SMB_QUERY_FILE_UNIX_BASIC
:
5176 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5177 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5179 DEBUG(4,("smbd_do_qfilepathinfo: "
5180 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5181 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5185 case SMB_QUERY_FILE_UNIX_INFO2
:
5187 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5188 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5192 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5194 for (i
=0; i
<100; i
++)
5195 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5201 case SMB_QUERY_FILE_UNIX_LINK
:
5204 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5207 return NT_STATUS_NO_MEMORY
;
5210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5212 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5213 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5216 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5218 link_len
= SMB_VFS_READLINK(conn
,
5219 smb_fname
->base_name
,
5221 if (link_len
== -1) {
5222 return map_nt_error_from_unix(errno
);
5224 buffer
[link_len
] = 0;
5225 status
= srvstr_push(dstart
, flags2
,
5227 PTR_DIFF(dend
, pdata
),
5228 STR_TERMINATE
, &len
);
5229 if (!NT_STATUS_IS_OK(status
)) {
5233 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5238 #if defined(HAVE_POSIX_ACLS)
5239 case SMB_QUERY_POSIX_ACL
:
5241 SMB_ACL_T file_acl
= NULL
;
5242 SMB_ACL_T def_acl
= NULL
;
5243 uint16_t num_file_acls
= 0;
5244 uint16_t num_def_acls
= 0;
5246 if (fsp
&& fsp
->fh
->fd
!= -1) {
5247 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5251 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5252 smb_fname
->base_name
,
5253 SMB_ACL_TYPE_ACCESS
,
5257 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5258 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5259 "not implemented on "
5260 "filesystem containing %s\n",
5261 smb_fname
->base_name
));
5262 return NT_STATUS_NOT_IMPLEMENTED
;
5265 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5266 if (fsp
&& fsp
->is_directory
) {
5268 SMB_VFS_SYS_ACL_GET_FILE(
5270 fsp
->fsp_name
->base_name
,
5271 SMB_ACL_TYPE_DEFAULT
,
5275 SMB_VFS_SYS_ACL_GET_FILE(
5277 smb_fname
->base_name
,
5278 SMB_ACL_TYPE_DEFAULT
,
5281 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5284 num_file_acls
= count_acl_entries(conn
, file_acl
);
5285 num_def_acls
= count_acl_entries(conn
, def_acl
);
5287 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5288 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5290 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5291 SMB_POSIX_ACL_HEADER_SIZE
) ));
5293 TALLOC_FREE(file_acl
);
5296 TALLOC_FREE(def_acl
);
5298 return NT_STATUS_BUFFER_TOO_SMALL
;
5301 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5302 SSVAL(pdata
,2,num_file_acls
);
5303 SSVAL(pdata
,4,num_def_acls
);
5304 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5306 TALLOC_FREE(file_acl
);
5309 TALLOC_FREE(def_acl
);
5311 return NT_STATUS_INTERNAL_ERROR
;
5313 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5315 TALLOC_FREE(file_acl
);
5318 TALLOC_FREE(def_acl
);
5320 return NT_STATUS_INTERNAL_ERROR
;
5324 TALLOC_FREE(file_acl
);
5327 TALLOC_FREE(def_acl
);
5329 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5335 case SMB_QUERY_POSIX_LOCK
:
5340 enum brl_type lock_type
;
5342 /* We need an open file with a real fd for this. */
5343 if (!fsp
|| fsp
->fh
->fd
== -1) {
5344 return NT_STATUS_INVALID_LEVEL
;
5347 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5348 return NT_STATUS_INVALID_PARAMETER
;
5351 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5352 case POSIX_LOCK_TYPE_READ
:
5353 lock_type
= READ_LOCK
;
5355 case POSIX_LOCK_TYPE_WRITE
:
5356 lock_type
= WRITE_LOCK
;
5358 case POSIX_LOCK_TYPE_UNLOCK
:
5360 /* There's no point in asking for an unlock... */
5361 return NT_STATUS_INVALID_PARAMETER
;
5364 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5365 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5366 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5368 status
= query_lock(fsp
,
5375 if (ERROR_WAS_LOCK_DENIED(status
)) {
5376 /* Here we need to report who has it locked... */
5377 data_size
= POSIX_LOCK_DATA_SIZE
;
5379 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5380 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5381 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5382 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5383 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5385 } else if (NT_STATUS_IS_OK(status
)) {
5386 /* For success we just return a copy of what we sent
5387 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5388 data_size
= POSIX_LOCK_DATA_SIZE
;
5389 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5390 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5398 return NT_STATUS_INVALID_LEVEL
;
5401 *pdata_size
= data_size
;
5402 return NT_STATUS_OK
;
5405 /****************************************************************************
5406 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5407 file name or file id).
5408 ****************************************************************************/
5410 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5411 struct smb_request
*req
,
5412 unsigned int tran_call
,
5413 char **pparams
, int total_params
,
5414 char **ppdata
, int total_data
,
5415 unsigned int max_data_bytes
)
5417 char *params
= *pparams
;
5418 char *pdata
= *ppdata
;
5419 uint16_t info_level
;
5420 unsigned int data_size
= 0;
5421 unsigned int param_size
= 2;
5422 struct smb_filename
*smb_fname
= NULL
;
5423 bool delete_pending
= False
;
5424 struct timespec write_time_ts
;
5425 files_struct
*fsp
= NULL
;
5426 struct file_id fileid
;
5427 struct ea_list
*ea_list
= NULL
;
5428 int lock_data_count
= 0;
5429 char *lock_data
= NULL
;
5430 size_t fixed_portion
;
5431 NTSTATUS status
= NT_STATUS_OK
;
5434 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5438 ZERO_STRUCT(write_time_ts
);
5440 if (tran_call
== TRANSACT2_QFILEINFO
) {
5441 if (total_params
< 4) {
5442 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5447 call_trans2qpipeinfo(conn
, req
, tran_call
,
5448 pparams
, total_params
,
5454 fsp
= file_fsp(req
, SVAL(params
,0));
5455 info_level
= SVAL(params
,2);
5457 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5459 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5460 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5464 /* Initial check for valid fsp ptr. */
5465 if (!check_fsp_open(conn
, req
, fsp
)) {
5469 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5470 if (smb_fname
== NULL
) {
5471 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5475 if(fsp
->fake_file_handle
) {
5477 * This is actually for the QUOTA_FAKE_FILE --metze
5480 /* We know this name is ok, it's already passed the checks. */
5482 } else if(fsp
->fh
->fd
== -1) {
5484 * This is actually a QFILEINFO on a directory
5485 * handle (returned from an NT SMB). NT5.0 seems
5486 * to do this call. JRA.
5489 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5490 /* Always do lstat for UNIX calls. */
5491 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5492 DEBUG(3,("call_trans2qfilepathinfo: "
5493 "SMB_VFS_LSTAT of %s failed "
5495 smb_fname_str_dbg(smb_fname
),
5498 map_nt_error_from_unix(errno
));
5501 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5502 DEBUG(3,("call_trans2qfilepathinfo: "
5503 "SMB_VFS_STAT of %s failed (%s)\n",
5504 smb_fname_str_dbg(smb_fname
),
5507 map_nt_error_from_unix(errno
));
5511 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5512 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5515 * Original code - this is an open file.
5517 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5518 DEBUG(3, ("fstat of %s failed (%s)\n",
5519 fsp_fnum_dbg(fsp
), strerror(errno
)));
5521 map_nt_error_from_unix(errno
));
5524 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5525 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5531 uint32_t ucf_flags
= 0;
5534 if (total_params
< 7) {
5535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5539 info_level
= SVAL(params
,0);
5541 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5543 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5544 if (!lp_unix_extensions()) {
5545 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5548 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5549 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5550 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5551 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5555 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5557 STR_TERMINATE
, &status
);
5558 if (!NT_STATUS_IS_OK(status
)) {
5559 reply_nterror(req
, status
);
5563 status
= filename_convert(req
,
5565 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5570 if (!NT_STATUS_IS_OK(status
)) {
5571 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5572 reply_botherror(req
,
5573 NT_STATUS_PATH_NOT_COVERED
,
5574 ERRSRV
, ERRbadpath
);
5577 reply_nterror(req
, status
);
5581 /* If this is a stream, check if there is a delete_pending. */
5582 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5583 && is_ntfs_stream_smb_fname(smb_fname
)) {
5584 struct smb_filename
*smb_fname_base
;
5586 /* Create an smb_filename with stream_name == NULL. */
5587 smb_fname_base
= synthetic_smb_fname(
5588 talloc_tos(), smb_fname
->base_name
,
5590 if (smb_fname_base
== NULL
) {
5591 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5595 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5596 /* Always do lstat for UNIX calls. */
5597 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5598 DEBUG(3,("call_trans2qfilepathinfo: "
5599 "SMB_VFS_LSTAT of %s failed "
5601 smb_fname_str_dbg(smb_fname_base
),
5603 TALLOC_FREE(smb_fname_base
);
5605 map_nt_error_from_unix(errno
));
5609 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5610 DEBUG(3,("call_trans2qfilepathinfo: "
5611 "fileinfo of %s failed "
5613 smb_fname_str_dbg(smb_fname_base
),
5615 TALLOC_FREE(smb_fname_base
);
5617 map_nt_error_from_unix(errno
));
5622 status
= file_name_hash(conn
,
5623 smb_fname_str_dbg(smb_fname_base
),
5625 if (!NT_STATUS_IS_OK(status
)) {
5626 TALLOC_FREE(smb_fname_base
);
5627 reply_nterror(req
, status
);
5631 fileid
= vfs_file_id_from_sbuf(conn
,
5632 &smb_fname_base
->st
);
5633 TALLOC_FREE(smb_fname_base
);
5634 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5635 if (delete_pending
) {
5636 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5641 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5642 /* Always do lstat for UNIX calls. */
5643 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5644 DEBUG(3,("call_trans2qfilepathinfo: "
5645 "SMB_VFS_LSTAT of %s failed (%s)\n",
5646 smb_fname_str_dbg(smb_fname
),
5649 map_nt_error_from_unix(errno
));
5654 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5655 DEBUG(3,("call_trans2qfilepathinfo: "
5656 "SMB_VFS_STAT of %s failed (%s)\n",
5657 smb_fname_str_dbg(smb_fname
),
5660 map_nt_error_from_unix(errno
));
5665 status
= file_name_hash(conn
,
5666 smb_fname_str_dbg(smb_fname
),
5668 if (!NT_STATUS_IS_OK(status
)) {
5669 reply_nterror(req
, status
);
5673 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5674 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5675 if (delete_pending
) {
5676 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5681 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5682 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5684 info_level
,tran_call
,total_data
));
5686 /* Pull out any data sent here before we realloc. */
5687 switch (info_level
) {
5688 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5690 /* Pull any EA list from the data portion. */
5693 if (total_data
< 4) {
5695 req
, NT_STATUS_INVALID_PARAMETER
);
5698 ea_size
= IVAL(pdata
,0);
5700 if (total_data
> 0 && ea_size
!= total_data
) {
5701 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5702 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5704 req
, NT_STATUS_INVALID_PARAMETER
);
5708 if (!lp_ea_support(SNUM(conn
))) {
5709 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5713 /* Pull out the list of names. */
5714 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5717 req
, NT_STATUS_INVALID_PARAMETER
);
5723 case SMB_QUERY_POSIX_LOCK
:
5725 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5726 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5730 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5732 req
, NT_STATUS_INVALID_PARAMETER
);
5736 /* Copy the lock range data. */
5737 lock_data
= (char *)talloc_memdup(
5738 req
, pdata
, total_data
);
5740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5743 lock_data_count
= total_data
;
5749 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5750 if (*pparams
== NULL
) {
5751 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5758 * draft-leach-cifs-v1-spec-02.txt
5759 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5762 * The requested information is placed in the Data portion of the
5763 * transaction response. For the information levels greater than 0x100,
5764 * the transaction response has 1 parameter word which should be
5765 * ignored by the client.
5767 * However Windows only follows this rule for the IS_NAME_VALID call.
5769 switch (info_level
) {
5770 case SMB_INFO_IS_NAME_VALID
:
5775 if ((info_level
& 0xFF00) == 0xFF00) {
5777 * We use levels that start with 0xFF00
5778 * internally to represent SMB2 specific levels
5780 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5784 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5786 delete_pending
, write_time_ts
,
5788 lock_data_count
, lock_data
,
5789 req
->flags2
, max_data_bytes
,
5791 ppdata
, &data_size
);
5792 if (!NT_STATUS_IS_OK(status
)) {
5793 reply_nterror(req
, status
);
5796 if (fixed_portion
> max_data_bytes
) {
5797 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5801 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5807 /****************************************************************************
5808 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5810 ****************************************************************************/
5812 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5813 connection_struct
*conn
,
5814 struct smb_request
*req
,
5815 bool overwrite_if_exists
,
5816 const struct smb_filename
*smb_fname_old
,
5817 struct smb_filename
*smb_fname_new
)
5819 NTSTATUS status
= NT_STATUS_OK
;
5821 /* source must already exist. */
5822 if (!VALID_STAT(smb_fname_old
->st
)) {
5823 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5826 if (VALID_STAT(smb_fname_new
->st
)) {
5827 if (overwrite_if_exists
) {
5828 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5829 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5831 status
= unlink_internals(conn
,
5833 FILE_ATTRIBUTE_NORMAL
,
5836 if (!NT_STATUS_IS_OK(status
)) {
5840 /* Disallow if newname already exists. */
5841 return NT_STATUS_OBJECT_NAME_COLLISION
;
5845 /* No links from a directory. */
5846 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5847 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5850 /* Setting a hardlink to/from a stream isn't currently supported. */
5851 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5852 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5853 return NT_STATUS_INVALID_PARAMETER
;
5856 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5857 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5859 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5860 smb_fname_new
->base_name
) != 0) {
5861 status
= map_nt_error_from_unix(errno
);
5862 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5863 nt_errstr(status
), smb_fname_old
->base_name
,
5864 smb_fname_new
->base_name
));
5869 /****************************************************************************
5870 Deal with setting the time from any of the setfilepathinfo functions.
5871 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5872 calling this function.
5873 ****************************************************************************/
5875 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5877 const struct smb_filename
*smb_fname
,
5878 struct smb_file_time
*ft
,
5879 bool setting_write_time
)
5881 struct smb_filename smb_fname_base
;
5883 FILE_NOTIFY_CHANGE_LAST_ACCESS
5884 |FILE_NOTIFY_CHANGE_LAST_WRITE
5885 |FILE_NOTIFY_CHANGE_CREATION
;
5887 if (!VALID_STAT(smb_fname
->st
)) {
5888 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5891 /* get some defaults (no modifications) if any info is zero or -1. */
5892 if (null_timespec(ft
->create_time
)) {
5893 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5896 if (null_timespec(ft
->atime
)) {
5897 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5900 if (null_timespec(ft
->mtime
)) {
5901 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5904 if (!setting_write_time
) {
5905 /* ft->mtime comes from change time, not write time. */
5906 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5909 /* Ensure the resolution is the correct for
5910 * what we can store on this filesystem. */
5912 round_timespec(conn
->ts_res
, &ft
->create_time
);
5913 round_timespec(conn
->ts_res
, &ft
->ctime
);
5914 round_timespec(conn
->ts_res
, &ft
->atime
);
5915 round_timespec(conn
->ts_res
, &ft
->mtime
);
5917 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5918 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5919 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5920 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5921 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5922 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5923 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5924 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5926 if (setting_write_time
) {
5928 * This was a Windows setfileinfo on an open file.
5929 * NT does this a lot. We also need to
5930 * set the time here, as it can be read by
5931 * FindFirst/FindNext and with the patch for bug #2045
5932 * in smbd/fileio.c it ensures that this timestamp is
5933 * kept sticky even after a write. We save the request
5934 * away and will set it on file close and after a write. JRA.
5937 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5938 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5941 if (fsp
->base_fsp
) {
5942 set_sticky_write_time_fsp(fsp
->base_fsp
,
5945 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5948 set_sticky_write_time_path(
5949 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5954 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5956 /* Always call ntimes on the base, even if a stream was passed in. */
5957 smb_fname_base
= *smb_fname
;
5958 smb_fname_base
.stream_name
= NULL
;
5960 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5961 return map_nt_error_from_unix(errno
);
5964 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5965 smb_fname
->base_name
);
5966 return NT_STATUS_OK
;
5969 /****************************************************************************
5970 Deal with setting the dosmode from any of the setfilepathinfo functions.
5971 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5972 done before calling this function.
5973 ****************************************************************************/
5975 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5976 const struct smb_filename
*smb_fname
,
5979 struct smb_filename
*smb_fname_base
;
5982 if (!VALID_STAT(smb_fname
->st
)) {
5983 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5986 /* Always operate on the base_name, even if a stream was passed in. */
5987 smb_fname_base
= synthetic_smb_fname(
5988 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5989 if (smb_fname_base
== NULL
) {
5990 return NT_STATUS_NO_MEMORY
;
5994 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5995 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5997 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6001 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6003 /* check the mode isn't different, before changing it */
6004 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6005 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6006 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6007 (unsigned int)dosmode
));
6009 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6011 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6013 smb_fname_str_dbg(smb_fname_base
),
6015 status
= map_nt_error_from_unix(errno
);
6019 status
= NT_STATUS_OK
;
6021 TALLOC_FREE(smb_fname_base
);
6025 /****************************************************************************
6026 Deal with setting the size from any of the setfilepathinfo functions.
6027 ****************************************************************************/
6029 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6030 struct smb_request
*req
,
6032 const struct smb_filename
*smb_fname
,
6033 const SMB_STRUCT_STAT
*psbuf
,
6035 bool fail_after_createfile
)
6037 NTSTATUS status
= NT_STATUS_OK
;
6038 struct smb_filename
*smb_fname_tmp
= NULL
;
6039 files_struct
*new_fsp
= NULL
;
6041 if (!VALID_STAT(*psbuf
)) {
6042 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6045 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6047 if (size
== get_file_size_stat(psbuf
)) {
6048 return NT_STATUS_OK
;
6051 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6052 smb_fname_str_dbg(smb_fname
), (double)size
));
6054 if (fsp
&& fsp
->fh
->fd
!= -1) {
6055 /* Handle based call. */
6056 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6057 return NT_STATUS_ACCESS_DENIED
;
6060 if (vfs_set_filelen(fsp
, size
) == -1) {
6061 return map_nt_error_from_unix(errno
);
6063 trigger_write_time_update_immediate(fsp
);
6064 return NT_STATUS_OK
;
6067 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6068 if (smb_fname_tmp
== NULL
) {
6069 return NT_STATUS_NO_MEMORY
;
6072 smb_fname_tmp
->st
= *psbuf
;
6074 status
= SMB_VFS_CREATE_FILE(
6077 0, /* root_dir_fid */
6078 smb_fname_tmp
, /* fname */
6079 FILE_WRITE_DATA
, /* access_mask */
6080 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6082 FILE_OPEN
, /* create_disposition*/
6083 0, /* create_options */
6084 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6085 0, /* oplock_request */
6087 0, /* allocation_size */
6088 0, /* private_flags */
6091 &new_fsp
, /* result */
6093 NULL
, NULL
); /* create context */
6095 TALLOC_FREE(smb_fname_tmp
);
6097 if (!NT_STATUS_IS_OK(status
)) {
6098 /* NB. We check for open_was_deferred in the caller. */
6102 /* See RAW-SFILEINFO-END-OF-FILE */
6103 if (fail_after_createfile
) {
6104 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6105 return NT_STATUS_INVALID_LEVEL
;
6108 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6109 status
= map_nt_error_from_unix(errno
);
6110 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6114 trigger_write_time_update_immediate(new_fsp
);
6115 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6116 return NT_STATUS_OK
;
6119 /****************************************************************************
6120 Deal with SMB_INFO_SET_EA.
6121 ****************************************************************************/
6123 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6127 const struct smb_filename
*smb_fname
)
6129 struct ea_list
*ea_list
= NULL
;
6130 TALLOC_CTX
*ctx
= NULL
;
6131 NTSTATUS status
= NT_STATUS_OK
;
6133 if (total_data
< 10) {
6135 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6136 length. They seem to have no effect. Bug #3212. JRA */
6138 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6139 /* We're done. We only get EA info in this call. */
6140 return NT_STATUS_OK
;
6143 return NT_STATUS_INVALID_PARAMETER
;
6146 if (IVAL(pdata
,0) > total_data
) {
6147 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6148 IVAL(pdata
,0), (unsigned int)total_data
));
6149 return NT_STATUS_INVALID_PARAMETER
;
6153 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6155 return NT_STATUS_INVALID_PARAMETER
;
6158 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6163 /****************************************************************************
6164 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6165 ****************************************************************************/
6167 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6172 struct ea_list
*ea_list
= NULL
;
6176 return NT_STATUS_INVALID_HANDLE
;
6179 if (!lp_ea_support(SNUM(conn
))) {
6180 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6181 "EA's not supported.\n",
6182 (unsigned int)total_data
));
6183 return NT_STATUS_EAS_NOT_SUPPORTED
;
6186 if (total_data
< 10) {
6187 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6189 (unsigned int)total_data
));
6190 return NT_STATUS_INVALID_PARAMETER
;
6193 ea_list
= read_nttrans_ea_list(talloc_tos(),
6198 return NT_STATUS_INVALID_PARAMETER
;
6201 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6203 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6204 smb_fname_str_dbg(fsp
->fsp_name
),
6205 nt_errstr(status
) ));
6211 /****************************************************************************
6212 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6213 ****************************************************************************/
6215 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6219 struct smb_filename
*smb_fname
)
6221 NTSTATUS status
= NT_STATUS_OK
;
6222 bool delete_on_close
;
6223 uint32_t dosmode
= 0;
6225 if (total_data
< 1) {
6226 return NT_STATUS_INVALID_PARAMETER
;
6230 return NT_STATUS_INVALID_HANDLE
;
6233 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6234 dosmode
= dos_mode(conn
, smb_fname
);
6236 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6237 "delete_on_close = %u\n",
6238 smb_fname_str_dbg(smb_fname
),
6239 (unsigned int)dosmode
,
6240 (unsigned int)delete_on_close
));
6242 if (delete_on_close
) {
6243 status
= can_set_delete_on_close(fsp
, dosmode
);
6244 if (!NT_STATUS_IS_OK(status
)) {
6249 /* The set is across all open files on this dev/inode pair. */
6250 if (!set_delete_on_close(fsp
, delete_on_close
,
6251 conn
->session_info
->security_token
,
6252 conn
->session_info
->unix_token
)) {
6253 return NT_STATUS_ACCESS_DENIED
;
6255 return NT_STATUS_OK
;
6258 /****************************************************************************
6259 Deal with SMB_FILE_POSITION_INFORMATION.
6260 ****************************************************************************/
6262 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6267 uint64_t position_information
;
6269 if (total_data
< 8) {
6270 return NT_STATUS_INVALID_PARAMETER
;
6274 /* Ignore on pathname based set. */
6275 return NT_STATUS_OK
;
6278 position_information
= (uint64_t)IVAL(pdata
,0);
6279 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6281 DEBUG(10,("smb_file_position_information: Set file position "
6282 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6283 (double)position_information
));
6284 fsp
->fh
->position_information
= position_information
;
6285 return NT_STATUS_OK
;
6288 /****************************************************************************
6289 Deal with SMB_FILE_MODE_INFORMATION.
6290 ****************************************************************************/
6292 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6298 if (total_data
< 4) {
6299 return NT_STATUS_INVALID_PARAMETER
;
6301 mode
= IVAL(pdata
,0);
6302 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6303 return NT_STATUS_INVALID_PARAMETER
;
6305 return NT_STATUS_OK
;
6308 /****************************************************************************
6309 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6310 ****************************************************************************/
6312 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6313 struct smb_request
*req
,
6316 const struct smb_filename
*smb_fname
)
6318 char *link_target
= NULL
;
6319 const char *newname
= smb_fname
->base_name
;
6320 TALLOC_CTX
*ctx
= talloc_tos();
6322 /* Set a symbolic link. */
6323 /* Don't allow this if follow links is false. */
6325 if (total_data
== 0) {
6326 return NT_STATUS_INVALID_PARAMETER
;
6329 if (!lp_follow_symlinks(SNUM(conn
))) {
6330 return NT_STATUS_ACCESS_DENIED
;
6333 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6334 total_data
, STR_TERMINATE
);
6337 return NT_STATUS_INVALID_PARAMETER
;
6340 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6341 newname
, link_target
));
6343 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6344 return map_nt_error_from_unix(errno
);
6347 return NT_STATUS_OK
;
6350 /****************************************************************************
6351 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6352 ****************************************************************************/
6354 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6355 struct smb_request
*req
,
6356 const char *pdata
, int total_data
,
6357 struct smb_filename
*smb_fname_new
)
6359 char *oldname
= NULL
;
6360 struct smb_filename
*smb_fname_old
= NULL
;
6361 TALLOC_CTX
*ctx
= talloc_tos();
6362 NTSTATUS status
= NT_STATUS_OK
;
6364 /* Set a hard link. */
6365 if (total_data
== 0) {
6366 return NT_STATUS_INVALID_PARAMETER
;
6369 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6370 total_data
, STR_TERMINATE
, &status
);
6371 if (!NT_STATUS_IS_OK(status
)) {
6375 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6376 smb_fname_str_dbg(smb_fname_new
), oldname
));
6378 status
= filename_convert(ctx
,
6380 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6385 if (!NT_STATUS_IS_OK(status
)) {
6389 return hardlink_internals(ctx
, conn
, req
, false,
6390 smb_fname_old
, smb_fname_new
);
6393 /****************************************************************************
6394 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6395 ****************************************************************************/
6397 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6398 struct smb_request
*req
,
6402 struct smb_filename
*smb_fname_src
)
6406 char *newname
= NULL
;
6407 struct smb_filename
*smb_fname_dst
= NULL
;
6408 NTSTATUS status
= NT_STATUS_OK
;
6409 TALLOC_CTX
*ctx
= talloc_tos();
6412 return NT_STATUS_INVALID_HANDLE
;
6415 if (total_data
< 20) {
6416 return NT_STATUS_INVALID_PARAMETER
;
6419 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6420 len
= IVAL(pdata
,16);
6422 if (len
> (total_data
- 20) || (len
== 0)) {
6423 return NT_STATUS_INVALID_PARAMETER
;
6426 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6427 &pdata
[20], len
, STR_TERMINATE
,
6429 if (!NT_STATUS_IS_OK(status
)) {
6433 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6436 status
= filename_convert(ctx
,
6438 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6443 if (!NT_STATUS_IS_OK(status
)) {
6447 if (fsp
->base_fsp
) {
6448 /* newname must be a stream name. */
6449 if (newname
[0] != ':') {
6450 return NT_STATUS_NOT_SUPPORTED
;
6453 /* Create an smb_fname to call rename_internals_fsp() with. */
6454 smb_fname_dst
= synthetic_smb_fname(
6455 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6457 if (smb_fname_dst
== NULL
) {
6458 status
= NT_STATUS_NO_MEMORY
;
6463 * Set the original last component, since
6464 * rename_internals_fsp() requires it.
6466 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6468 if (smb_fname_dst
->original_lcomp
== NULL
) {
6469 status
= NT_STATUS_NO_MEMORY
;
6475 DEBUG(10,("smb2_file_rename_information: "
6476 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6477 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6478 smb_fname_str_dbg(smb_fname_dst
)));
6479 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6480 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6484 TALLOC_FREE(smb_fname_dst
);
6488 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6489 struct smb_request
*req
,
6493 struct smb_filename
*smb_fname_src
)
6497 char *newname
= NULL
;
6498 struct smb_filename
*smb_fname_dst
= NULL
;
6499 NTSTATUS status
= NT_STATUS_OK
;
6500 TALLOC_CTX
*ctx
= talloc_tos();
6503 return NT_STATUS_INVALID_HANDLE
;
6506 if (total_data
< 20) {
6507 return NT_STATUS_INVALID_PARAMETER
;
6510 overwrite
= (CVAL(pdata
,0) ? true : false);
6511 len
= IVAL(pdata
,16);
6513 if (len
> (total_data
- 20) || (len
== 0)) {
6514 return NT_STATUS_INVALID_PARAMETER
;
6517 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6518 &pdata
[20], len
, STR_TERMINATE
,
6520 if (!NT_STATUS_IS_OK(status
)) {
6524 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6527 status
= filename_convert(ctx
,
6529 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6534 if (!NT_STATUS_IS_OK(status
)) {
6538 if (fsp
->base_fsp
) {
6539 /* No stream names. */
6540 return NT_STATUS_NOT_SUPPORTED
;
6543 DEBUG(10,("smb_file_link_information: "
6544 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6545 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6546 smb_fname_str_dbg(smb_fname_dst
)));
6547 status
= hardlink_internals(ctx
,
6554 TALLOC_FREE(smb_fname_dst
);
6558 /****************************************************************************
6559 Deal with SMB_FILE_RENAME_INFORMATION.
6560 ****************************************************************************/
6562 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6563 struct smb_request
*req
,
6567 struct smb_filename
*smb_fname_src
)
6572 char *newname
= NULL
;
6573 struct smb_filename
*smb_fname_dst
= NULL
;
6574 bool dest_has_wcard
= False
;
6575 NTSTATUS status
= NT_STATUS_OK
;
6577 TALLOC_CTX
*ctx
= talloc_tos();
6579 if (total_data
< 13) {
6580 return NT_STATUS_INVALID_PARAMETER
;
6583 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6584 root_fid
= IVAL(pdata
,4);
6585 len
= IVAL(pdata
,8);
6587 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6588 return NT_STATUS_INVALID_PARAMETER
;
6591 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6594 if (!NT_STATUS_IS_OK(status
)) {
6598 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6601 status
= resolve_dfspath_wcard(ctx
, conn
,
6602 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6605 !conn
->sconn
->using_smb2
,
6608 if (!NT_STATUS_IS_OK(status
)) {
6612 /* Check the new name has no '/' characters. */
6613 if (strchr_m(newname
, '/')) {
6614 return NT_STATUS_NOT_SUPPORTED
;
6617 if (fsp
&& fsp
->base_fsp
) {
6618 /* newname must be a stream name. */
6619 if (newname
[0] != ':') {
6620 return NT_STATUS_NOT_SUPPORTED
;
6623 /* Create an smb_fname to call rename_internals_fsp() with. */
6624 smb_fname_dst
= synthetic_smb_fname(
6625 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6627 if (smb_fname_dst
== NULL
) {
6628 status
= NT_STATUS_NO_MEMORY
;
6633 * Set the original last component, since
6634 * rename_internals_fsp() requires it.
6636 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6638 if (smb_fname_dst
->original_lcomp
== NULL
) {
6639 status
= NT_STATUS_NO_MEMORY
;
6645 * Build up an smb_fname_dst based on the filename passed in.
6646 * We basically just strip off the last component, and put on
6647 * the newname instead.
6649 char *base_name
= NULL
;
6651 /* newname must *not* be a stream name. */
6652 if (newname
[0] == ':') {
6653 return NT_STATUS_NOT_SUPPORTED
;
6657 * Strip off the last component (filename) of the path passed
6660 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6662 return NT_STATUS_NO_MEMORY
;
6664 p
= strrchr_m(base_name
, '/');
6668 base_name
= talloc_strdup(ctx
, "");
6670 return NT_STATUS_NO_MEMORY
;
6673 /* Append the new name. */
6674 base_name
= talloc_asprintf_append(base_name
,
6678 return NT_STATUS_NO_MEMORY
;
6681 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6684 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6687 /* If an error we expect this to be
6688 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6690 if (!NT_STATUS_IS_OK(status
)) {
6691 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6695 /* Create an smb_fname to call rename_internals_fsp() */
6696 smb_fname_dst
= synthetic_smb_fname(
6697 ctx
, base_name
, NULL
, NULL
);
6698 if (smb_fname_dst
== NULL
) {
6699 status
= NT_STATUS_NO_MEMORY
;
6706 DEBUG(10,("smb_file_rename_information: "
6707 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6708 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6709 smb_fname_str_dbg(smb_fname_dst
)));
6710 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6713 DEBUG(10,("smb_file_rename_information: "
6714 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6715 smb_fname_str_dbg(smb_fname_src
),
6716 smb_fname_str_dbg(smb_fname_dst
)));
6717 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6718 smb_fname_dst
, 0, overwrite
, false,
6720 FILE_WRITE_ATTRIBUTES
);
6723 TALLOC_FREE(smb_fname_dst
);
6727 /****************************************************************************
6728 Deal with SMB_SET_POSIX_ACL.
6729 ****************************************************************************/
6731 #if defined(HAVE_POSIX_ACLS)
6732 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6736 const struct smb_filename
*smb_fname
)
6738 uint16_t posix_acl_version
;
6739 uint16_t num_file_acls
;
6740 uint16_t num_def_acls
;
6741 bool valid_file_acls
= True
;
6742 bool valid_def_acls
= True
;
6744 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6745 return NT_STATUS_INVALID_PARAMETER
;
6747 posix_acl_version
= SVAL(pdata
,0);
6748 num_file_acls
= SVAL(pdata
,2);
6749 num_def_acls
= SVAL(pdata
,4);
6751 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6752 valid_file_acls
= False
;
6756 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6757 valid_def_acls
= False
;
6761 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6762 return NT_STATUS_INVALID_PARAMETER
;
6765 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6766 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6767 return NT_STATUS_INVALID_PARAMETER
;
6770 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6771 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6772 (unsigned int)num_file_acls
,
6773 (unsigned int)num_def_acls
));
6775 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6776 smb_fname
->base_name
, num_file_acls
,
6777 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6778 return map_nt_error_from_unix(errno
);
6781 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6782 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6783 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6784 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6785 return map_nt_error_from_unix(errno
);
6787 return NT_STATUS_OK
;
6791 /****************************************************************************
6792 Deal with SMB_SET_POSIX_LOCK.
6793 ****************************************************************************/
6795 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6796 struct smb_request
*req
,
6804 bool blocking_lock
= False
;
6805 enum brl_type lock_type
;
6807 NTSTATUS status
= NT_STATUS_OK
;
6809 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6810 return NT_STATUS_INVALID_HANDLE
;
6813 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6814 return NT_STATUS_INVALID_PARAMETER
;
6817 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6818 case POSIX_LOCK_TYPE_READ
:
6819 lock_type
= READ_LOCK
;
6821 case POSIX_LOCK_TYPE_WRITE
:
6822 /* Return the right POSIX-mappable error code for files opened read-only. */
6823 if (!fsp
->can_write
) {
6824 return NT_STATUS_INVALID_HANDLE
;
6826 lock_type
= WRITE_LOCK
;
6828 case POSIX_LOCK_TYPE_UNLOCK
:
6829 lock_type
= UNLOCK_LOCK
;
6832 return NT_STATUS_INVALID_PARAMETER
;
6835 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6836 blocking_lock
= False
;
6837 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6838 blocking_lock
= True
;
6840 return NT_STATUS_INVALID_PARAMETER
;
6843 if (!lp_blocking_locks(SNUM(conn
))) {
6844 blocking_lock
= False
;
6847 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6848 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6849 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6850 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6851 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6853 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6854 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6856 (unsigned int)lock_type
,
6857 (unsigned long long)smblctx
,
6861 if (lock_type
== UNLOCK_LOCK
) {
6862 status
= do_unlock(req
->sconn
->msg_ctx
,
6869 uint64_t block_smblctx
;
6871 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6882 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6884 * A blocking lock was requested. Package up
6885 * this smb into a queued request and push it
6886 * onto the blocking lock queue.
6888 if(push_blocking_lock_request(br_lck
,
6891 -1, /* infinite timeout. */
6899 TALLOC_FREE(br_lck
);
6903 TALLOC_FREE(br_lck
);
6909 /****************************************************************************
6910 Deal with SMB_SET_FILE_BASIC_INFO.
6911 ****************************************************************************/
6913 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6917 const struct smb_filename
*smb_fname
)
6919 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6920 struct smb_file_time ft
;
6921 uint32_t dosmode
= 0;
6922 NTSTATUS status
= NT_STATUS_OK
;
6926 if (total_data
< 36) {
6927 return NT_STATUS_INVALID_PARAMETER
;
6930 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6931 if (!NT_STATUS_IS_OK(status
)) {
6935 /* Set the attributes */
6936 dosmode
= IVAL(pdata
,32);
6937 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6938 if (!NT_STATUS_IS_OK(status
)) {
6943 ft
.create_time
= interpret_long_date(pdata
);
6946 ft
.atime
= interpret_long_date(pdata
+8);
6949 ft
.mtime
= interpret_long_date(pdata
+16);
6952 ft
.ctime
= interpret_long_date(pdata
+24);
6954 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6955 smb_fname_str_dbg(smb_fname
)));
6957 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6961 /****************************************************************************
6962 Deal with SMB_INFO_STANDARD.
6963 ****************************************************************************/
6965 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6969 const struct smb_filename
*smb_fname
)
6972 struct smb_file_time ft
;
6976 if (total_data
< 12) {
6977 return NT_STATUS_INVALID_PARAMETER
;
6981 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6983 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6985 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6987 DEBUG(10,("smb_set_info_standard: file %s\n",
6988 smb_fname_str_dbg(smb_fname
)));
6990 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6991 if (!NT_STATUS_IS_OK(status
)) {
6995 return smb_set_file_time(conn
,
7002 /****************************************************************************
7003 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7004 ****************************************************************************/
7006 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7007 struct smb_request
*req
,
7011 struct smb_filename
*smb_fname
)
7013 uint64_t allocation_size
= 0;
7014 NTSTATUS status
= NT_STATUS_OK
;
7015 files_struct
*new_fsp
= NULL
;
7017 if (!VALID_STAT(smb_fname
->st
)) {
7018 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7021 if (total_data
< 8) {
7022 return NT_STATUS_INVALID_PARAMETER
;
7025 allocation_size
= (uint64_t)IVAL(pdata
,0);
7026 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7027 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7028 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7029 (double)allocation_size
));
7031 if (allocation_size
) {
7032 allocation_size
= smb_roundup(conn
, allocation_size
);
7035 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7036 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7037 (double)allocation_size
));
7039 if (fsp
&& fsp
->fh
->fd
!= -1) {
7040 /* Open file handle. */
7041 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7042 return NT_STATUS_ACCESS_DENIED
;
7045 /* Only change if needed. */
7046 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7047 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7048 return map_nt_error_from_unix(errno
);
7051 /* But always update the time. */
7053 * This is equivalent to a write. Ensure it's seen immediately
7054 * if there are no pending writes.
7056 trigger_write_time_update_immediate(fsp
);
7057 return NT_STATUS_OK
;
7060 /* Pathname or stat or directory file. */
7061 status
= SMB_VFS_CREATE_FILE(
7064 0, /* root_dir_fid */
7065 smb_fname
, /* fname */
7066 FILE_WRITE_DATA
, /* access_mask */
7067 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7069 FILE_OPEN
, /* create_disposition*/
7070 0, /* create_options */
7071 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7072 0, /* oplock_request */
7074 0, /* allocation_size */
7075 0, /* private_flags */
7078 &new_fsp
, /* result */
7080 NULL
, NULL
); /* create context */
7082 if (!NT_STATUS_IS_OK(status
)) {
7083 /* NB. We check for open_was_deferred in the caller. */
7087 /* Only change if needed. */
7088 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7089 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7090 status
= map_nt_error_from_unix(errno
);
7091 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7096 /* Changing the allocation size should set the last mod time. */
7098 * This is equivalent to a write. Ensure it's seen immediately
7099 * if there are no pending writes.
7101 trigger_write_time_update_immediate(new_fsp
);
7102 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7103 return NT_STATUS_OK
;
7106 /****************************************************************************
7107 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7108 ****************************************************************************/
7110 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7111 struct smb_request
*req
,
7115 const struct smb_filename
*smb_fname
,
7116 bool fail_after_createfile
)
7120 if (total_data
< 8) {
7121 return NT_STATUS_INVALID_PARAMETER
;
7124 size
= IVAL(pdata
,0);
7125 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7126 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7127 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7130 return smb_set_file_size(conn
, req
,
7135 fail_after_createfile
);
7138 /****************************************************************************
7139 Allow a UNIX info mknod.
7140 ****************************************************************************/
7142 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7145 const struct smb_filename
*smb_fname
)
7147 uint32_t file_type
= IVAL(pdata
,56);
7148 #if defined(HAVE_MAKEDEV)
7149 uint32_t dev_major
= IVAL(pdata
,60);
7150 uint32_t dev_minor
= IVAL(pdata
,68);
7152 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7153 uint32_t raw_unixmode
= IVAL(pdata
,84);
7157 if (total_data
< 100) {
7158 return NT_STATUS_INVALID_PARAMETER
;
7161 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7162 PERM_NEW_FILE
, &unixmode
);
7163 if (!NT_STATUS_IS_OK(status
)) {
7167 #if defined(HAVE_MAKEDEV)
7168 dev
= makedev(dev_major
, dev_minor
);
7171 switch (file_type
) {
7172 #if defined(S_IFIFO)
7173 case UNIX_TYPE_FIFO
:
7174 unixmode
|= S_IFIFO
;
7177 #if defined(S_IFSOCK)
7178 case UNIX_TYPE_SOCKET
:
7179 unixmode
|= S_IFSOCK
;
7182 #if defined(S_IFCHR)
7183 case UNIX_TYPE_CHARDEV
:
7184 unixmode
|= S_IFCHR
;
7187 #if defined(S_IFBLK)
7188 case UNIX_TYPE_BLKDEV
:
7189 unixmode
|= S_IFBLK
;
7193 return NT_STATUS_INVALID_PARAMETER
;
7196 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7197 "%.0f mode 0%o for file %s\n", (double)dev
,
7198 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7200 /* Ok - do the mknod. */
7201 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7202 return map_nt_error_from_unix(errno
);
7205 /* If any of the other "set" calls fail we
7206 * don't want to end up with a half-constructed mknod.
7209 if (lp_inherit_permissions(SNUM(conn
))) {
7211 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7213 return NT_STATUS_NO_MEMORY
;
7215 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7217 TALLOC_FREE(parent
);
7220 return NT_STATUS_OK
;
7223 /****************************************************************************
7224 Deal with SMB_SET_FILE_UNIX_BASIC.
7225 ****************************************************************************/
7227 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7228 struct smb_request
*req
,
7232 const struct smb_filename
*smb_fname
)
7234 struct smb_file_time ft
;
7235 uint32_t raw_unixmode
;
7238 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7239 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7240 NTSTATUS status
= NT_STATUS_OK
;
7241 bool delete_on_fail
= False
;
7242 enum perm_type ptype
;
7243 files_struct
*all_fsps
= NULL
;
7244 bool modify_mtime
= true;
7246 struct smb_filename
*smb_fname_tmp
= NULL
;
7247 SMB_STRUCT_STAT sbuf
;
7251 if (total_data
< 100) {
7252 return NT_STATUS_INVALID_PARAMETER
;
7255 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7256 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7257 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7258 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7261 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7262 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7263 set_owner
= (uid_t
)IVAL(pdata
,40);
7264 set_grp
= (gid_t
)IVAL(pdata
,48);
7265 raw_unixmode
= IVAL(pdata
,84);
7267 if (VALID_STAT(smb_fname
->st
)) {
7268 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7269 ptype
= PERM_EXISTING_DIR
;
7271 ptype
= PERM_EXISTING_FILE
;
7274 ptype
= PERM_NEW_FILE
;
7277 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7279 if (!NT_STATUS_IS_OK(status
)) {
7283 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7284 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7285 smb_fname_str_dbg(smb_fname
), (double)size
,
7286 (unsigned int)set_owner
, (unsigned int)set_grp
,
7287 (int)raw_unixmode
));
7289 sbuf
= smb_fname
->st
;
7291 if (!VALID_STAT(sbuf
)) {
7293 * The only valid use of this is to create character and block
7294 * devices, and named pipes. This is deprecated (IMHO) and
7295 * a new info level should be used for mknod. JRA.
7298 status
= smb_unix_mknod(conn
,
7302 if (!NT_STATUS_IS_OK(status
)) {
7306 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7307 if (smb_fname_tmp
== NULL
) {
7308 return NT_STATUS_NO_MEMORY
;
7311 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7312 status
= map_nt_error_from_unix(errno
);
7313 TALLOC_FREE(smb_fname_tmp
);
7314 SMB_VFS_UNLINK(conn
, smb_fname
);
7318 sbuf
= smb_fname_tmp
->st
;
7319 smb_fname
= smb_fname_tmp
;
7321 /* Ensure we don't try and change anything else. */
7322 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7323 size
= get_file_size_stat(&sbuf
);
7324 ft
.atime
= sbuf
.st_ex_atime
;
7325 ft
.mtime
= sbuf
.st_ex_mtime
;
7327 * We continue here as we might want to change the
7330 delete_on_fail
= True
;
7334 /* Horrible backwards compatibility hack as an old server bug
7335 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7339 size
= get_file_size_stat(&sbuf
);
7344 * Deal with the UNIX specific mode set.
7347 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7350 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7351 "setting mode 0%o for file %s\n",
7352 (unsigned int)unixmode
,
7353 smb_fname_str_dbg(smb_fname
)));
7354 if (fsp
&& fsp
->fh
->fd
!= -1) {
7355 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7357 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7360 return map_nt_error_from_unix(errno
);
7365 * Deal with the UNIX specific uid set.
7368 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7369 (sbuf
.st_ex_uid
!= set_owner
)) {
7372 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7373 "changing owner %u for path %s\n",
7374 (unsigned int)set_owner
,
7375 smb_fname_str_dbg(smb_fname
)));
7377 if (fsp
&& fsp
->fh
->fd
!= -1) {
7378 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7381 * UNIX extensions calls must always operate
7384 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7385 set_owner
, (gid_t
)-1);
7389 status
= map_nt_error_from_unix(errno
);
7390 if (delete_on_fail
) {
7391 SMB_VFS_UNLINK(conn
, smb_fname
);
7398 * Deal with the UNIX specific gid set.
7401 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7402 (sbuf
.st_ex_gid
!= set_grp
)) {
7405 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7406 "changing group %u for file %s\n",
7407 (unsigned int)set_owner
,
7408 smb_fname_str_dbg(smb_fname
)));
7409 if (fsp
&& fsp
->fh
->fd
!= -1) {
7410 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7413 * UNIX extensions calls must always operate
7416 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7420 status
= map_nt_error_from_unix(errno
);
7421 if (delete_on_fail
) {
7422 SMB_VFS_UNLINK(conn
, smb_fname
);
7428 /* Deal with any size changes. */
7430 status
= smb_set_file_size(conn
, req
,
7436 if (!NT_STATUS_IS_OK(status
)) {
7440 /* Deal with any time changes. */
7441 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7442 /* No change, don't cancel anything. */
7446 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7447 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7448 all_fsps
= file_find_di_next(all_fsps
)) {
7450 * We're setting the time explicitly for UNIX.
7451 * Cancel any pending changes over all handles.
7453 all_fsps
->update_write_time_on_close
= false;
7454 TALLOC_FREE(all_fsps
->update_write_time_event
);
7458 * Override the "setting_write_time"
7459 * parameter here as it almost does what
7460 * we need. Just remember if we modified
7461 * mtime and send the notify ourselves.
7463 if (null_timespec(ft
.mtime
)) {
7464 modify_mtime
= false;
7467 status
= smb_set_file_time(conn
,
7473 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7474 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7479 /****************************************************************************
7480 Deal with SMB_SET_FILE_UNIX_INFO2.
7481 ****************************************************************************/
7483 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7484 struct smb_request
*req
,
7488 const struct smb_filename
*smb_fname
)
7491 uint32_t smb_fflags
;
7494 if (total_data
< 116) {
7495 return NT_STATUS_INVALID_PARAMETER
;
7498 /* Start by setting all the fields that are common between UNIX_BASIC
7501 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7503 if (!NT_STATUS_IS_OK(status
)) {
7507 smb_fflags
= IVAL(pdata
, 108);
7508 smb_fmask
= IVAL(pdata
, 112);
7510 /* NB: We should only attempt to alter the file flags if the client
7511 * sends a non-zero mask.
7513 if (smb_fmask
!= 0) {
7514 int stat_fflags
= 0;
7516 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7517 smb_fmask
, &stat_fflags
)) {
7518 /* Client asked to alter a flag we don't understand. */
7519 return NT_STATUS_INVALID_PARAMETER
;
7522 if (fsp
&& fsp
->fh
->fd
!= -1) {
7523 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7524 return NT_STATUS_NOT_SUPPORTED
;
7526 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7527 stat_fflags
) != 0) {
7528 return map_nt_error_from_unix(errno
);
7533 /* XXX: need to add support for changing the create_time here. You
7534 * can do this for paths on Darwin with setattrlist(2). The right way
7535 * to hook this up is probably by extending the VFS utimes interface.
7538 return NT_STATUS_OK
;
7541 /****************************************************************************
7542 Create a directory with POSIX semantics.
7543 ****************************************************************************/
7545 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7546 struct smb_request
*req
,
7549 struct smb_filename
*smb_fname
,
7550 int *pdata_return_size
)
7552 NTSTATUS status
= NT_STATUS_OK
;
7553 uint32_t raw_unixmode
= 0;
7554 uint32_t mod_unixmode
= 0;
7555 mode_t unixmode
= (mode_t
)0;
7556 files_struct
*fsp
= NULL
;
7557 uint16_t info_level_return
= 0;
7559 char *pdata
= *ppdata
;
7561 if (total_data
< 18) {
7562 return NT_STATUS_INVALID_PARAMETER
;
7565 raw_unixmode
= IVAL(pdata
,8);
7566 /* Next 4 bytes are not yet defined. */
7568 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7569 PERM_NEW_DIR
, &unixmode
);
7570 if (!NT_STATUS_IS_OK(status
)) {
7574 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7576 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7577 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7579 status
= SMB_VFS_CREATE_FILE(
7582 0, /* root_dir_fid */
7583 smb_fname
, /* fname */
7584 FILE_READ_ATTRIBUTES
, /* access_mask */
7585 FILE_SHARE_NONE
, /* share_access */
7586 FILE_CREATE
, /* create_disposition*/
7587 FILE_DIRECTORY_FILE
, /* create_options */
7588 mod_unixmode
, /* file_attributes */
7589 0, /* oplock_request */
7591 0, /* allocation_size */
7592 0, /* private_flags */
7597 NULL
, NULL
); /* create context */
7599 if (NT_STATUS_IS_OK(status
)) {
7600 close_file(req
, fsp
, NORMAL_CLOSE
);
7603 info_level_return
= SVAL(pdata
,16);
7605 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7606 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7607 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7608 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7610 *pdata_return_size
= 12;
7613 /* Realloc the data size */
7614 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7615 if (*ppdata
== NULL
) {
7616 *pdata_return_size
= 0;
7617 return NT_STATUS_NO_MEMORY
;
7621 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7622 SSVAL(pdata
,2,0); /* No fnum. */
7623 SIVAL(pdata
,4,info
); /* Was directory created. */
7625 switch (info_level_return
) {
7626 case SMB_QUERY_FILE_UNIX_BASIC
:
7627 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7628 SSVAL(pdata
,10,0); /* Padding. */
7629 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7632 case SMB_QUERY_FILE_UNIX_INFO2
:
7633 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7634 SSVAL(pdata
,10,0); /* Padding. */
7635 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7639 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7640 SSVAL(pdata
,10,0); /* Padding. */
7647 /****************************************************************************
7648 Open/Create a file with POSIX semantics.
7649 ****************************************************************************/
7651 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7652 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7654 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7655 struct smb_request
*req
,
7658 struct smb_filename
*smb_fname
,
7659 int *pdata_return_size
)
7661 bool extended_oplock_granted
= False
;
7662 char *pdata
= *ppdata
;
7664 uint32_t wire_open_mode
= 0;
7665 uint32_t raw_unixmode
= 0;
7666 uint32_t mod_unixmode
= 0;
7667 uint32_t create_disp
= 0;
7668 uint32_t access_mask
= 0;
7669 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7670 NTSTATUS status
= NT_STATUS_OK
;
7671 mode_t unixmode
= (mode_t
)0;
7672 files_struct
*fsp
= NULL
;
7673 int oplock_request
= 0;
7675 uint16_t info_level_return
= 0;
7677 if (total_data
< 18) {
7678 return NT_STATUS_INVALID_PARAMETER
;
7681 flags
= IVAL(pdata
,0);
7682 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7683 if (oplock_request
) {
7684 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7687 wire_open_mode
= IVAL(pdata
,4);
7689 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7690 return smb_posix_mkdir(conn
, req
,
7697 switch (wire_open_mode
& SMB_ACCMODE
) {
7699 access_mask
= SMB_O_RDONLY_MAPPING
;
7702 access_mask
= SMB_O_WRONLY_MAPPING
;
7705 access_mask
= (SMB_O_RDONLY_MAPPING
|
7706 SMB_O_WRONLY_MAPPING
);
7709 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7710 (unsigned int)wire_open_mode
));
7711 return NT_STATUS_INVALID_PARAMETER
;
7714 wire_open_mode
&= ~SMB_ACCMODE
;
7716 /* First take care of O_CREAT|O_EXCL interactions. */
7717 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7718 case (SMB_O_CREAT
| SMB_O_EXCL
):
7719 /* File exists fail. File not exist create. */
7720 create_disp
= FILE_CREATE
;
7723 /* File exists open. File not exist create. */
7724 create_disp
= FILE_OPEN_IF
;
7727 /* O_EXCL on its own without O_CREAT is undefined.
7728 We deliberately ignore it as some versions of
7729 Linux CIFSFS can send a bare O_EXCL on the
7730 wire which other filesystems in the kernel
7731 ignore. See bug 9519 for details. */
7736 /* File exists open. File not exist fail. */
7737 create_disp
= FILE_OPEN
;
7740 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7741 (unsigned int)wire_open_mode
));
7742 return NT_STATUS_INVALID_PARAMETER
;
7745 /* Next factor in the effects of O_TRUNC. */
7746 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7748 if (wire_open_mode
& SMB_O_TRUNC
) {
7749 switch (create_disp
) {
7751 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7752 /* Leave create_disp alone as
7753 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7755 /* File exists fail. File not exist create. */
7758 /* SMB_O_CREAT | SMB_O_TRUNC */
7759 /* File exists overwrite. File not exist create. */
7760 create_disp
= FILE_OVERWRITE_IF
;
7764 /* File exists overwrite. File not exist fail. */
7765 create_disp
= FILE_OVERWRITE
;
7768 /* Cannot get here. */
7769 smb_panic("smb_posix_open: logic error");
7770 return NT_STATUS_INVALID_PARAMETER
;
7774 raw_unixmode
= IVAL(pdata
,8);
7775 /* Next 4 bytes are not yet defined. */
7777 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7778 (VALID_STAT(smb_fname
->st
) ?
7779 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7782 if (!NT_STATUS_IS_OK(status
)) {
7786 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7788 if (wire_open_mode
& SMB_O_SYNC
) {
7789 create_options
|= FILE_WRITE_THROUGH
;
7791 if (wire_open_mode
& SMB_O_APPEND
) {
7792 access_mask
|= FILE_APPEND_DATA
;
7794 if (wire_open_mode
& SMB_O_DIRECT
) {
7795 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7798 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7799 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7800 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7801 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7803 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7804 create_options
|= FILE_DIRECTORY_FILE
;
7807 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7808 smb_fname_str_dbg(smb_fname
),
7809 (unsigned int)wire_open_mode
,
7810 (unsigned int)unixmode
));
7812 status
= SMB_VFS_CREATE_FILE(
7815 0, /* root_dir_fid */
7816 smb_fname
, /* fname */
7817 access_mask
, /* access_mask */
7818 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7820 create_disp
, /* create_disposition*/
7821 create_options
, /* create_options */
7822 mod_unixmode
, /* file_attributes */
7823 oplock_request
, /* oplock_request */
7825 0, /* allocation_size */
7826 0, /* private_flags */
7831 NULL
, NULL
); /* create context */
7833 if (!NT_STATUS_IS_OK(status
)) {
7837 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7838 extended_oplock_granted
= True
;
7841 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7842 extended_oplock_granted
= True
;
7845 info_level_return
= SVAL(pdata
,16);
7847 /* Allocate the correct return size. */
7849 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7850 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7851 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7852 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7854 *pdata_return_size
= 12;
7857 /* Realloc the data size */
7858 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7859 if (*ppdata
== NULL
) {
7860 close_file(req
, fsp
, ERROR_CLOSE
);
7861 *pdata_return_size
= 0;
7862 return NT_STATUS_NO_MEMORY
;
7866 if (extended_oplock_granted
) {
7867 if (flags
& REQUEST_BATCH_OPLOCK
) {
7868 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7870 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7872 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7873 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7875 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7878 SSVAL(pdata
,2,fsp
->fnum
);
7879 SIVAL(pdata
,4,info
); /* Was file created etc. */
7881 switch (info_level_return
) {
7882 case SMB_QUERY_FILE_UNIX_BASIC
:
7883 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7884 SSVAL(pdata
,10,0); /* padding. */
7885 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7888 case SMB_QUERY_FILE_UNIX_INFO2
:
7889 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7890 SSVAL(pdata
,10,0); /* padding. */
7891 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7895 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7896 SSVAL(pdata
,10,0); /* padding. */
7899 return NT_STATUS_OK
;
7902 /****************************************************************************
7903 Delete a file with POSIX semantics.
7904 ****************************************************************************/
7906 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7907 struct smb_request
*req
,
7910 struct smb_filename
*smb_fname
)
7912 NTSTATUS status
= NT_STATUS_OK
;
7913 files_struct
*fsp
= NULL
;
7917 int create_options
= 0;
7919 struct share_mode_lock
*lck
= NULL
;
7921 if (total_data
< 2) {
7922 return NT_STATUS_INVALID_PARAMETER
;
7925 flags
= SVAL(pdata
,0);
7927 if (!VALID_STAT(smb_fname
->st
)) {
7928 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7931 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7932 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7933 return NT_STATUS_NOT_A_DIRECTORY
;
7936 DEBUG(10,("smb_posix_unlink: %s %s\n",
7937 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7938 smb_fname_str_dbg(smb_fname
)));
7940 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7941 create_options
|= FILE_DIRECTORY_FILE
;
7944 status
= SMB_VFS_CREATE_FILE(
7947 0, /* root_dir_fid */
7948 smb_fname
, /* fname */
7949 DELETE_ACCESS
, /* access_mask */
7950 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7952 FILE_OPEN
, /* create_disposition*/
7953 create_options
, /* create_options */
7954 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7955 0, /* oplock_request */
7957 0, /* allocation_size */
7958 0, /* private_flags */
7963 NULL
, NULL
); /* create context */
7965 if (!NT_STATUS_IS_OK(status
)) {
7970 * Don't lie to client. If we can't really delete due to
7971 * non-POSIX opens return SHARING_VIOLATION.
7974 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7976 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7977 "lock for file %s\n", fsp_str_dbg(fsp
)));
7978 close_file(req
, fsp
, NORMAL_CLOSE
);
7979 return NT_STATUS_INVALID_PARAMETER
;
7983 * See if others still have the file open. If this is the case, then
7984 * don't delete. If all opens are POSIX delete we can set the delete
7985 * on close disposition.
7987 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7988 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7989 if (is_valid_share_mode_entry(e
)) {
7990 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7993 if (share_mode_stale_pid(lck
->data
, i
)) {
7996 /* Fail with sharing violation. */
7998 close_file(req
, fsp
, NORMAL_CLOSE
);
7999 return NT_STATUS_SHARING_VIOLATION
;
8004 * Set the delete on close.
8006 status
= smb_set_file_disposition_info(conn
,
8014 if (!NT_STATUS_IS_OK(status
)) {
8015 close_file(req
, fsp
, NORMAL_CLOSE
);
8018 return close_file(req
, fsp
, NORMAL_CLOSE
);
8021 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8022 struct smb_request
*req
,
8023 TALLOC_CTX
*mem_ctx
,
8024 uint16_t info_level
,
8026 struct smb_filename
*smb_fname
,
8027 char **ppdata
, int total_data
,
8030 char *pdata
= *ppdata
;
8031 NTSTATUS status
= NT_STATUS_OK
;
8032 int data_return_size
= 0;
8036 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8037 return NT_STATUS_INVALID_LEVEL
;
8040 if (!CAN_WRITE(conn
)) {
8041 /* Allow POSIX opens. The open path will deny
8042 * any non-readonly opens. */
8043 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8044 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8048 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8049 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8051 info_level
, total_data
));
8053 switch (info_level
) {
8055 case SMB_INFO_STANDARD
:
8057 status
= smb_set_info_standard(conn
,
8065 case SMB_INFO_SET_EA
:
8067 status
= smb_info_set_ea(conn
,
8075 case SMB_SET_FILE_BASIC_INFO
:
8076 case SMB_FILE_BASIC_INFORMATION
:
8078 status
= smb_set_file_basic_info(conn
,
8086 case SMB_FILE_ALLOCATION_INFORMATION
:
8087 case SMB_SET_FILE_ALLOCATION_INFO
:
8089 status
= smb_set_file_allocation_info(conn
, req
,
8097 case SMB_FILE_END_OF_FILE_INFORMATION
:
8098 case SMB_SET_FILE_END_OF_FILE_INFO
:
8101 * XP/Win7 both fail after the createfile with
8102 * SMB_SET_FILE_END_OF_FILE_INFO but not
8103 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8104 * The level is known here, so pass it down
8108 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8110 status
= smb_set_file_end_of_file_info(conn
, req
,
8119 case SMB_FILE_DISPOSITION_INFORMATION
:
8120 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8123 /* JRA - We used to just ignore this on a path ?
8124 * Shouldn't this be invalid level on a pathname
8127 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8128 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8131 status
= smb_set_file_disposition_info(conn
,
8139 case SMB_FILE_POSITION_INFORMATION
:
8141 status
= smb_file_position_information(conn
,
8148 case SMB_FILE_FULL_EA_INFORMATION
:
8150 status
= smb_set_file_full_ea_info(conn
,
8157 /* From tridge Samba4 :
8158 * MODE_INFORMATION in setfileinfo (I have no
8159 * idea what "mode information" on a file is - it takes a value of 0,
8160 * 2, 4 or 6. What could it be?).
8163 case SMB_FILE_MODE_INFORMATION
:
8165 status
= smb_file_mode_information(conn
,
8172 * CIFS UNIX extensions.
8175 case SMB_SET_FILE_UNIX_BASIC
:
8177 status
= smb_set_file_unix_basic(conn
, req
,
8185 case SMB_SET_FILE_UNIX_INFO2
:
8187 status
= smb_set_file_unix_info2(conn
, req
,
8195 case SMB_SET_FILE_UNIX_LINK
:
8198 /* We must have a pathname for this. */
8199 return NT_STATUS_INVALID_LEVEL
;
8201 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8202 total_data
, smb_fname
);
8206 case SMB_SET_FILE_UNIX_HLINK
:
8209 /* We must have a pathname for this. */
8210 return NT_STATUS_INVALID_LEVEL
;
8212 status
= smb_set_file_unix_hlink(conn
, req
,
8218 case SMB_FILE_RENAME_INFORMATION
:
8220 status
= smb_file_rename_information(conn
, req
,
8226 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8228 /* SMB2 rename information. */
8229 status
= smb2_file_rename_information(conn
, req
,
8235 case SMB_FILE_LINK_INFORMATION
:
8237 status
= smb_file_link_information(conn
, req
,
8243 #if defined(HAVE_POSIX_ACLS)
8244 case SMB_SET_POSIX_ACL
:
8246 status
= smb_set_posix_acl(conn
,
8255 case SMB_SET_POSIX_LOCK
:
8258 return NT_STATUS_INVALID_LEVEL
;
8260 status
= smb_set_posix_lock(conn
, req
,
8261 pdata
, total_data
, fsp
);
8265 case SMB_POSIX_PATH_OPEN
:
8268 /* We must have a pathname for this. */
8269 return NT_STATUS_INVALID_LEVEL
;
8272 status
= smb_posix_open(conn
, req
,
8280 case SMB_POSIX_PATH_UNLINK
:
8283 /* We must have a pathname for this. */
8284 return NT_STATUS_INVALID_LEVEL
;
8287 status
= smb_posix_unlink(conn
, req
,
8295 return NT_STATUS_INVALID_LEVEL
;
8298 if (!NT_STATUS_IS_OK(status
)) {
8302 *ret_data_size
= data_return_size
;
8303 return NT_STATUS_OK
;
8306 /****************************************************************************
8307 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8308 ****************************************************************************/
8310 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8311 struct smb_request
*req
,
8312 unsigned int tran_call
,
8313 char **pparams
, int total_params
,
8314 char **ppdata
, int total_data
,
8315 unsigned int max_data_bytes
)
8317 char *params
= *pparams
;
8318 char *pdata
= *ppdata
;
8319 uint16_t info_level
;
8320 struct smb_filename
*smb_fname
= NULL
;
8321 files_struct
*fsp
= NULL
;
8322 NTSTATUS status
= NT_STATUS_OK
;
8323 int data_return_size
= 0;
8326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8330 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8331 if (total_params
< 4) {
8332 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8336 fsp
= file_fsp(req
, SVAL(params
,0));
8337 /* Basic check for non-null fsp. */
8338 if (!check_fsp_open(conn
, req
, fsp
)) {
8341 info_level
= SVAL(params
,2);
8343 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8344 if (smb_fname
== NULL
) {
8345 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8349 if(fsp
->fh
->fd
== -1) {
8351 * This is actually a SETFILEINFO on a directory
8352 * handle (returned from an NT SMB). NT5.0 seems
8353 * to do this call. JRA.
8355 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8356 /* Always do lstat for UNIX calls. */
8357 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8358 DEBUG(3,("call_trans2setfilepathinfo: "
8359 "SMB_VFS_LSTAT of %s failed "
8361 smb_fname_str_dbg(smb_fname
),
8363 reply_nterror(req
, map_nt_error_from_unix(errno
));
8367 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8368 DEBUG(3,("call_trans2setfilepathinfo: "
8369 "fileinfo of %s failed (%s)\n",
8370 smb_fname_str_dbg(smb_fname
),
8372 reply_nterror(req
, map_nt_error_from_unix(errno
));
8376 } else if (fsp
->print_file
) {
8378 * Doing a DELETE_ON_CLOSE should cancel a print job.
8380 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8381 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8383 DEBUG(3,("call_trans2setfilepathinfo: "
8384 "Cancelling print job (%s)\n",
8388 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8394 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8399 * Original code - this is an open file.
8401 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8402 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8403 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8405 reply_nterror(req
, map_nt_error_from_unix(errno
));
8411 uint32_t ucf_flags
= 0;
8414 if (total_params
< 7) {
8415 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8419 info_level
= SVAL(params
,0);
8420 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8421 total_params
- 6, STR_TERMINATE
,
8423 if (!NT_STATUS_IS_OK(status
)) {
8424 reply_nterror(req
, status
);
8428 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8429 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8430 info_level
== SMB_FILE_RENAME_INFORMATION
||
8431 info_level
== SMB_POSIX_PATH_UNLINK
) {
8432 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8435 status
= filename_convert(req
, conn
,
8436 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8441 if (!NT_STATUS_IS_OK(status
)) {
8442 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8443 reply_botherror(req
,
8444 NT_STATUS_PATH_NOT_COVERED
,
8445 ERRSRV
, ERRbadpath
);
8448 reply_nterror(req
, status
);
8452 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8454 * For CIFS UNIX extensions the target name may not exist.
8457 /* Always do lstat for UNIX calls. */
8458 SMB_VFS_LSTAT(conn
, smb_fname
);
8460 } else if (!VALID_STAT(smb_fname
->st
) &&
8461 SMB_VFS_STAT(conn
, smb_fname
)) {
8462 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8464 smb_fname_str_dbg(smb_fname
),
8466 reply_nterror(req
, map_nt_error_from_unix(errno
));
8471 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8472 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8474 info_level
,total_data
));
8476 /* Realloc the parameter size */
8477 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8478 if (*pparams
== NULL
) {
8479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8486 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8492 if (!NT_STATUS_IS_OK(status
)) {
8493 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8494 /* We have re-scheduled this call. */
8497 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8498 /* We have re-scheduled this call. */
8501 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8502 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8503 ERRSRV
, ERRbadpath
);
8506 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8507 reply_openerror(req
, status
);
8512 * Invalid EA name needs to return 2 param bytes,
8513 * not a zero-length error packet.
8515 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8516 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8519 reply_nterror(req
, status
);
8524 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8530 /****************************************************************************
8531 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8532 ****************************************************************************/
8534 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8535 char **pparams
, int total_params
,
8536 char **ppdata
, int total_data
,
8537 unsigned int max_data_bytes
)
8539 struct smb_filename
*smb_dname
= NULL
;
8540 char *params
= *pparams
;
8541 char *pdata
= *ppdata
;
8542 char *directory
= NULL
;
8543 NTSTATUS status
= NT_STATUS_OK
;
8544 struct ea_list
*ea_list
= NULL
;
8545 TALLOC_CTX
*ctx
= talloc_tos();
8547 if (!CAN_WRITE(conn
)) {
8548 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8552 if (total_params
< 5) {
8553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8557 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8558 total_params
- 4, STR_TERMINATE
,
8560 if (!NT_STATUS_IS_OK(status
)) {
8561 reply_nterror(req
, status
);
8565 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8567 status
= filename_convert(ctx
,
8569 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8575 if (!NT_STATUS_IS_OK(status
)) {
8576 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8577 reply_botherror(req
,
8578 NT_STATUS_PATH_NOT_COVERED
,
8579 ERRSRV
, ERRbadpath
);
8582 reply_nterror(req
, status
);
8587 * OS/2 workplace shell seems to send SET_EA requests of "null"
8588 * length (4 bytes containing IVAL 4).
8589 * They seem to have no effect. Bug #3212. JRA.
8592 if (total_data
&& (total_data
!= 4)) {
8593 /* Any data in this call is an EA list. */
8594 if (total_data
< 10) {
8595 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8599 if (IVAL(pdata
,0) > total_data
) {
8600 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8601 IVAL(pdata
,0), (unsigned int)total_data
));
8602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8606 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8609 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8613 if (!lp_ea_support(SNUM(conn
))) {
8614 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8618 /* If total_data == 4 Windows doesn't care what values
8619 * are placed in that field, it just ignores them.
8620 * The System i QNTC IBM SMB client puts bad values here,
8621 * so ignore them. */
8623 status
= create_directory(conn
, req
, smb_dname
);
8625 if (!NT_STATUS_IS_OK(status
)) {
8626 reply_nterror(req
, status
);
8630 /* Try and set any given EA. */
8632 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8633 if (!NT_STATUS_IS_OK(status
)) {
8634 reply_nterror(req
, status
);
8639 /* Realloc the parameter and data sizes */
8640 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8641 if(*pparams
== NULL
) {
8642 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8649 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8652 TALLOC_FREE(smb_dname
);
8656 /****************************************************************************
8657 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8658 We don't actually do this - we just send a null response.
8659 ****************************************************************************/
8661 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8662 struct smb_request
*req
,
8663 char **pparams
, int total_params
,
8664 char **ppdata
, int total_data
,
8665 unsigned int max_data_bytes
)
8667 char *params
= *pparams
;
8668 uint16_t info_level
;
8670 if (total_params
< 6) {
8671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8675 info_level
= SVAL(params
,4);
8676 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8678 switch (info_level
) {
8683 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8687 /* Realloc the parameter and data sizes */
8688 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8689 if (*pparams
== NULL
) {
8690 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8695 SSVAL(params
,0,fnf_handle
);
8696 SSVAL(params
,2,0); /* No changes */
8697 SSVAL(params
,4,0); /* No EA errors */
8704 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8709 /****************************************************************************
8710 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8711 changes). Currently this does nothing.
8712 ****************************************************************************/
8714 static void call_trans2findnotifynext(connection_struct
*conn
,
8715 struct smb_request
*req
,
8716 char **pparams
, int total_params
,
8717 char **ppdata
, int total_data
,
8718 unsigned int max_data_bytes
)
8720 char *params
= *pparams
;
8722 DEBUG(3,("call_trans2findnotifynext\n"));
8724 /* Realloc the parameter and data sizes */
8725 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8726 if (*pparams
== NULL
) {
8727 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8732 SSVAL(params
,0,0); /* No changes */
8733 SSVAL(params
,2,0); /* No EA errors */
8735 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8740 /****************************************************************************
8741 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8742 ****************************************************************************/
8744 static void call_trans2getdfsreferral(connection_struct
*conn
,
8745 struct smb_request
*req
,
8746 char **pparams
, int total_params
,
8747 char **ppdata
, int total_data
,
8748 unsigned int max_data_bytes
)
8750 char *params
= *pparams
;
8751 char *pathname
= NULL
;
8753 int max_referral_level
;
8754 NTSTATUS status
= NT_STATUS_OK
;
8755 TALLOC_CTX
*ctx
= talloc_tos();
8757 DEBUG(10,("call_trans2getdfsreferral\n"));
8759 if (total_params
< 3) {
8760 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8764 max_referral_level
= SVAL(params
,0);
8766 if(!lp_host_msdfs()) {
8767 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8771 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8772 total_params
- 2, STR_TERMINATE
);
8774 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8777 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8778 ppdata
,&status
)) < 0) {
8779 reply_nterror(req
, status
);
8783 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8784 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8785 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8790 #define LMCAT_SPL 0x53
8791 #define LMFUNC_GETJOBID 0x60
8793 /****************************************************************************
8794 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8795 ****************************************************************************/
8797 static void call_trans2ioctl(connection_struct
*conn
,
8798 struct smb_request
*req
,
8799 char **pparams
, int total_params
,
8800 char **ppdata
, int total_data
,
8801 unsigned int max_data_bytes
)
8803 char *pdata
= *ppdata
;
8804 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8808 /* check for an invalid fid before proceeding */
8811 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8815 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8816 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8817 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8818 if (*ppdata
== NULL
) {
8819 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8824 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8825 CAN ACCEPT THIS IN UNICODE. JRA. */
8828 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8830 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8831 lp_netbios_name(), 15,
8832 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8833 if (!NT_STATUS_IS_OK(status
)) {
8834 reply_nterror(req
, status
);
8837 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8838 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8839 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8840 if (!NT_STATUS_IS_OK(status
)) {
8841 reply_nterror(req
, status
);
8844 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8849 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8850 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8853 /****************************************************************************
8854 Reply to a SMBfindclose (stop trans2 directory search).
8855 ****************************************************************************/
8857 void reply_findclose(struct smb_request
*req
)
8860 struct smbd_server_connection
*sconn
= req
->sconn
;
8862 START_PROFILE(SMBfindclose
);
8865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8866 END_PROFILE(SMBfindclose
);
8870 dptr_num
= SVALS(req
->vwv
+0, 0);
8872 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8874 dptr_close(sconn
, &dptr_num
);
8876 reply_outbuf(req
, 0, 0);
8878 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8880 END_PROFILE(SMBfindclose
);
8884 /****************************************************************************
8885 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8886 ****************************************************************************/
8888 void reply_findnclose(struct smb_request
*req
)
8892 START_PROFILE(SMBfindnclose
);
8895 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8896 END_PROFILE(SMBfindnclose
);
8900 dptr_num
= SVAL(req
->vwv
+0, 0);
8902 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8904 /* We never give out valid handles for a
8905 findnotifyfirst - so any dptr_num is ok here.
8908 reply_outbuf(req
, 0, 0);
8910 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8912 END_PROFILE(SMBfindnclose
);
8916 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8917 struct trans_state
*state
)
8919 if (get_Protocol() >= PROTOCOL_NT1
) {
8920 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8921 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8924 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8925 if (state
->call
!= TRANSACT2_QFSINFO
&&
8926 state
->call
!= TRANSACT2_SETFSINFO
) {
8927 DEBUG(0,("handle_trans2: encryption required "
8929 (unsigned int)state
->call
));
8930 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8935 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8937 /* Now we must call the relevant TRANS2 function */
8938 switch(state
->call
) {
8939 case TRANSACT2_OPEN
:
8941 START_PROFILE(Trans2_open
);
8942 call_trans2open(conn
, req
,
8943 &state
->param
, state
->total_param
,
8944 &state
->data
, state
->total_data
,
8945 state
->max_data_return
);
8946 END_PROFILE(Trans2_open
);
8950 case TRANSACT2_FINDFIRST
:
8952 START_PROFILE(Trans2_findfirst
);
8953 call_trans2findfirst(conn
, req
,
8954 &state
->param
, state
->total_param
,
8955 &state
->data
, state
->total_data
,
8956 state
->max_data_return
);
8957 END_PROFILE(Trans2_findfirst
);
8961 case TRANSACT2_FINDNEXT
:
8963 START_PROFILE(Trans2_findnext
);
8964 call_trans2findnext(conn
, req
,
8965 &state
->param
, state
->total_param
,
8966 &state
->data
, state
->total_data
,
8967 state
->max_data_return
);
8968 END_PROFILE(Trans2_findnext
);
8972 case TRANSACT2_QFSINFO
:
8974 START_PROFILE(Trans2_qfsinfo
);
8975 call_trans2qfsinfo(conn
, req
,
8976 &state
->param
, state
->total_param
,
8977 &state
->data
, state
->total_data
,
8978 state
->max_data_return
);
8979 END_PROFILE(Trans2_qfsinfo
);
8983 case TRANSACT2_SETFSINFO
:
8985 START_PROFILE(Trans2_setfsinfo
);
8986 call_trans2setfsinfo(conn
, req
,
8987 &state
->param
, state
->total_param
,
8988 &state
->data
, state
->total_data
,
8989 state
->max_data_return
);
8990 END_PROFILE(Trans2_setfsinfo
);
8994 case TRANSACT2_QPATHINFO
:
8995 case TRANSACT2_QFILEINFO
:
8997 START_PROFILE(Trans2_qpathinfo
);
8998 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8999 &state
->param
, state
->total_param
,
9000 &state
->data
, state
->total_data
,
9001 state
->max_data_return
);
9002 END_PROFILE(Trans2_qpathinfo
);
9006 case TRANSACT2_SETPATHINFO
:
9007 case TRANSACT2_SETFILEINFO
:
9009 START_PROFILE(Trans2_setpathinfo
);
9010 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9011 &state
->param
, state
->total_param
,
9012 &state
->data
, state
->total_data
,
9013 state
->max_data_return
);
9014 END_PROFILE(Trans2_setpathinfo
);
9018 case TRANSACT2_FINDNOTIFYFIRST
:
9020 START_PROFILE(Trans2_findnotifyfirst
);
9021 call_trans2findnotifyfirst(conn
, req
,
9022 &state
->param
, state
->total_param
,
9023 &state
->data
, state
->total_data
,
9024 state
->max_data_return
);
9025 END_PROFILE(Trans2_findnotifyfirst
);
9029 case TRANSACT2_FINDNOTIFYNEXT
:
9031 START_PROFILE(Trans2_findnotifynext
);
9032 call_trans2findnotifynext(conn
, req
,
9033 &state
->param
, state
->total_param
,
9034 &state
->data
, state
->total_data
,
9035 state
->max_data_return
);
9036 END_PROFILE(Trans2_findnotifynext
);
9040 case TRANSACT2_MKDIR
:
9042 START_PROFILE(Trans2_mkdir
);
9043 call_trans2mkdir(conn
, req
,
9044 &state
->param
, state
->total_param
,
9045 &state
->data
, state
->total_data
,
9046 state
->max_data_return
);
9047 END_PROFILE(Trans2_mkdir
);
9051 case TRANSACT2_GET_DFS_REFERRAL
:
9053 START_PROFILE(Trans2_get_dfs_referral
);
9054 call_trans2getdfsreferral(conn
, req
,
9055 &state
->param
, state
->total_param
,
9056 &state
->data
, state
->total_data
,
9057 state
->max_data_return
);
9058 END_PROFILE(Trans2_get_dfs_referral
);
9062 case TRANSACT2_IOCTL
:
9064 START_PROFILE(Trans2_ioctl
);
9065 call_trans2ioctl(conn
, req
,
9066 &state
->param
, state
->total_param
,
9067 &state
->data
, state
->total_data
,
9068 state
->max_data_return
);
9069 END_PROFILE(Trans2_ioctl
);
9074 /* Error in request */
9075 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9076 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9080 /****************************************************************************
9081 Reply to a SMBtrans2.
9082 ****************************************************************************/
9084 void reply_trans2(struct smb_request
*req
)
9086 connection_struct
*conn
= req
->conn
;
9091 unsigned int tran_call
;
9092 struct trans_state
*state
;
9095 START_PROFILE(SMBtrans2
);
9097 if (req
->wct
< 14) {
9098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9099 END_PROFILE(SMBtrans2
);
9103 dsoff
= SVAL(req
->vwv
+12, 0);
9104 dscnt
= SVAL(req
->vwv
+11, 0);
9105 psoff
= SVAL(req
->vwv
+10, 0);
9106 pscnt
= SVAL(req
->vwv
+9, 0);
9107 tran_call
= SVAL(req
->vwv
+14, 0);
9109 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9110 if (!NT_STATUS_IS_OK(result
)) {
9111 DEBUG(2, ("Got invalid trans2 request: %s\n",
9112 nt_errstr(result
)));
9113 reply_nterror(req
, result
);
9114 END_PROFILE(SMBtrans2
);
9119 switch (tran_call
) {
9120 /* List the allowed trans2 calls on IPC$ */
9121 case TRANSACT2_OPEN
:
9122 case TRANSACT2_GET_DFS_REFERRAL
:
9123 case TRANSACT2_QFILEINFO
:
9124 case TRANSACT2_QFSINFO
:
9125 case TRANSACT2_SETFSINFO
:
9128 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9129 END_PROFILE(SMBtrans2
);
9134 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9135 DEBUG(0, ("talloc failed\n"));
9136 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9137 END_PROFILE(SMBtrans2
);
9141 state
->cmd
= SMBtrans2
;
9143 state
->mid
= req
->mid
;
9144 state
->vuid
= req
->vuid
;
9145 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9146 state
->setup
= NULL
;
9147 state
->total_param
= SVAL(req
->vwv
+0, 0);
9148 state
->param
= NULL
;
9149 state
->total_data
= SVAL(req
->vwv
+1, 0);
9151 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9152 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9153 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9154 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9155 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9157 state
->call
= tran_call
;
9159 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9160 is so as a sanity check */
9161 if (state
->setup_count
!= 1) {
9163 * Need to have rc=0 for ioctl to get job id for OS/2.
9164 * Network printing will fail if function is not successful.
9165 * Similar function in reply.c will be used if protocol
9166 * is LANMAN1.0 instead of LM1.2X002.
9167 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9168 * outbuf doesn't have to be set(only job id is used).
9170 if ( (state
->setup_count
== 4)
9171 && (tran_call
== TRANSACT2_IOCTL
)
9172 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9173 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9174 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9176 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9177 DEBUG(2,("Transaction is %d\n",tran_call
));
9179 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9180 END_PROFILE(SMBtrans2
);
9185 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9188 if (state
->total_data
) {
9190 if (trans_oob(state
->total_data
, 0, dscnt
)
9191 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9195 /* Can't use talloc here, the core routines do realloc on the
9196 * params and data. */
9197 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9198 if (state
->data
== NULL
) {
9199 DEBUG(0,("reply_trans2: data malloc fail for %u "
9200 "bytes !\n", (unsigned int)state
->total_data
));
9202 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9203 END_PROFILE(SMBtrans2
);
9207 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9210 if (state
->total_param
) {
9212 if (trans_oob(state
->total_param
, 0, pscnt
)
9213 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9217 /* Can't use talloc here, the core routines do realloc on the
9218 * params and data. */
9219 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9220 if (state
->param
== NULL
) {
9221 DEBUG(0,("reply_trans: param malloc fail for %u "
9222 "bytes !\n", (unsigned int)state
->total_param
));
9223 SAFE_FREE(state
->data
);
9225 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9226 END_PROFILE(SMBtrans2
);
9230 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9233 state
->received_data
= dscnt
;
9234 state
->received_param
= pscnt
;
9236 if ((state
->received_param
== state
->total_param
) &&
9237 (state
->received_data
== state
->total_data
)) {
9239 handle_trans2(conn
, req
, state
);
9241 SAFE_FREE(state
->data
);
9242 SAFE_FREE(state
->param
);
9244 END_PROFILE(SMBtrans2
);
9248 DLIST_ADD(conn
->pending_trans
, state
);
9250 /* We need to send an interim response then receive the rest
9251 of the parameter/data bytes */
9252 reply_outbuf(req
, 0, 0);
9253 show_msg((char *)req
->outbuf
);
9254 END_PROFILE(SMBtrans2
);
9259 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9260 SAFE_FREE(state
->data
);
9261 SAFE_FREE(state
->param
);
9263 END_PROFILE(SMBtrans2
);
9264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9268 /****************************************************************************
9269 Reply to a SMBtranss2
9270 ****************************************************************************/
9272 void reply_transs2(struct smb_request
*req
)
9274 connection_struct
*conn
= req
->conn
;
9275 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9276 struct trans_state
*state
;
9278 START_PROFILE(SMBtranss2
);
9280 show_msg((const char *)req
->inbuf
);
9282 /* Windows clients expect all replies to
9283 a transact secondary (SMBtranss2 0x33)
9284 to have a command code of transact
9285 (SMBtrans2 0x32). See bug #8989
9286 and also [MS-CIFS] section 2.2.4.47.2
9289 req
->cmd
= SMBtrans2
;
9292 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9293 END_PROFILE(SMBtranss2
);
9297 for (state
= conn
->pending_trans
; state
!= NULL
;
9298 state
= state
->next
) {
9299 if (state
->mid
== req
->mid
) {
9304 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9305 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9306 END_PROFILE(SMBtranss2
);
9310 /* Revise state->total_param and state->total_data in case they have
9311 changed downwards */
9313 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9314 state
->total_param
= SVAL(req
->vwv
+0, 0);
9315 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9316 state
->total_data
= SVAL(req
->vwv
+1, 0);
9318 pcnt
= SVAL(req
->vwv
+2, 0);
9319 poff
= SVAL(req
->vwv
+3, 0);
9320 pdisp
= SVAL(req
->vwv
+4, 0);
9322 dcnt
= SVAL(req
->vwv
+5, 0);
9323 doff
= SVAL(req
->vwv
+6, 0);
9324 ddisp
= SVAL(req
->vwv
+7, 0);
9326 state
->received_param
+= pcnt
;
9327 state
->received_data
+= dcnt
;
9329 if ((state
->received_data
> state
->total_data
) ||
9330 (state
->received_param
> state
->total_param
))
9334 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9335 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9338 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9342 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9343 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9346 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9349 if ((state
->received_param
< state
->total_param
) ||
9350 (state
->received_data
< state
->total_data
)) {
9351 END_PROFILE(SMBtranss2
);
9355 handle_trans2(conn
, req
, state
);
9357 DLIST_REMOVE(conn
->pending_trans
, state
);
9358 SAFE_FREE(state
->data
);
9359 SAFE_FREE(state
->param
);
9362 END_PROFILE(SMBtranss2
);
9367 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9368 DLIST_REMOVE(conn
->pending_trans
, state
);
9369 SAFE_FREE(state
->data
);
9370 SAFE_FREE(state
->param
);
9372 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9373 END_PROFILE(SMBtranss2
);