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(pdata
+ data_len
, sid_len
,
3800 &conn
->session_info
->security_token
->sids
[i
]);
3801 data_len
+= sid_len
;
3807 case SMB_MAC_QUERY_FS_INFO
:
3809 * Thursby MAC extension... ONLY on NTFS filesystems
3810 * once we do streams then we don't need this
3812 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3814 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3819 return NT_STATUS_INVALID_LEVEL
;
3822 *ret_data_len
= data_len
;
3826 /****************************************************************************
3827 Reply to a TRANS2_QFSINFO (query filesystem info).
3828 ****************************************************************************/
3830 static void call_trans2qfsinfo(connection_struct
*conn
,
3831 struct smb_request
*req
,
3832 char **pparams
, int total_params
,
3833 char **ppdata
, int total_data
,
3834 unsigned int max_data_bytes
)
3836 char *params
= *pparams
;
3837 uint16_t info_level
;
3839 size_t fixed_portion
;
3842 if (total_params
< 2) {
3843 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3847 info_level
= SVAL(params
,0);
3849 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3850 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3851 DEBUG(0,("call_trans2qfsinfo: encryption required "
3852 "and info level 0x%x sent.\n",
3853 (unsigned int)info_level
));
3854 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3859 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3861 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3868 if (!NT_STATUS_IS_OK(status
)) {
3869 reply_nterror(req
, status
);
3873 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3876 DEBUG( 4, ( "%s info_level = %d\n",
3877 smb_fn_name(req
->cmd
), info_level
) );
3882 /****************************************************************************
3883 Reply to a TRANS2_SETFSINFO (set filesystem info).
3884 ****************************************************************************/
3886 static void call_trans2setfsinfo(connection_struct
*conn
,
3887 struct smb_request
*req
,
3888 char **pparams
, int total_params
,
3889 char **ppdata
, int total_data
,
3890 unsigned int max_data_bytes
)
3892 struct smbXsrv_connection
*xconn
= req
->xconn
;
3893 char *pdata
= *ppdata
;
3894 char *params
= *pparams
;
3895 uint16_t info_level
;
3897 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3898 lp_servicename(talloc_tos(), SNUM(conn
))));
3901 if (total_params
< 4) {
3902 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3904 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3908 info_level
= SVAL(params
,2);
3911 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3912 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3913 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3914 "info level (0x%x) on IPC$.\n",
3915 (unsigned int)info_level
));
3916 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3921 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3922 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3923 DEBUG(0,("call_trans2setfsinfo: encryption required "
3924 "and info level 0x%x sent.\n",
3925 (unsigned int)info_level
));
3926 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3931 switch(info_level
) {
3932 case SMB_SET_CIFS_UNIX_INFO
:
3933 if (!lp_unix_extensions()) {
3934 DEBUG(2,("call_trans2setfsinfo: "
3935 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3936 "unix extensions off\n"));
3938 NT_STATUS_INVALID_LEVEL
);
3942 /* There should be 12 bytes of capabilities set. */
3943 if (total_data
< 12) {
3946 NT_STATUS_INVALID_PARAMETER
);
3949 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3950 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3951 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3952 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3953 /* Just print these values for now. */
3954 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3955 "major = %u, minor = %u cap_low = 0x%x, "
3957 (unsigned int)xconn
->
3958 smb1
.unix_info
.client_major
,
3959 (unsigned int)xconn
->
3960 smb1
.unix_info
.client_minor
,
3961 (unsigned int)xconn
->
3962 smb1
.unix_info
.client_cap_low
,
3963 (unsigned int)xconn
->
3964 smb1
.unix_info
.client_cap_high
));
3966 /* Here is where we must switch to posix pathname processing... */
3967 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3968 lp_set_posix_pathnames();
3969 mangle_change_to_posix();
3972 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3973 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3974 /* Client that knows how to do posix locks,
3975 * but not posix open/mkdir operations. Set a
3976 * default type for read/write checks. */
3978 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3983 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3986 size_t param_len
= 0;
3987 size_t data_len
= total_data
;
3989 if (!lp_unix_extensions()) {
3992 NT_STATUS_INVALID_LEVEL
);
3996 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3999 NT_STATUS_NOT_SUPPORTED
);
4003 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4004 DEBUG( 2,("call_trans2setfsinfo: "
4005 "request transport encryption disabled"
4006 "with 'fork echo handler = yes'\n"));
4009 NT_STATUS_NOT_SUPPORTED
);
4013 DEBUG( 4,("call_trans2setfsinfo: "
4014 "request transport encryption.\n"));
4016 status
= srv_request_encryption_setup(conn
,
4017 (unsigned char **)ppdata
,
4019 (unsigned char **)pparams
,
4022 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4023 !NT_STATUS_IS_OK(status
)) {
4024 reply_nterror(req
, status
);
4028 send_trans2_replies(conn
, req
,
4036 if (NT_STATUS_IS_OK(status
)) {
4037 /* Server-side transport
4038 * encryption is now *on*. */
4039 status
= srv_encryption_start(conn
);
4040 if (!NT_STATUS_IS_OK(status
)) {
4041 char *reason
= talloc_asprintf(talloc_tos(),
4042 "Failure in setting "
4043 "up encrypted transport: %s",
4045 exit_server_cleanly(reason
);
4051 case SMB_FS_QUOTA_INFORMATION
:
4053 files_struct
*fsp
= NULL
;
4054 SMB_NTQUOTA_STRUCT quotas
;
4056 ZERO_STRUCT(quotas
);
4059 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4060 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4061 lp_servicename(talloc_tos(), SNUM(conn
)),
4062 conn
->session_info
->unix_info
->unix_name
));
4063 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4067 /* note: normally there're 48 bytes,
4068 * but we didn't use the last 6 bytes for now
4071 fsp
= file_fsp(req
, SVAL(params
,0));
4073 if (!check_fsp_ntquota_handle(conn
, req
,
4075 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4077 req
, NT_STATUS_INVALID_HANDLE
);
4081 if (total_data
< 42) {
4082 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4086 NT_STATUS_INVALID_PARAMETER
);
4090 /* unknown_1 24 NULL bytes in pdata*/
4092 /* the soft quotas 8 bytes (uint64_t)*/
4093 quotas
.softlim
= BVAL(pdata
,24);
4095 /* the hard quotas 8 bytes (uint64_t)*/
4096 quotas
.hardlim
= BVAL(pdata
,32);
4098 /* quota_flags 2 bytes **/
4099 quotas
.qflags
= SVAL(pdata
,40);
4101 /* unknown_2 6 NULL bytes follow*/
4103 /* now set the quotas */
4104 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4105 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4106 reply_nterror(req
, map_nt_error_from_unix(errno
));
4113 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4115 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4121 * sending this reply works fine,
4122 * but I'm not sure it's the same
4123 * like windows do...
4126 reply_outbuf(req
, 10, 0);
4129 #if defined(HAVE_POSIX_ACLS)
4130 /****************************************************************************
4131 Utility function to count the number of entries in a POSIX acl.
4132 ****************************************************************************/
4134 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4136 unsigned int ace_count
= 0;
4137 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4138 SMB_ACL_ENTRY_T entry
;
4140 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4142 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4143 entry_id
= SMB_ACL_NEXT_ENTRY
;
4150 /****************************************************************************
4151 Utility function to marshall a POSIX acl into wire format.
4152 ****************************************************************************/
4154 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4156 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4157 SMB_ACL_ENTRY_T entry
;
4159 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4160 SMB_ACL_TAG_T tagtype
;
4161 SMB_ACL_PERMSET_T permset
;
4162 unsigned char perms
= 0;
4163 unsigned int own_grp
;
4166 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4167 entry_id
= SMB_ACL_NEXT_ENTRY
;
4170 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4171 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4175 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4176 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4180 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4181 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4182 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4184 SCVAL(pdata
,1,perms
);
4187 case SMB_ACL_USER_OBJ
:
4188 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4189 own_grp
= (unsigned int)pst
->st_ex_uid
;
4190 SIVAL(pdata
,2,own_grp
);
4195 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4197 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4200 own_grp
= (unsigned int)*puid
;
4201 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4202 SIVAL(pdata
,2,own_grp
);
4206 case SMB_ACL_GROUP_OBJ
:
4207 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4208 own_grp
= (unsigned int)pst
->st_ex_gid
;
4209 SIVAL(pdata
,2,own_grp
);
4214 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4216 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4219 own_grp
= (unsigned int)*pgid
;
4220 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4221 SIVAL(pdata
,2,own_grp
);
4226 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4227 SIVAL(pdata
,2,0xFFFFFFFF);
4228 SIVAL(pdata
,6,0xFFFFFFFF);
4231 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4232 SIVAL(pdata
,2,0xFFFFFFFF);
4233 SIVAL(pdata
,6,0xFFFFFFFF);
4236 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4239 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4246 /****************************************************************************
4247 Store the FILE_UNIX_BASIC info.
4248 ****************************************************************************/
4250 static char *store_file_unix_basic(connection_struct
*conn
,
4253 const SMB_STRUCT_STAT
*psbuf
)
4255 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4258 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4259 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4261 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4264 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4267 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4268 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4269 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4272 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4276 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4280 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4283 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4284 devno
= psbuf
->st_ex_rdev
;
4286 devno
= psbuf
->st_ex_dev
;
4289 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4293 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4297 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4300 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4304 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4311 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4312 * the chflags(2) (or equivalent) flags.
4314 * XXX: this really should be behind the VFS interface. To do this, we would
4315 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4316 * Each VFS module could then implement its own mapping as appropriate for the
4317 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4319 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4323 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4327 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4331 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4335 { UF_HIDDEN
, EXT_HIDDEN
},
4338 /* Do not remove. We need to guarantee that this array has at least one
4339 * entry to build on HP-UX.
4345 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4346 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4350 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4351 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4352 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4353 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4358 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4359 const uint32_t smb_fflags
,
4360 const uint32_t smb_fmask
,
4363 uint32_t max_fmask
= 0;
4366 *stat_fflags
= psbuf
->st_ex_flags
;
4368 /* For each flags requested in smb_fmask, check the state of the
4369 * corresponding flag in smb_fflags and set or clear the matching
4373 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4374 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4375 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4376 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4377 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4379 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4384 /* If smb_fmask is asking to set any bits that are not supported by
4385 * our flag mappings, we should fail.
4387 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4395 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4396 * of file flags and birth (create) time.
4398 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4401 const SMB_STRUCT_STAT
*psbuf
)
4403 uint32_t file_flags
= 0;
4404 uint32_t flags_mask
= 0;
4406 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4408 /* Create (birth) time 64 bit */
4409 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4412 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4413 SIVAL(pdata
, 0, file_flags
); /* flags */
4414 SIVAL(pdata
, 4, flags_mask
); /* mask */
4420 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4421 const struct stream_struct
*streams
,
4423 unsigned int max_data_bytes
,
4424 unsigned int *data_size
)
4427 unsigned int ofs
= 0;
4429 if (max_data_bytes
< 32) {
4430 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4433 for (i
= 0; i
< num_streams
; i
++) {
4434 unsigned int next_offset
;
4436 smb_ucs2_t
*namebuf
;
4438 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4439 streams
[i
].name
, &namelen
) ||
4442 return NT_STATUS_INVALID_PARAMETER
;
4446 * name_buf is now null-terminated, we need to marshall as not
4453 * We cannot overflow ...
4455 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4456 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4458 TALLOC_FREE(namebuf
);
4459 return STATUS_BUFFER_OVERFLOW
;
4462 SIVAL(data
, ofs
+4, namelen
);
4463 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4464 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4465 memcpy(data
+ofs
+24, namebuf
, namelen
);
4466 TALLOC_FREE(namebuf
);
4468 next_offset
= ofs
+ 24 + namelen
;
4470 if (i
== num_streams
-1) {
4471 SIVAL(data
, ofs
, 0);
4474 unsigned int align
= ndr_align_size(next_offset
, 8);
4476 if ((next_offset
+ align
) > max_data_bytes
) {
4477 DEBUG(10, ("refusing to overflow align "
4478 "reply at stream %u\n",
4480 TALLOC_FREE(namebuf
);
4481 return STATUS_BUFFER_OVERFLOW
;
4484 memset(data
+next_offset
, 0, align
);
4485 next_offset
+= align
;
4487 SIVAL(data
, ofs
, next_offset
- ofs
);
4494 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4498 return NT_STATUS_OK
;
4501 /****************************************************************************
4502 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4503 ****************************************************************************/
4505 static void call_trans2qpipeinfo(connection_struct
*conn
,
4506 struct smb_request
*req
,
4507 unsigned int tran_call
,
4508 char **pparams
, int total_params
,
4509 char **ppdata
, int total_data
,
4510 unsigned int max_data_bytes
)
4512 char *params
= *pparams
;
4513 char *pdata
= *ppdata
;
4514 unsigned int data_size
= 0;
4515 unsigned int param_size
= 2;
4516 uint16_t info_level
;
4520 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4524 if (total_params
< 4) {
4525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4529 fsp
= file_fsp(req
, SVAL(params
,0));
4530 if (!fsp_is_np(fsp
)) {
4531 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4535 info_level
= SVAL(params
,2);
4537 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4538 if (*pparams
== NULL
) {
4539 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4544 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4545 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4548 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4549 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4550 if (*ppdata
== NULL
) {
4551 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4556 switch (info_level
) {
4557 case SMB_FILE_STANDARD_INFORMATION
:
4559 SOFF_T(pdata
,0,4096LL);
4566 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4570 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4576 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4577 TALLOC_CTX
*mem_ctx
,
4578 uint16_t info_level
,
4580 struct smb_filename
*smb_fname
,
4581 bool delete_pending
,
4582 struct timespec write_time_ts
,
4583 struct ea_list
*ea_list
,
4584 int lock_data_count
,
4587 unsigned int max_data_bytes
,
4588 size_t *fixed_portion
,
4590 unsigned int *pdata_size
)
4592 char *pdata
= *ppdata
;
4593 char *dstart
, *dend
;
4594 unsigned int data_size
;
4595 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4596 time_t create_time
, mtime
, atime
, c_time
;
4597 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4604 uint64_t file_size
= 0;
4606 uint64_t allocation_size
= 0;
4607 uint64_t file_index
= 0;
4608 uint32_t access_mask
= 0;
4611 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4612 return NT_STATUS_INVALID_LEVEL
;
4615 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4616 smb_fname_str_dbg(smb_fname
),
4618 info_level
, max_data_bytes
));
4620 mode
= dos_mode(conn
, smb_fname
);
4621 nlink
= psbuf
->st_ex_nlink
;
4623 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4627 if ((nlink
> 0) && delete_pending
) {
4631 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4632 return NT_STATUS_INVALID_PARAMETER
;
4635 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4636 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4637 if (*ppdata
== NULL
) {
4638 return NT_STATUS_NO_MEMORY
;
4642 dend
= dstart
+ data_size
- 1;
4644 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4645 update_stat_ex_mtime(psbuf
, write_time_ts
);
4648 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4649 mtime_ts
= psbuf
->st_ex_mtime
;
4650 atime_ts
= psbuf
->st_ex_atime
;
4651 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4653 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4654 dos_filetime_timespec(&create_time_ts
);
4655 dos_filetime_timespec(&mtime_ts
);
4656 dos_filetime_timespec(&atime_ts
);
4657 dos_filetime_timespec(&ctime_ts
);
4660 create_time
= convert_timespec_to_time_t(create_time_ts
);
4661 mtime
= convert_timespec_to_time_t(mtime_ts
);
4662 atime
= convert_timespec_to_time_t(atime_ts
);
4663 c_time
= convert_timespec_to_time_t(ctime_ts
);
4665 p
= strrchr_m(smb_fname
->base_name
,'/');
4667 base_name
= smb_fname
->base_name
;
4671 /* NT expects the name to be in an exact form of the *full*
4672 filename. See the trans2 torture test */
4673 if (ISDOT(base_name
)) {
4674 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4676 return NT_STATUS_NO_MEMORY
;
4679 dos_fname
= talloc_asprintf(mem_ctx
,
4681 smb_fname
->base_name
);
4683 return NT_STATUS_NO_MEMORY
;
4685 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4686 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4687 smb_fname
->stream_name
);
4689 return NT_STATUS_NO_MEMORY
;
4693 string_replace(dos_fname
, '/', '\\');
4696 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4699 /* Do we have this path open ? */
4701 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4702 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4703 if (fsp1
&& fsp1
->initial_allocation_size
) {
4704 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4708 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4709 file_size
= get_file_size_stat(psbuf
);
4713 pos
= fsp
->fh
->position_information
;
4717 access_mask
= fsp
->access_mask
;
4719 /* GENERIC_EXECUTE mapping from Windows */
4720 access_mask
= 0x12019F;
4723 /* This should be an index number - looks like
4726 I think this causes us to fail the IFSKIT
4727 BasicFileInformationTest. -tpot */
4728 file_index
= get_FileIndex(conn
, psbuf
);
4732 switch (info_level
) {
4733 case SMB_INFO_STANDARD
:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4736 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4737 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4738 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4739 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4740 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4741 SSVAL(pdata
,l1_attrFile
,mode
);
4744 case SMB_INFO_QUERY_EA_SIZE
:
4746 unsigned int ea_size
=
4747 estimate_ea_size(conn
, fsp
,
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4751 srv_put_dos_date2(pdata
,0,create_time
);
4752 srv_put_dos_date2(pdata
,4,atime
);
4753 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4754 SIVAL(pdata
,12,(uint32_t)file_size
);
4755 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4756 SSVAL(pdata
,20,mode
);
4757 SIVAL(pdata
,22,ea_size
);
4761 case SMB_INFO_IS_NAME_VALID
:
4762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4764 /* os/2 needs this ? really ?*/
4765 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4767 /* This is only reached for qpathinfo */
4771 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4773 size_t total_ea_len
= 0;
4774 struct ea_list
*ea_file_list
= NULL
;
4775 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4778 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4780 &total_ea_len
, &ea_file_list
);
4781 if (!NT_STATUS_IS_OK(status
)) {
4785 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4787 if (!ea_list
|| (total_ea_len
> data_size
)) {
4789 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4793 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4797 case SMB_INFO_QUERY_ALL_EAS
:
4799 /* We have data_size bytes to put EA's into. */
4800 size_t total_ea_len
= 0;
4801 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4803 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4805 &total_ea_len
, &ea_list
);
4806 if (!NT_STATUS_IS_OK(status
)) {
4810 if (!ea_list
|| (total_ea_len
> data_size
)) {
4812 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4816 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4820 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4822 /* This is FileFullEaInformation - 0xF which maps to
4823 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4825 /* We have data_size bytes to put EA's into. */
4826 size_t total_ea_len
= 0;
4827 struct ea_list
*ea_file_list
= NULL
;
4829 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4831 /*TODO: add filtering and index handling */
4834 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4836 &total_ea_len
, &ea_file_list
);
4837 if (!NT_STATUS_IS_OK(status
)) {
4840 if (!ea_file_list
) {
4841 return NT_STATUS_NO_EAS_ON_FILE
;
4844 status
= fill_ea_chained_buffer(mem_ctx
,
4848 conn
, ea_file_list
);
4849 if (!NT_STATUS_IS_OK(status
)) {
4855 case SMB_FILE_BASIC_INFORMATION
:
4856 case SMB_QUERY_FILE_BASIC_INFO
:
4858 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4859 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4860 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4862 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4866 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4867 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4868 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4869 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4870 SIVAL(pdata
,32,mode
);
4872 DEBUG(5,("SMB_QFBI - "));
4873 DEBUG(5,("create: %s ", ctime(&create_time
)));
4874 DEBUG(5,("access: %s ", ctime(&atime
)));
4875 DEBUG(5,("write: %s ", ctime(&mtime
)));
4876 DEBUG(5,("change: %s ", ctime(&c_time
)));
4877 DEBUG(5,("mode: %x\n", mode
));
4878 *fixed_portion
= data_size
;
4881 case SMB_FILE_STANDARD_INFORMATION
:
4882 case SMB_QUERY_FILE_STANDARD_INFO
:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4886 SOFF_T(pdata
,0,allocation_size
);
4887 SOFF_T(pdata
,8,file_size
);
4888 SIVAL(pdata
,16,nlink
);
4889 SCVAL(pdata
,20,delete_pending
?1:0);
4890 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4891 SSVAL(pdata
,22,0); /* Padding. */
4892 *fixed_portion
= 24;
4895 case SMB_FILE_EA_INFORMATION
:
4896 case SMB_QUERY_FILE_EA_INFO
:
4898 unsigned int ea_size
=
4899 estimate_ea_size(conn
, fsp
, smb_fname
);
4900 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4903 SIVAL(pdata
,0,ea_size
);
4907 /* Get the 8.3 name - used if NT SMB was negotiated. */
4908 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4909 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4911 char mangled_name
[13];
4912 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4913 if (!name_to_8_3(base_name
,mangled_name
,
4914 True
,conn
->params
)) {
4915 return NT_STATUS_NO_MEMORY
;
4917 status
= srvstr_push(dstart
, flags2
,
4918 pdata
+4, mangled_name
,
4919 PTR_DIFF(dend
, pdata
+4),
4921 if (!NT_STATUS_IS_OK(status
)) {
4924 data_size
= 4 + len
;
4930 case SMB_QUERY_FILE_NAME_INFO
:
4933 this must be *exactly* right for ACLs on mapped drives to work
4935 status
= srvstr_push(dstart
, flags2
,
4937 PTR_DIFF(dend
, pdata
+4),
4939 if (!NT_STATUS_IS_OK(status
)) {
4942 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4943 data_size
= 4 + len
;
4948 case SMB_FILE_ALLOCATION_INFORMATION
:
4949 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4950 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4952 SOFF_T(pdata
,0,allocation_size
);
4955 case SMB_FILE_END_OF_FILE_INFORMATION
:
4956 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4957 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4959 SOFF_T(pdata
,0,file_size
);
4962 case SMB_QUERY_FILE_ALL_INFO
:
4963 case SMB_FILE_ALL_INFORMATION
:
4965 unsigned int ea_size
=
4966 estimate_ea_size(conn
, fsp
, smb_fname
);
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4968 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4969 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4970 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4971 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4972 SIVAL(pdata
,32,mode
);
4973 SIVAL(pdata
,36,0); /* padding. */
4975 SOFF_T(pdata
,0,allocation_size
);
4976 SOFF_T(pdata
,8,file_size
);
4977 SIVAL(pdata
,16,nlink
);
4978 SCVAL(pdata
,20,delete_pending
);
4979 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4982 SIVAL(pdata
,0,ea_size
);
4983 pdata
+= 4; /* EA info */
4984 status
= srvstr_push(dstart
, flags2
,
4986 PTR_DIFF(dend
, pdata
+4),
4988 if (!NT_STATUS_IS_OK(status
)) {
4993 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4994 *fixed_portion
= 10;
4998 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5000 unsigned int ea_size
=
5001 estimate_ea_size(conn
, fsp
, smb_fname
);
5002 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5003 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5004 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5005 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5006 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5007 SIVAL(pdata
, 0x20, mode
);
5008 SIVAL(pdata
, 0x24, 0); /* padding. */
5009 SBVAL(pdata
, 0x28, allocation_size
);
5010 SBVAL(pdata
, 0x30, file_size
);
5011 SIVAL(pdata
, 0x38, nlink
);
5012 SCVAL(pdata
, 0x3C, delete_pending
);
5013 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5014 SSVAL(pdata
, 0x3E, 0); /* padding */
5015 SBVAL(pdata
, 0x40, file_index
);
5016 SIVAL(pdata
, 0x48, ea_size
);
5017 SIVAL(pdata
, 0x4C, access_mask
);
5018 SBVAL(pdata
, 0x50, pos
);
5019 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5020 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5024 status
= srvstr_push(dstart
, flags2
,
5026 PTR_DIFF(dend
, pdata
+4),
5028 if (!NT_STATUS_IS_OK(status
)) {
5033 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5034 *fixed_portion
= 104;
5037 case SMB_FILE_INTERNAL_INFORMATION
:
5039 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5040 SBVAL(pdata
, 0, file_index
);
5045 case SMB_FILE_ACCESS_INFORMATION
:
5046 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5047 SIVAL(pdata
, 0, access_mask
);
5052 case SMB_FILE_NAME_INFORMATION
:
5053 /* Pathname with leading '\'. */
5056 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5058 SIVAL(pdata
,0,byte_len
);
5059 data_size
= 4 + byte_len
;
5063 case SMB_FILE_DISPOSITION_INFORMATION
:
5064 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5066 SCVAL(pdata
,0,delete_pending
);
5070 case SMB_FILE_POSITION_INFORMATION
:
5071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5073 SOFF_T(pdata
,0,pos
);
5077 case SMB_FILE_MODE_INFORMATION
:
5078 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5079 SIVAL(pdata
,0,mode
);
5084 case SMB_FILE_ALIGNMENT_INFORMATION
:
5085 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5086 SIVAL(pdata
,0,0); /* No alignment needed. */
5092 * NT4 server just returns "invalid query" to this - if we try
5093 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5096 /* The first statement above is false - verified using Thursby
5097 * client against NT4 -- gcolley.
5099 case SMB_QUERY_FILE_STREAM_INFO
:
5100 case SMB_FILE_STREAM_INFORMATION
: {
5101 unsigned int num_streams
= 0;
5102 struct stream_struct
*streams
= NULL
;
5104 DEBUG(10,("smbd_do_qfilepathinfo: "
5105 "SMB_FILE_STREAM_INFORMATION\n"));
5107 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5108 return NT_STATUS_INVALID_PARAMETER
;
5111 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5112 talloc_tos(), &num_streams
, &streams
);
5114 if (!NT_STATUS_IS_OK(status
)) {
5115 DEBUG(10, ("could not get stream info: %s\n",
5116 nt_errstr(status
)));
5120 status
= marshall_stream_info(num_streams
, streams
,
5121 pdata
, max_data_bytes
,
5124 if (!NT_STATUS_IS_OK(status
)) {
5125 DEBUG(10, ("marshall_stream_info failed: %s\n",
5126 nt_errstr(status
)));
5127 TALLOC_FREE(streams
);
5131 TALLOC_FREE(streams
);
5133 *fixed_portion
= 32;
5137 case SMB_QUERY_COMPRESSION_INFO
:
5138 case SMB_FILE_COMPRESSION_INFORMATION
:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5140 SOFF_T(pdata
,0,file_size
);
5141 SIVAL(pdata
,8,0); /* ??? */
5142 SIVAL(pdata
,12,0); /* ??? */
5144 *fixed_portion
= 16;
5147 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5148 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5149 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5150 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5151 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5152 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5153 SOFF_T(pdata
,32,allocation_size
);
5154 SOFF_T(pdata
,40,file_size
);
5155 SIVAL(pdata
,48,mode
);
5156 SIVAL(pdata
,52,0); /* ??? */
5158 *fixed_portion
= 56;
5161 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5162 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5163 SIVAL(pdata
,0,mode
);
5170 * CIFS UNIX Extensions.
5173 case SMB_QUERY_FILE_UNIX_BASIC
:
5175 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5176 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5178 DEBUG(4,("smbd_do_qfilepathinfo: "
5179 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5180 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5184 case SMB_QUERY_FILE_UNIX_INFO2
:
5186 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5187 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5191 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5193 for (i
=0; i
<100; i
++)
5194 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5200 case SMB_QUERY_FILE_UNIX_LINK
:
5203 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5206 return NT_STATUS_NO_MEMORY
;
5209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5211 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5212 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5215 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5217 link_len
= SMB_VFS_READLINK(conn
,
5218 smb_fname
->base_name
,
5220 if (link_len
== -1) {
5221 return map_nt_error_from_unix(errno
);
5223 buffer
[link_len
] = 0;
5224 status
= srvstr_push(dstart
, flags2
,
5226 PTR_DIFF(dend
, pdata
),
5227 STR_TERMINATE
, &len
);
5228 if (!NT_STATUS_IS_OK(status
)) {
5232 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5237 #if defined(HAVE_POSIX_ACLS)
5238 case SMB_QUERY_POSIX_ACL
:
5240 SMB_ACL_T file_acl
= NULL
;
5241 SMB_ACL_T def_acl
= NULL
;
5242 uint16_t num_file_acls
= 0;
5243 uint16_t num_def_acls
= 0;
5245 if (fsp
&& fsp
->fh
->fd
!= -1) {
5246 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5250 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5251 smb_fname
->base_name
,
5252 SMB_ACL_TYPE_ACCESS
,
5256 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5257 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5258 "not implemented on "
5259 "filesystem containing %s\n",
5260 smb_fname
->base_name
));
5261 return NT_STATUS_NOT_IMPLEMENTED
;
5264 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5265 if (fsp
&& fsp
->is_directory
) {
5267 SMB_VFS_SYS_ACL_GET_FILE(
5269 fsp
->fsp_name
->base_name
,
5270 SMB_ACL_TYPE_DEFAULT
,
5274 SMB_VFS_SYS_ACL_GET_FILE(
5276 smb_fname
->base_name
,
5277 SMB_ACL_TYPE_DEFAULT
,
5280 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5283 num_file_acls
= count_acl_entries(conn
, file_acl
);
5284 num_def_acls
= count_acl_entries(conn
, def_acl
);
5286 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5287 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5289 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5290 SMB_POSIX_ACL_HEADER_SIZE
) ));
5292 TALLOC_FREE(file_acl
);
5295 TALLOC_FREE(def_acl
);
5297 return NT_STATUS_BUFFER_TOO_SMALL
;
5300 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5301 SSVAL(pdata
,2,num_file_acls
);
5302 SSVAL(pdata
,4,num_def_acls
);
5303 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5305 TALLOC_FREE(file_acl
);
5308 TALLOC_FREE(def_acl
);
5310 return NT_STATUS_INTERNAL_ERROR
;
5312 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5314 TALLOC_FREE(file_acl
);
5317 TALLOC_FREE(def_acl
);
5319 return NT_STATUS_INTERNAL_ERROR
;
5323 TALLOC_FREE(file_acl
);
5326 TALLOC_FREE(def_acl
);
5328 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5334 case SMB_QUERY_POSIX_LOCK
:
5339 enum brl_type lock_type
;
5341 /* We need an open file with a real fd for this. */
5342 if (!fsp
|| fsp
->fh
->fd
== -1) {
5343 return NT_STATUS_INVALID_LEVEL
;
5346 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5347 return NT_STATUS_INVALID_PARAMETER
;
5350 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5351 case POSIX_LOCK_TYPE_READ
:
5352 lock_type
= READ_LOCK
;
5354 case POSIX_LOCK_TYPE_WRITE
:
5355 lock_type
= WRITE_LOCK
;
5357 case POSIX_LOCK_TYPE_UNLOCK
:
5359 /* There's no point in asking for an unlock... */
5360 return NT_STATUS_INVALID_PARAMETER
;
5363 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5364 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5365 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5367 status
= query_lock(fsp
,
5374 if (ERROR_WAS_LOCK_DENIED(status
)) {
5375 /* Here we need to report who has it locked... */
5376 data_size
= POSIX_LOCK_DATA_SIZE
;
5378 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5379 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5380 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5381 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5382 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5384 } else if (NT_STATUS_IS_OK(status
)) {
5385 /* For success we just return a copy of what we sent
5386 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5387 data_size
= POSIX_LOCK_DATA_SIZE
;
5388 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5389 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5397 return NT_STATUS_INVALID_LEVEL
;
5400 *pdata_size
= data_size
;
5401 return NT_STATUS_OK
;
5404 /****************************************************************************
5405 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5406 file name or file id).
5407 ****************************************************************************/
5409 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5410 struct smb_request
*req
,
5411 unsigned int tran_call
,
5412 char **pparams
, int total_params
,
5413 char **ppdata
, int total_data
,
5414 unsigned int max_data_bytes
)
5416 char *params
= *pparams
;
5417 char *pdata
= *ppdata
;
5418 uint16_t info_level
;
5419 unsigned int data_size
= 0;
5420 unsigned int param_size
= 2;
5421 struct smb_filename
*smb_fname
= NULL
;
5422 bool delete_pending
= False
;
5423 struct timespec write_time_ts
;
5424 files_struct
*fsp
= NULL
;
5425 struct file_id fileid
;
5426 struct ea_list
*ea_list
= NULL
;
5427 int lock_data_count
= 0;
5428 char *lock_data
= NULL
;
5429 size_t fixed_portion
;
5430 NTSTATUS status
= NT_STATUS_OK
;
5433 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5437 ZERO_STRUCT(write_time_ts
);
5439 if (tran_call
== TRANSACT2_QFILEINFO
) {
5440 if (total_params
< 4) {
5441 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5446 call_trans2qpipeinfo(conn
, req
, tran_call
,
5447 pparams
, total_params
,
5453 fsp
= file_fsp(req
, SVAL(params
,0));
5454 info_level
= SVAL(params
,2);
5456 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5458 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5459 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5463 /* Initial check for valid fsp ptr. */
5464 if (!check_fsp_open(conn
, req
, fsp
)) {
5468 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5469 if (smb_fname
== NULL
) {
5470 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5474 if(fsp
->fake_file_handle
) {
5476 * This is actually for the QUOTA_FAKE_FILE --metze
5479 /* We know this name is ok, it's already passed the checks. */
5481 } else if(fsp
->fh
->fd
== -1) {
5483 * This is actually a QFILEINFO on a directory
5484 * handle (returned from an NT SMB). NT5.0 seems
5485 * to do this call. JRA.
5488 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5489 /* Always do lstat for UNIX calls. */
5490 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5491 DEBUG(3,("call_trans2qfilepathinfo: "
5492 "SMB_VFS_LSTAT of %s failed "
5494 smb_fname_str_dbg(smb_fname
),
5497 map_nt_error_from_unix(errno
));
5500 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5501 DEBUG(3,("call_trans2qfilepathinfo: "
5502 "SMB_VFS_STAT of %s failed (%s)\n",
5503 smb_fname_str_dbg(smb_fname
),
5506 map_nt_error_from_unix(errno
));
5510 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5511 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5514 * Original code - this is an open file.
5516 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5517 DEBUG(3, ("fstat of %s failed (%s)\n",
5518 fsp_fnum_dbg(fsp
), strerror(errno
)));
5520 map_nt_error_from_unix(errno
));
5523 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5524 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5530 uint32_t ucf_flags
= 0;
5533 if (total_params
< 7) {
5534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5538 info_level
= SVAL(params
,0);
5540 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5542 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5543 if (!lp_unix_extensions()) {
5544 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5547 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5548 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5549 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5550 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5554 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5556 STR_TERMINATE
, &status
);
5557 if (!NT_STATUS_IS_OK(status
)) {
5558 reply_nterror(req
, status
);
5562 status
= filename_convert(req
,
5564 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5569 if (!NT_STATUS_IS_OK(status
)) {
5570 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5571 reply_botherror(req
,
5572 NT_STATUS_PATH_NOT_COVERED
,
5573 ERRSRV
, ERRbadpath
);
5576 reply_nterror(req
, status
);
5580 /* If this is a stream, check if there is a delete_pending. */
5581 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5582 && is_ntfs_stream_smb_fname(smb_fname
)) {
5583 struct smb_filename
*smb_fname_base
;
5585 /* Create an smb_filename with stream_name == NULL. */
5586 smb_fname_base
= synthetic_smb_fname(
5587 talloc_tos(), smb_fname
->base_name
,
5589 if (smb_fname_base
== NULL
) {
5590 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5594 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5595 /* Always do lstat for UNIX calls. */
5596 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5597 DEBUG(3,("call_trans2qfilepathinfo: "
5598 "SMB_VFS_LSTAT of %s failed "
5600 smb_fname_str_dbg(smb_fname_base
),
5602 TALLOC_FREE(smb_fname_base
);
5604 map_nt_error_from_unix(errno
));
5608 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5609 DEBUG(3,("call_trans2qfilepathinfo: "
5610 "fileinfo of %s failed "
5612 smb_fname_str_dbg(smb_fname_base
),
5614 TALLOC_FREE(smb_fname_base
);
5616 map_nt_error_from_unix(errno
));
5621 status
= file_name_hash(conn
,
5622 smb_fname_str_dbg(smb_fname_base
),
5624 if (!NT_STATUS_IS_OK(status
)) {
5625 TALLOC_FREE(smb_fname_base
);
5626 reply_nterror(req
, status
);
5630 fileid
= vfs_file_id_from_sbuf(conn
,
5631 &smb_fname_base
->st
);
5632 TALLOC_FREE(smb_fname_base
);
5633 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5634 if (delete_pending
) {
5635 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5640 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5641 /* Always do lstat for UNIX calls. */
5642 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5643 DEBUG(3,("call_trans2qfilepathinfo: "
5644 "SMB_VFS_LSTAT of %s failed (%s)\n",
5645 smb_fname_str_dbg(smb_fname
),
5648 map_nt_error_from_unix(errno
));
5653 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5654 DEBUG(3,("call_trans2qfilepathinfo: "
5655 "SMB_VFS_STAT of %s failed (%s)\n",
5656 smb_fname_str_dbg(smb_fname
),
5659 map_nt_error_from_unix(errno
));
5664 status
= file_name_hash(conn
,
5665 smb_fname_str_dbg(smb_fname
),
5667 if (!NT_STATUS_IS_OK(status
)) {
5668 reply_nterror(req
, status
);
5672 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5673 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5674 if (delete_pending
) {
5675 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5680 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5681 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5683 info_level
,tran_call
,total_data
));
5685 /* Pull out any data sent here before we realloc. */
5686 switch (info_level
) {
5687 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5689 /* Pull any EA list from the data portion. */
5692 if (total_data
< 4) {
5694 req
, NT_STATUS_INVALID_PARAMETER
);
5697 ea_size
= IVAL(pdata
,0);
5699 if (total_data
> 0 && ea_size
!= total_data
) {
5700 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5701 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5703 req
, NT_STATUS_INVALID_PARAMETER
);
5707 if (!lp_ea_support(SNUM(conn
))) {
5708 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5712 /* Pull out the list of names. */
5713 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5716 req
, NT_STATUS_INVALID_PARAMETER
);
5722 case SMB_QUERY_POSIX_LOCK
:
5724 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5725 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5729 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5731 req
, NT_STATUS_INVALID_PARAMETER
);
5735 /* Copy the lock range data. */
5736 lock_data
= (char *)talloc_memdup(
5737 req
, pdata
, total_data
);
5739 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5742 lock_data_count
= total_data
;
5748 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5749 if (*pparams
== NULL
) {
5750 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5757 * draft-leach-cifs-v1-spec-02.txt
5758 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5761 * The requested information is placed in the Data portion of the
5762 * transaction response. For the information levels greater than 0x100,
5763 * the transaction response has 1 parameter word which should be
5764 * ignored by the client.
5766 * However Windows only follows this rule for the IS_NAME_VALID call.
5768 switch (info_level
) {
5769 case SMB_INFO_IS_NAME_VALID
:
5774 if ((info_level
& 0xFF00) == 0xFF00) {
5776 * We use levels that start with 0xFF00
5777 * internally to represent SMB2 specific levels
5779 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5783 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5785 delete_pending
, write_time_ts
,
5787 lock_data_count
, lock_data
,
5788 req
->flags2
, max_data_bytes
,
5790 ppdata
, &data_size
);
5791 if (!NT_STATUS_IS_OK(status
)) {
5792 reply_nterror(req
, status
);
5795 if (fixed_portion
> max_data_bytes
) {
5796 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5800 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5806 /****************************************************************************
5807 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5809 ****************************************************************************/
5811 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5812 connection_struct
*conn
,
5813 struct smb_request
*req
,
5814 bool overwrite_if_exists
,
5815 const struct smb_filename
*smb_fname_old
,
5816 struct smb_filename
*smb_fname_new
)
5818 NTSTATUS status
= NT_STATUS_OK
;
5820 /* source must already exist. */
5821 if (!VALID_STAT(smb_fname_old
->st
)) {
5822 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5825 if (VALID_STAT(smb_fname_new
->st
)) {
5826 if (overwrite_if_exists
) {
5827 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5828 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5830 status
= unlink_internals(conn
,
5832 FILE_ATTRIBUTE_NORMAL
,
5835 if (!NT_STATUS_IS_OK(status
)) {
5839 /* Disallow if newname already exists. */
5840 return NT_STATUS_OBJECT_NAME_COLLISION
;
5844 /* No links from a directory. */
5845 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5846 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5849 /* Setting a hardlink to/from a stream isn't currently supported. */
5850 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5851 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5852 return NT_STATUS_INVALID_PARAMETER
;
5855 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5856 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5858 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5859 smb_fname_new
->base_name
) != 0) {
5860 status
= map_nt_error_from_unix(errno
);
5861 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5862 nt_errstr(status
), smb_fname_old
->base_name
,
5863 smb_fname_new
->base_name
));
5868 /****************************************************************************
5869 Deal with setting the time from any of the setfilepathinfo functions.
5870 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5871 calling this function.
5872 ****************************************************************************/
5874 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5876 const struct smb_filename
*smb_fname
,
5877 struct smb_file_time
*ft
,
5878 bool setting_write_time
)
5880 struct smb_filename smb_fname_base
;
5882 FILE_NOTIFY_CHANGE_LAST_ACCESS
5883 |FILE_NOTIFY_CHANGE_LAST_WRITE
5884 |FILE_NOTIFY_CHANGE_CREATION
;
5886 if (!VALID_STAT(smb_fname
->st
)) {
5887 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5890 /* get some defaults (no modifications) if any info is zero or -1. */
5891 if (null_timespec(ft
->create_time
)) {
5892 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5895 if (null_timespec(ft
->atime
)) {
5896 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5899 if (null_timespec(ft
->mtime
)) {
5900 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5903 if (!setting_write_time
) {
5904 /* ft->mtime comes from change time, not write time. */
5905 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5908 /* Ensure the resolution is the correct for
5909 * what we can store on this filesystem. */
5911 round_timespec(conn
->ts_res
, &ft
->create_time
);
5912 round_timespec(conn
->ts_res
, &ft
->ctime
);
5913 round_timespec(conn
->ts_res
, &ft
->atime
);
5914 round_timespec(conn
->ts_res
, &ft
->mtime
);
5916 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5917 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5918 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5919 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5920 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5921 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5922 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5923 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5925 if (setting_write_time
) {
5927 * This was a Windows setfileinfo on an open file.
5928 * NT does this a lot. We also need to
5929 * set the time here, as it can be read by
5930 * FindFirst/FindNext and with the patch for bug #2045
5931 * in smbd/fileio.c it ensures that this timestamp is
5932 * kept sticky even after a write. We save the request
5933 * away and will set it on file close and after a write. JRA.
5936 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5937 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5940 if (fsp
->base_fsp
) {
5941 set_sticky_write_time_fsp(fsp
->base_fsp
,
5944 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5947 set_sticky_write_time_path(
5948 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5953 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5955 /* Always call ntimes on the base, even if a stream was passed in. */
5956 smb_fname_base
= *smb_fname
;
5957 smb_fname_base
.stream_name
= NULL
;
5959 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5960 return map_nt_error_from_unix(errno
);
5963 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5964 smb_fname
->base_name
);
5965 return NT_STATUS_OK
;
5968 /****************************************************************************
5969 Deal with setting the dosmode from any of the setfilepathinfo functions.
5970 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5971 done before calling this function.
5972 ****************************************************************************/
5974 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5975 const struct smb_filename
*smb_fname
,
5978 struct smb_filename
*smb_fname_base
;
5981 if (!VALID_STAT(smb_fname
->st
)) {
5982 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5985 /* Always operate on the base_name, even if a stream was passed in. */
5986 smb_fname_base
= synthetic_smb_fname(
5987 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5988 if (smb_fname_base
== NULL
) {
5989 return NT_STATUS_NO_MEMORY
;
5993 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5994 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5996 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6000 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6002 /* check the mode isn't different, before changing it */
6003 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6005 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6006 (unsigned int)dosmode
));
6008 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6010 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6012 smb_fname_str_dbg(smb_fname_base
),
6014 status
= map_nt_error_from_unix(errno
);
6018 status
= NT_STATUS_OK
;
6020 TALLOC_FREE(smb_fname_base
);
6024 /****************************************************************************
6025 Deal with setting the size from any of the setfilepathinfo functions.
6026 ****************************************************************************/
6028 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6029 struct smb_request
*req
,
6031 const struct smb_filename
*smb_fname
,
6032 const SMB_STRUCT_STAT
*psbuf
,
6034 bool fail_after_createfile
)
6036 NTSTATUS status
= NT_STATUS_OK
;
6037 struct smb_filename
*smb_fname_tmp
= NULL
;
6038 files_struct
*new_fsp
= NULL
;
6040 if (!VALID_STAT(*psbuf
)) {
6041 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6044 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6046 if (size
== get_file_size_stat(psbuf
)) {
6047 return NT_STATUS_OK
;
6050 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6051 smb_fname_str_dbg(smb_fname
), (double)size
));
6053 if (fsp
&& fsp
->fh
->fd
!= -1) {
6054 /* Handle based call. */
6055 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6056 return NT_STATUS_ACCESS_DENIED
;
6059 if (vfs_set_filelen(fsp
, size
) == -1) {
6060 return map_nt_error_from_unix(errno
);
6062 trigger_write_time_update_immediate(fsp
);
6063 return NT_STATUS_OK
;
6066 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6067 if (smb_fname_tmp
== NULL
) {
6068 return NT_STATUS_NO_MEMORY
;
6071 smb_fname_tmp
->st
= *psbuf
;
6073 status
= SMB_VFS_CREATE_FILE(
6076 0, /* root_dir_fid */
6077 smb_fname_tmp
, /* fname */
6078 FILE_WRITE_DATA
, /* access_mask */
6079 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6081 FILE_OPEN
, /* create_disposition*/
6082 0, /* create_options */
6083 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6084 0, /* oplock_request */
6086 0, /* allocation_size */
6087 0, /* private_flags */
6090 &new_fsp
, /* result */
6092 NULL
, NULL
); /* create context */
6094 TALLOC_FREE(smb_fname_tmp
);
6096 if (!NT_STATUS_IS_OK(status
)) {
6097 /* NB. We check for open_was_deferred in the caller. */
6101 /* See RAW-SFILEINFO-END-OF-FILE */
6102 if (fail_after_createfile
) {
6103 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6104 return NT_STATUS_INVALID_LEVEL
;
6107 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6108 status
= map_nt_error_from_unix(errno
);
6109 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6113 trigger_write_time_update_immediate(new_fsp
);
6114 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6115 return NT_STATUS_OK
;
6118 /****************************************************************************
6119 Deal with SMB_INFO_SET_EA.
6120 ****************************************************************************/
6122 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6126 const struct smb_filename
*smb_fname
)
6128 struct ea_list
*ea_list
= NULL
;
6129 TALLOC_CTX
*ctx
= NULL
;
6130 NTSTATUS status
= NT_STATUS_OK
;
6132 if (total_data
< 10) {
6134 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6135 length. They seem to have no effect. Bug #3212. JRA */
6137 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6138 /* We're done. We only get EA info in this call. */
6139 return NT_STATUS_OK
;
6142 return NT_STATUS_INVALID_PARAMETER
;
6145 if (IVAL(pdata
,0) > total_data
) {
6146 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6147 IVAL(pdata
,0), (unsigned int)total_data
));
6148 return NT_STATUS_INVALID_PARAMETER
;
6152 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6154 return NT_STATUS_INVALID_PARAMETER
;
6157 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6162 /****************************************************************************
6163 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6164 ****************************************************************************/
6166 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6171 struct ea_list
*ea_list
= NULL
;
6175 return NT_STATUS_INVALID_HANDLE
;
6178 if (!lp_ea_support(SNUM(conn
))) {
6179 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6180 "EA's not supported.\n",
6181 (unsigned int)total_data
));
6182 return NT_STATUS_EAS_NOT_SUPPORTED
;
6185 if (total_data
< 10) {
6186 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6188 (unsigned int)total_data
));
6189 return NT_STATUS_INVALID_PARAMETER
;
6192 ea_list
= read_nttrans_ea_list(talloc_tos(),
6197 return NT_STATUS_INVALID_PARAMETER
;
6200 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6202 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6203 smb_fname_str_dbg(fsp
->fsp_name
),
6204 nt_errstr(status
) ));
6210 /****************************************************************************
6211 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6212 ****************************************************************************/
6214 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6218 struct smb_filename
*smb_fname
)
6220 NTSTATUS status
= NT_STATUS_OK
;
6221 bool delete_on_close
;
6222 uint32_t dosmode
= 0;
6224 if (total_data
< 1) {
6225 return NT_STATUS_INVALID_PARAMETER
;
6229 return NT_STATUS_INVALID_HANDLE
;
6232 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6233 dosmode
= dos_mode(conn
, smb_fname
);
6235 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6236 "delete_on_close = %u\n",
6237 smb_fname_str_dbg(smb_fname
),
6238 (unsigned int)dosmode
,
6239 (unsigned int)delete_on_close
));
6241 if (delete_on_close
) {
6242 status
= can_set_delete_on_close(fsp
, dosmode
);
6243 if (!NT_STATUS_IS_OK(status
)) {
6248 /* The set is across all open files on this dev/inode pair. */
6249 if (!set_delete_on_close(fsp
, delete_on_close
,
6250 conn
->session_info
->security_token
,
6251 conn
->session_info
->unix_token
)) {
6252 return NT_STATUS_ACCESS_DENIED
;
6254 return NT_STATUS_OK
;
6257 /****************************************************************************
6258 Deal with SMB_FILE_POSITION_INFORMATION.
6259 ****************************************************************************/
6261 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6266 uint64_t position_information
;
6268 if (total_data
< 8) {
6269 return NT_STATUS_INVALID_PARAMETER
;
6273 /* Ignore on pathname based set. */
6274 return NT_STATUS_OK
;
6277 position_information
= (uint64_t)IVAL(pdata
,0);
6278 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6280 DEBUG(10,("smb_file_position_information: Set file position "
6281 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6282 (double)position_information
));
6283 fsp
->fh
->position_information
= position_information
;
6284 return NT_STATUS_OK
;
6287 /****************************************************************************
6288 Deal with SMB_FILE_MODE_INFORMATION.
6289 ****************************************************************************/
6291 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6297 if (total_data
< 4) {
6298 return NT_STATUS_INVALID_PARAMETER
;
6300 mode
= IVAL(pdata
,0);
6301 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6302 return NT_STATUS_INVALID_PARAMETER
;
6304 return NT_STATUS_OK
;
6307 /****************************************************************************
6308 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6309 ****************************************************************************/
6311 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6312 struct smb_request
*req
,
6315 const struct smb_filename
*smb_fname
)
6317 char *link_target
= NULL
;
6318 const char *newname
= smb_fname
->base_name
;
6319 TALLOC_CTX
*ctx
= talloc_tos();
6321 /* Set a symbolic link. */
6322 /* Don't allow this if follow links is false. */
6324 if (total_data
== 0) {
6325 return NT_STATUS_INVALID_PARAMETER
;
6328 if (!lp_follow_symlinks(SNUM(conn
))) {
6329 return NT_STATUS_ACCESS_DENIED
;
6332 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6333 total_data
, STR_TERMINATE
);
6336 return NT_STATUS_INVALID_PARAMETER
;
6339 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6340 newname
, link_target
));
6342 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6343 return map_nt_error_from_unix(errno
);
6346 return NT_STATUS_OK
;
6349 /****************************************************************************
6350 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6351 ****************************************************************************/
6353 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6354 struct smb_request
*req
,
6355 const char *pdata
, int total_data
,
6356 struct smb_filename
*smb_fname_new
)
6358 char *oldname
= NULL
;
6359 struct smb_filename
*smb_fname_old
= NULL
;
6360 TALLOC_CTX
*ctx
= talloc_tos();
6361 NTSTATUS status
= NT_STATUS_OK
;
6363 /* Set a hard link. */
6364 if (total_data
== 0) {
6365 return NT_STATUS_INVALID_PARAMETER
;
6368 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6369 total_data
, STR_TERMINATE
, &status
);
6370 if (!NT_STATUS_IS_OK(status
)) {
6374 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6375 smb_fname_str_dbg(smb_fname_new
), oldname
));
6377 status
= filename_convert(ctx
,
6379 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6384 if (!NT_STATUS_IS_OK(status
)) {
6388 return hardlink_internals(ctx
, conn
, req
, false,
6389 smb_fname_old
, smb_fname_new
);
6392 /****************************************************************************
6393 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6394 ****************************************************************************/
6396 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6397 struct smb_request
*req
,
6401 struct smb_filename
*smb_fname_src
)
6405 char *newname
= NULL
;
6406 struct smb_filename
*smb_fname_dst
= NULL
;
6407 NTSTATUS status
= NT_STATUS_OK
;
6408 TALLOC_CTX
*ctx
= talloc_tos();
6411 return NT_STATUS_INVALID_HANDLE
;
6414 if (total_data
< 20) {
6415 return NT_STATUS_INVALID_PARAMETER
;
6418 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6419 len
= IVAL(pdata
,16);
6421 if (len
> (total_data
- 20) || (len
== 0)) {
6422 return NT_STATUS_INVALID_PARAMETER
;
6425 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6426 &pdata
[20], len
, STR_TERMINATE
,
6428 if (!NT_STATUS_IS_OK(status
)) {
6432 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6435 status
= filename_convert(ctx
,
6437 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6442 if (!NT_STATUS_IS_OK(status
)) {
6446 if (fsp
->base_fsp
) {
6447 /* newname must be a stream name. */
6448 if (newname
[0] != ':') {
6449 return NT_STATUS_NOT_SUPPORTED
;
6452 /* Create an smb_fname to call rename_internals_fsp() with. */
6453 smb_fname_dst
= synthetic_smb_fname(
6454 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6456 if (smb_fname_dst
== NULL
) {
6457 status
= NT_STATUS_NO_MEMORY
;
6462 * Set the original last component, since
6463 * rename_internals_fsp() requires it.
6465 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6467 if (smb_fname_dst
->original_lcomp
== NULL
) {
6468 status
= NT_STATUS_NO_MEMORY
;
6474 DEBUG(10,("smb2_file_rename_information: "
6475 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6476 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6477 smb_fname_str_dbg(smb_fname_dst
)));
6478 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6479 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6483 TALLOC_FREE(smb_fname_dst
);
6487 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6488 struct smb_request
*req
,
6492 struct smb_filename
*smb_fname_src
)
6496 char *newname
= NULL
;
6497 struct smb_filename
*smb_fname_dst
= NULL
;
6498 NTSTATUS status
= NT_STATUS_OK
;
6499 TALLOC_CTX
*ctx
= talloc_tos();
6502 return NT_STATUS_INVALID_HANDLE
;
6505 if (total_data
< 20) {
6506 return NT_STATUS_INVALID_PARAMETER
;
6509 overwrite
= (CVAL(pdata
,0) ? true : false);
6510 len
= IVAL(pdata
,16);
6512 if (len
> (total_data
- 20) || (len
== 0)) {
6513 return NT_STATUS_INVALID_PARAMETER
;
6516 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6517 &pdata
[20], len
, STR_TERMINATE
,
6519 if (!NT_STATUS_IS_OK(status
)) {
6523 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6526 status
= filename_convert(ctx
,
6528 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6533 if (!NT_STATUS_IS_OK(status
)) {
6537 if (fsp
->base_fsp
) {
6538 /* No stream names. */
6539 return NT_STATUS_NOT_SUPPORTED
;
6542 DEBUG(10,("smb_file_link_information: "
6543 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6544 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6545 smb_fname_str_dbg(smb_fname_dst
)));
6546 status
= hardlink_internals(ctx
,
6553 TALLOC_FREE(smb_fname_dst
);
6557 /****************************************************************************
6558 Deal with SMB_FILE_RENAME_INFORMATION.
6559 ****************************************************************************/
6561 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6562 struct smb_request
*req
,
6566 struct smb_filename
*smb_fname_src
)
6571 char *newname
= NULL
;
6572 struct smb_filename
*smb_fname_dst
= NULL
;
6573 bool dest_has_wcard
= False
;
6574 NTSTATUS status
= NT_STATUS_OK
;
6576 TALLOC_CTX
*ctx
= talloc_tos();
6578 if (total_data
< 13) {
6579 return NT_STATUS_INVALID_PARAMETER
;
6582 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6583 root_fid
= IVAL(pdata
,4);
6584 len
= IVAL(pdata
,8);
6586 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6587 return NT_STATUS_INVALID_PARAMETER
;
6590 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6593 if (!NT_STATUS_IS_OK(status
)) {
6597 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6600 status
= resolve_dfspath_wcard(ctx
, conn
,
6601 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6604 !conn
->sconn
->using_smb2
,
6607 if (!NT_STATUS_IS_OK(status
)) {
6611 /* Check the new name has no '/' characters. */
6612 if (strchr_m(newname
, '/')) {
6613 return NT_STATUS_NOT_SUPPORTED
;
6616 if (fsp
&& fsp
->base_fsp
) {
6617 /* newname must be a stream name. */
6618 if (newname
[0] != ':') {
6619 return NT_STATUS_NOT_SUPPORTED
;
6622 /* Create an smb_fname to call rename_internals_fsp() with. */
6623 smb_fname_dst
= synthetic_smb_fname(
6624 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6626 if (smb_fname_dst
== NULL
) {
6627 status
= NT_STATUS_NO_MEMORY
;
6632 * Set the original last component, since
6633 * rename_internals_fsp() requires it.
6635 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6637 if (smb_fname_dst
->original_lcomp
== NULL
) {
6638 status
= NT_STATUS_NO_MEMORY
;
6644 * Build up an smb_fname_dst based on the filename passed in.
6645 * We basically just strip off the last component, and put on
6646 * the newname instead.
6648 char *base_name
= NULL
;
6650 /* newname must *not* be a stream name. */
6651 if (newname
[0] == ':') {
6652 return NT_STATUS_NOT_SUPPORTED
;
6656 * Strip off the last component (filename) of the path passed
6659 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6661 return NT_STATUS_NO_MEMORY
;
6663 p
= strrchr_m(base_name
, '/');
6667 base_name
= talloc_strdup(ctx
, "");
6669 return NT_STATUS_NO_MEMORY
;
6672 /* Append the new name. */
6673 base_name
= talloc_asprintf_append(base_name
,
6677 return NT_STATUS_NO_MEMORY
;
6680 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6683 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6686 /* If an error we expect this to be
6687 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6689 if (!NT_STATUS_IS_OK(status
)) {
6690 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6694 /* Create an smb_fname to call rename_internals_fsp() */
6695 smb_fname_dst
= synthetic_smb_fname(
6696 ctx
, base_name
, NULL
, NULL
);
6697 if (smb_fname_dst
== NULL
) {
6698 status
= NT_STATUS_NO_MEMORY
;
6705 DEBUG(10,("smb_file_rename_information: "
6706 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6707 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6708 smb_fname_str_dbg(smb_fname_dst
)));
6709 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6712 DEBUG(10,("smb_file_rename_information: "
6713 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6714 smb_fname_str_dbg(smb_fname_src
),
6715 smb_fname_str_dbg(smb_fname_dst
)));
6716 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6717 smb_fname_dst
, 0, overwrite
, false,
6719 FILE_WRITE_ATTRIBUTES
);
6722 TALLOC_FREE(smb_fname_dst
);
6726 /****************************************************************************
6727 Deal with SMB_SET_POSIX_ACL.
6728 ****************************************************************************/
6730 #if defined(HAVE_POSIX_ACLS)
6731 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6735 const struct smb_filename
*smb_fname
)
6737 uint16_t posix_acl_version
;
6738 uint16_t num_file_acls
;
6739 uint16_t num_def_acls
;
6740 bool valid_file_acls
= True
;
6741 bool valid_def_acls
= True
;
6743 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6744 return NT_STATUS_INVALID_PARAMETER
;
6746 posix_acl_version
= SVAL(pdata
,0);
6747 num_file_acls
= SVAL(pdata
,2);
6748 num_def_acls
= SVAL(pdata
,4);
6750 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6751 valid_file_acls
= False
;
6755 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6756 valid_def_acls
= False
;
6760 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6761 return NT_STATUS_INVALID_PARAMETER
;
6764 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6765 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6766 return NT_STATUS_INVALID_PARAMETER
;
6769 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6770 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6771 (unsigned int)num_file_acls
,
6772 (unsigned int)num_def_acls
));
6774 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6775 smb_fname
->base_name
, num_file_acls
,
6776 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6777 return map_nt_error_from_unix(errno
);
6780 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6781 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6782 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6783 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6784 return map_nt_error_from_unix(errno
);
6786 return NT_STATUS_OK
;
6790 /****************************************************************************
6791 Deal with SMB_SET_POSIX_LOCK.
6792 ****************************************************************************/
6794 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6795 struct smb_request
*req
,
6803 bool blocking_lock
= False
;
6804 enum brl_type lock_type
;
6806 NTSTATUS status
= NT_STATUS_OK
;
6808 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6809 return NT_STATUS_INVALID_HANDLE
;
6812 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6813 return NT_STATUS_INVALID_PARAMETER
;
6816 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6817 case POSIX_LOCK_TYPE_READ
:
6818 lock_type
= READ_LOCK
;
6820 case POSIX_LOCK_TYPE_WRITE
:
6821 /* Return the right POSIX-mappable error code for files opened read-only. */
6822 if (!fsp
->can_write
) {
6823 return NT_STATUS_INVALID_HANDLE
;
6825 lock_type
= WRITE_LOCK
;
6827 case POSIX_LOCK_TYPE_UNLOCK
:
6828 lock_type
= UNLOCK_LOCK
;
6831 return NT_STATUS_INVALID_PARAMETER
;
6834 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6835 blocking_lock
= False
;
6836 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6837 blocking_lock
= True
;
6839 return NT_STATUS_INVALID_PARAMETER
;
6842 if (!lp_blocking_locks(SNUM(conn
))) {
6843 blocking_lock
= False
;
6846 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6847 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6848 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6849 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6850 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6852 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6853 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6855 (unsigned int)lock_type
,
6856 (unsigned long long)smblctx
,
6860 if (lock_type
== UNLOCK_LOCK
) {
6861 status
= do_unlock(req
->sconn
->msg_ctx
,
6868 uint64_t block_smblctx
;
6870 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6881 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6883 * A blocking lock was requested. Package up
6884 * this smb into a queued request and push it
6885 * onto the blocking lock queue.
6887 if(push_blocking_lock_request(br_lck
,
6890 -1, /* infinite timeout. */
6898 TALLOC_FREE(br_lck
);
6902 TALLOC_FREE(br_lck
);
6908 /****************************************************************************
6909 Deal with SMB_SET_FILE_BASIC_INFO.
6910 ****************************************************************************/
6912 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6916 const struct smb_filename
*smb_fname
)
6918 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6919 struct smb_file_time ft
;
6920 uint32_t dosmode
= 0;
6921 NTSTATUS status
= NT_STATUS_OK
;
6925 if (total_data
< 36) {
6926 return NT_STATUS_INVALID_PARAMETER
;
6929 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6930 if (!NT_STATUS_IS_OK(status
)) {
6934 /* Set the attributes */
6935 dosmode
= IVAL(pdata
,32);
6936 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6937 if (!NT_STATUS_IS_OK(status
)) {
6942 ft
.create_time
= interpret_long_date(pdata
);
6945 ft
.atime
= interpret_long_date(pdata
+8);
6948 ft
.mtime
= interpret_long_date(pdata
+16);
6951 ft
.ctime
= interpret_long_date(pdata
+24);
6953 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6954 smb_fname_str_dbg(smb_fname
)));
6956 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6960 /****************************************************************************
6961 Deal with SMB_INFO_STANDARD.
6962 ****************************************************************************/
6964 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6968 const struct smb_filename
*smb_fname
)
6971 struct smb_file_time ft
;
6975 if (total_data
< 12) {
6976 return NT_STATUS_INVALID_PARAMETER
;
6980 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6982 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6984 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6986 DEBUG(10,("smb_set_info_standard: file %s\n",
6987 smb_fname_str_dbg(smb_fname
)));
6989 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6990 if (!NT_STATUS_IS_OK(status
)) {
6994 return smb_set_file_time(conn
,
7001 /****************************************************************************
7002 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7003 ****************************************************************************/
7005 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7006 struct smb_request
*req
,
7010 struct smb_filename
*smb_fname
)
7012 uint64_t allocation_size
= 0;
7013 NTSTATUS status
= NT_STATUS_OK
;
7014 files_struct
*new_fsp
= NULL
;
7016 if (!VALID_STAT(smb_fname
->st
)) {
7017 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7020 if (total_data
< 8) {
7021 return NT_STATUS_INVALID_PARAMETER
;
7024 allocation_size
= (uint64_t)IVAL(pdata
,0);
7025 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7026 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7027 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7028 (double)allocation_size
));
7030 if (allocation_size
) {
7031 allocation_size
= smb_roundup(conn
, allocation_size
);
7034 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7035 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7036 (double)allocation_size
));
7038 if (fsp
&& fsp
->fh
->fd
!= -1) {
7039 /* Open file handle. */
7040 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7041 return NT_STATUS_ACCESS_DENIED
;
7044 /* Only change if needed. */
7045 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7046 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7047 return map_nt_error_from_unix(errno
);
7050 /* But always update the time. */
7052 * This is equivalent to a write. Ensure it's seen immediately
7053 * if there are no pending writes.
7055 trigger_write_time_update_immediate(fsp
);
7056 return NT_STATUS_OK
;
7059 /* Pathname or stat or directory file. */
7060 status
= SMB_VFS_CREATE_FILE(
7063 0, /* root_dir_fid */
7064 smb_fname
, /* fname */
7065 FILE_WRITE_DATA
, /* access_mask */
7066 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7068 FILE_OPEN
, /* create_disposition*/
7069 0, /* create_options */
7070 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7071 0, /* oplock_request */
7073 0, /* allocation_size */
7074 0, /* private_flags */
7077 &new_fsp
, /* result */
7079 NULL
, NULL
); /* create context */
7081 if (!NT_STATUS_IS_OK(status
)) {
7082 /* NB. We check for open_was_deferred in the caller. */
7086 /* Only change if needed. */
7087 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7088 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7089 status
= map_nt_error_from_unix(errno
);
7090 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7095 /* Changing the allocation size should set the last mod time. */
7097 * This is equivalent to a write. Ensure it's seen immediately
7098 * if there are no pending writes.
7100 trigger_write_time_update_immediate(new_fsp
);
7101 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7102 return NT_STATUS_OK
;
7105 /****************************************************************************
7106 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7107 ****************************************************************************/
7109 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7110 struct smb_request
*req
,
7114 const struct smb_filename
*smb_fname
,
7115 bool fail_after_createfile
)
7119 if (total_data
< 8) {
7120 return NT_STATUS_INVALID_PARAMETER
;
7123 size
= IVAL(pdata
,0);
7124 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7125 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7126 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7129 return smb_set_file_size(conn
, req
,
7134 fail_after_createfile
);
7137 /****************************************************************************
7138 Allow a UNIX info mknod.
7139 ****************************************************************************/
7141 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7144 const struct smb_filename
*smb_fname
)
7146 uint32_t file_type
= IVAL(pdata
,56);
7147 #if defined(HAVE_MAKEDEV)
7148 uint32_t dev_major
= IVAL(pdata
,60);
7149 uint32_t dev_minor
= IVAL(pdata
,68);
7151 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7152 uint32_t raw_unixmode
= IVAL(pdata
,84);
7156 if (total_data
< 100) {
7157 return NT_STATUS_INVALID_PARAMETER
;
7160 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7161 PERM_NEW_FILE
, &unixmode
);
7162 if (!NT_STATUS_IS_OK(status
)) {
7166 #if defined(HAVE_MAKEDEV)
7167 dev
= makedev(dev_major
, dev_minor
);
7170 switch (file_type
) {
7171 #if defined(S_IFIFO)
7172 case UNIX_TYPE_FIFO
:
7173 unixmode
|= S_IFIFO
;
7176 #if defined(S_IFSOCK)
7177 case UNIX_TYPE_SOCKET
:
7178 unixmode
|= S_IFSOCK
;
7181 #if defined(S_IFCHR)
7182 case UNIX_TYPE_CHARDEV
:
7183 unixmode
|= S_IFCHR
;
7186 #if defined(S_IFBLK)
7187 case UNIX_TYPE_BLKDEV
:
7188 unixmode
|= S_IFBLK
;
7192 return NT_STATUS_INVALID_PARAMETER
;
7195 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7196 "%.0f mode 0%o for file %s\n", (double)dev
,
7197 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7199 /* Ok - do the mknod. */
7200 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7201 return map_nt_error_from_unix(errno
);
7204 /* If any of the other "set" calls fail we
7205 * don't want to end up with a half-constructed mknod.
7208 if (lp_inherit_permissions(SNUM(conn
))) {
7210 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7212 return NT_STATUS_NO_MEMORY
;
7214 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7216 TALLOC_FREE(parent
);
7219 return NT_STATUS_OK
;
7222 /****************************************************************************
7223 Deal with SMB_SET_FILE_UNIX_BASIC.
7224 ****************************************************************************/
7226 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7227 struct smb_request
*req
,
7231 const struct smb_filename
*smb_fname
)
7233 struct smb_file_time ft
;
7234 uint32_t raw_unixmode
;
7237 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7238 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7239 NTSTATUS status
= NT_STATUS_OK
;
7240 bool delete_on_fail
= False
;
7241 enum perm_type ptype
;
7242 files_struct
*all_fsps
= NULL
;
7243 bool modify_mtime
= true;
7245 struct smb_filename
*smb_fname_tmp
= NULL
;
7246 SMB_STRUCT_STAT sbuf
;
7250 if (total_data
< 100) {
7251 return NT_STATUS_INVALID_PARAMETER
;
7254 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7255 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7256 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7257 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7260 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7261 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7262 set_owner
= (uid_t
)IVAL(pdata
,40);
7263 set_grp
= (gid_t
)IVAL(pdata
,48);
7264 raw_unixmode
= IVAL(pdata
,84);
7266 if (VALID_STAT(smb_fname
->st
)) {
7267 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7268 ptype
= PERM_EXISTING_DIR
;
7270 ptype
= PERM_EXISTING_FILE
;
7273 ptype
= PERM_NEW_FILE
;
7276 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7278 if (!NT_STATUS_IS_OK(status
)) {
7282 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7283 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7284 smb_fname_str_dbg(smb_fname
), (double)size
,
7285 (unsigned int)set_owner
, (unsigned int)set_grp
,
7286 (int)raw_unixmode
));
7288 sbuf
= smb_fname
->st
;
7290 if (!VALID_STAT(sbuf
)) {
7292 * The only valid use of this is to create character and block
7293 * devices, and named pipes. This is deprecated (IMHO) and
7294 * a new info level should be used for mknod. JRA.
7297 status
= smb_unix_mknod(conn
,
7301 if (!NT_STATUS_IS_OK(status
)) {
7305 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7306 if (smb_fname_tmp
== NULL
) {
7307 return NT_STATUS_NO_MEMORY
;
7310 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7311 status
= map_nt_error_from_unix(errno
);
7312 TALLOC_FREE(smb_fname_tmp
);
7313 SMB_VFS_UNLINK(conn
, smb_fname
);
7317 sbuf
= smb_fname_tmp
->st
;
7318 smb_fname
= smb_fname_tmp
;
7320 /* Ensure we don't try and change anything else. */
7321 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7322 size
= get_file_size_stat(&sbuf
);
7323 ft
.atime
= sbuf
.st_ex_atime
;
7324 ft
.mtime
= sbuf
.st_ex_mtime
;
7326 * We continue here as we might want to change the
7329 delete_on_fail
= True
;
7333 /* Horrible backwards compatibility hack as an old server bug
7334 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7338 size
= get_file_size_stat(&sbuf
);
7343 * Deal with the UNIX specific mode set.
7346 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7349 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7350 "setting mode 0%o for file %s\n",
7351 (unsigned int)unixmode
,
7352 smb_fname_str_dbg(smb_fname
)));
7353 if (fsp
&& fsp
->fh
->fd
!= -1) {
7354 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7356 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7359 return map_nt_error_from_unix(errno
);
7364 * Deal with the UNIX specific uid set.
7367 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7368 (sbuf
.st_ex_uid
!= set_owner
)) {
7371 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7372 "changing owner %u for path %s\n",
7373 (unsigned int)set_owner
,
7374 smb_fname_str_dbg(smb_fname
)));
7376 if (fsp
&& fsp
->fh
->fd
!= -1) {
7377 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7380 * UNIX extensions calls must always operate
7383 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7384 set_owner
, (gid_t
)-1);
7388 status
= map_nt_error_from_unix(errno
);
7389 if (delete_on_fail
) {
7390 SMB_VFS_UNLINK(conn
, smb_fname
);
7397 * Deal with the UNIX specific gid set.
7400 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7401 (sbuf
.st_ex_gid
!= set_grp
)) {
7404 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7405 "changing group %u for file %s\n",
7406 (unsigned int)set_owner
,
7407 smb_fname_str_dbg(smb_fname
)));
7408 if (fsp
&& fsp
->fh
->fd
!= -1) {
7409 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7412 * UNIX extensions calls must always operate
7415 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7419 status
= map_nt_error_from_unix(errno
);
7420 if (delete_on_fail
) {
7421 SMB_VFS_UNLINK(conn
, smb_fname
);
7427 /* Deal with any size changes. */
7429 status
= smb_set_file_size(conn
, req
,
7435 if (!NT_STATUS_IS_OK(status
)) {
7439 /* Deal with any time changes. */
7440 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7441 /* No change, don't cancel anything. */
7445 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7446 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7447 all_fsps
= file_find_di_next(all_fsps
)) {
7449 * We're setting the time explicitly for UNIX.
7450 * Cancel any pending changes over all handles.
7452 all_fsps
->update_write_time_on_close
= false;
7453 TALLOC_FREE(all_fsps
->update_write_time_event
);
7457 * Override the "setting_write_time"
7458 * parameter here as it almost does what
7459 * we need. Just remember if we modified
7460 * mtime and send the notify ourselves.
7462 if (null_timespec(ft
.mtime
)) {
7463 modify_mtime
= false;
7466 status
= smb_set_file_time(conn
,
7472 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7473 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7478 /****************************************************************************
7479 Deal with SMB_SET_FILE_UNIX_INFO2.
7480 ****************************************************************************/
7482 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7483 struct smb_request
*req
,
7487 const struct smb_filename
*smb_fname
)
7490 uint32_t smb_fflags
;
7493 if (total_data
< 116) {
7494 return NT_STATUS_INVALID_PARAMETER
;
7497 /* Start by setting all the fields that are common between UNIX_BASIC
7500 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7502 if (!NT_STATUS_IS_OK(status
)) {
7506 smb_fflags
= IVAL(pdata
, 108);
7507 smb_fmask
= IVAL(pdata
, 112);
7509 /* NB: We should only attempt to alter the file flags if the client
7510 * sends a non-zero mask.
7512 if (smb_fmask
!= 0) {
7513 int stat_fflags
= 0;
7515 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7516 smb_fmask
, &stat_fflags
)) {
7517 /* Client asked to alter a flag we don't understand. */
7518 return NT_STATUS_INVALID_PARAMETER
;
7521 if (fsp
&& fsp
->fh
->fd
!= -1) {
7522 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7523 return NT_STATUS_NOT_SUPPORTED
;
7525 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7526 stat_fflags
) != 0) {
7527 return map_nt_error_from_unix(errno
);
7532 /* XXX: need to add support for changing the create_time here. You
7533 * can do this for paths on Darwin with setattrlist(2). The right way
7534 * to hook this up is probably by extending the VFS utimes interface.
7537 return NT_STATUS_OK
;
7540 /****************************************************************************
7541 Create a directory with POSIX semantics.
7542 ****************************************************************************/
7544 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7545 struct smb_request
*req
,
7548 struct smb_filename
*smb_fname
,
7549 int *pdata_return_size
)
7551 NTSTATUS status
= NT_STATUS_OK
;
7552 uint32_t raw_unixmode
= 0;
7553 uint32_t mod_unixmode
= 0;
7554 mode_t unixmode
= (mode_t
)0;
7555 files_struct
*fsp
= NULL
;
7556 uint16_t info_level_return
= 0;
7558 char *pdata
= *ppdata
;
7560 if (total_data
< 18) {
7561 return NT_STATUS_INVALID_PARAMETER
;
7564 raw_unixmode
= IVAL(pdata
,8);
7565 /* Next 4 bytes are not yet defined. */
7567 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7568 PERM_NEW_DIR
, &unixmode
);
7569 if (!NT_STATUS_IS_OK(status
)) {
7573 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7575 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7576 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7578 status
= SMB_VFS_CREATE_FILE(
7581 0, /* root_dir_fid */
7582 smb_fname
, /* fname */
7583 FILE_READ_ATTRIBUTES
, /* access_mask */
7584 FILE_SHARE_NONE
, /* share_access */
7585 FILE_CREATE
, /* create_disposition*/
7586 FILE_DIRECTORY_FILE
, /* create_options */
7587 mod_unixmode
, /* file_attributes */
7588 0, /* oplock_request */
7590 0, /* allocation_size */
7591 0, /* private_flags */
7596 NULL
, NULL
); /* create context */
7598 if (NT_STATUS_IS_OK(status
)) {
7599 close_file(req
, fsp
, NORMAL_CLOSE
);
7602 info_level_return
= SVAL(pdata
,16);
7604 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7605 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7606 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7607 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7609 *pdata_return_size
= 12;
7612 /* Realloc the data size */
7613 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7614 if (*ppdata
== NULL
) {
7615 *pdata_return_size
= 0;
7616 return NT_STATUS_NO_MEMORY
;
7620 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7621 SSVAL(pdata
,2,0); /* No fnum. */
7622 SIVAL(pdata
,4,info
); /* Was directory created. */
7624 switch (info_level_return
) {
7625 case SMB_QUERY_FILE_UNIX_BASIC
:
7626 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7627 SSVAL(pdata
,10,0); /* Padding. */
7628 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7631 case SMB_QUERY_FILE_UNIX_INFO2
:
7632 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7633 SSVAL(pdata
,10,0); /* Padding. */
7634 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7638 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7639 SSVAL(pdata
,10,0); /* Padding. */
7646 /****************************************************************************
7647 Open/Create a file with POSIX semantics.
7648 ****************************************************************************/
7650 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7651 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7653 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7654 struct smb_request
*req
,
7657 struct smb_filename
*smb_fname
,
7658 int *pdata_return_size
)
7660 bool extended_oplock_granted
= False
;
7661 char *pdata
= *ppdata
;
7663 uint32_t wire_open_mode
= 0;
7664 uint32_t raw_unixmode
= 0;
7665 uint32_t mod_unixmode
= 0;
7666 uint32_t create_disp
= 0;
7667 uint32_t access_mask
= 0;
7668 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7669 NTSTATUS status
= NT_STATUS_OK
;
7670 mode_t unixmode
= (mode_t
)0;
7671 files_struct
*fsp
= NULL
;
7672 int oplock_request
= 0;
7674 uint16_t info_level_return
= 0;
7676 if (total_data
< 18) {
7677 return NT_STATUS_INVALID_PARAMETER
;
7680 flags
= IVAL(pdata
,0);
7681 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7682 if (oplock_request
) {
7683 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7686 wire_open_mode
= IVAL(pdata
,4);
7688 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7689 return smb_posix_mkdir(conn
, req
,
7696 switch (wire_open_mode
& SMB_ACCMODE
) {
7698 access_mask
= SMB_O_RDONLY_MAPPING
;
7701 access_mask
= SMB_O_WRONLY_MAPPING
;
7704 access_mask
= (SMB_O_RDONLY_MAPPING
|
7705 SMB_O_WRONLY_MAPPING
);
7708 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7709 (unsigned int)wire_open_mode
));
7710 return NT_STATUS_INVALID_PARAMETER
;
7713 wire_open_mode
&= ~SMB_ACCMODE
;
7715 /* First take care of O_CREAT|O_EXCL interactions. */
7716 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7717 case (SMB_O_CREAT
| SMB_O_EXCL
):
7718 /* File exists fail. File not exist create. */
7719 create_disp
= FILE_CREATE
;
7722 /* File exists open. File not exist create. */
7723 create_disp
= FILE_OPEN_IF
;
7726 /* O_EXCL on its own without O_CREAT is undefined.
7727 We deliberately ignore it as some versions of
7728 Linux CIFSFS can send a bare O_EXCL on the
7729 wire which other filesystems in the kernel
7730 ignore. See bug 9519 for details. */
7735 /* File exists open. File not exist fail. */
7736 create_disp
= FILE_OPEN
;
7739 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7740 (unsigned int)wire_open_mode
));
7741 return NT_STATUS_INVALID_PARAMETER
;
7744 /* Next factor in the effects of O_TRUNC. */
7745 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7747 if (wire_open_mode
& SMB_O_TRUNC
) {
7748 switch (create_disp
) {
7750 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7751 /* Leave create_disp alone as
7752 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7754 /* File exists fail. File not exist create. */
7757 /* SMB_O_CREAT | SMB_O_TRUNC */
7758 /* File exists overwrite. File not exist create. */
7759 create_disp
= FILE_OVERWRITE_IF
;
7763 /* File exists overwrite. File not exist fail. */
7764 create_disp
= FILE_OVERWRITE
;
7767 /* Cannot get here. */
7768 smb_panic("smb_posix_open: logic error");
7769 return NT_STATUS_INVALID_PARAMETER
;
7773 raw_unixmode
= IVAL(pdata
,8);
7774 /* Next 4 bytes are not yet defined. */
7776 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7777 (VALID_STAT(smb_fname
->st
) ?
7778 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7781 if (!NT_STATUS_IS_OK(status
)) {
7785 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7787 if (wire_open_mode
& SMB_O_SYNC
) {
7788 create_options
|= FILE_WRITE_THROUGH
;
7790 if (wire_open_mode
& SMB_O_APPEND
) {
7791 access_mask
|= FILE_APPEND_DATA
;
7793 if (wire_open_mode
& SMB_O_DIRECT
) {
7794 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7797 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7798 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7799 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7800 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7802 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7803 create_options
|= FILE_DIRECTORY_FILE
;
7806 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7807 smb_fname_str_dbg(smb_fname
),
7808 (unsigned int)wire_open_mode
,
7809 (unsigned int)unixmode
));
7811 status
= SMB_VFS_CREATE_FILE(
7814 0, /* root_dir_fid */
7815 smb_fname
, /* fname */
7816 access_mask
, /* access_mask */
7817 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7819 create_disp
, /* create_disposition*/
7820 create_options
, /* create_options */
7821 mod_unixmode
, /* file_attributes */
7822 oplock_request
, /* oplock_request */
7824 0, /* allocation_size */
7825 0, /* private_flags */
7830 NULL
, NULL
); /* create context */
7832 if (!NT_STATUS_IS_OK(status
)) {
7836 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7837 extended_oplock_granted
= True
;
7840 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7841 extended_oplock_granted
= True
;
7844 info_level_return
= SVAL(pdata
,16);
7846 /* Allocate the correct return size. */
7848 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7849 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7850 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7851 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7853 *pdata_return_size
= 12;
7856 /* Realloc the data size */
7857 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7858 if (*ppdata
== NULL
) {
7859 close_file(req
, fsp
, ERROR_CLOSE
);
7860 *pdata_return_size
= 0;
7861 return NT_STATUS_NO_MEMORY
;
7865 if (extended_oplock_granted
) {
7866 if (flags
& REQUEST_BATCH_OPLOCK
) {
7867 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7869 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7871 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7872 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7874 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7877 SSVAL(pdata
,2,fsp
->fnum
);
7878 SIVAL(pdata
,4,info
); /* Was file created etc. */
7880 switch (info_level_return
) {
7881 case SMB_QUERY_FILE_UNIX_BASIC
:
7882 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7883 SSVAL(pdata
,10,0); /* padding. */
7884 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7887 case SMB_QUERY_FILE_UNIX_INFO2
:
7888 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7889 SSVAL(pdata
,10,0); /* padding. */
7890 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7894 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7895 SSVAL(pdata
,10,0); /* padding. */
7898 return NT_STATUS_OK
;
7901 /****************************************************************************
7902 Delete a file with POSIX semantics.
7903 ****************************************************************************/
7905 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7906 struct smb_request
*req
,
7909 struct smb_filename
*smb_fname
)
7911 NTSTATUS status
= NT_STATUS_OK
;
7912 files_struct
*fsp
= NULL
;
7916 int create_options
= 0;
7918 struct share_mode_lock
*lck
= NULL
;
7920 if (total_data
< 2) {
7921 return NT_STATUS_INVALID_PARAMETER
;
7924 flags
= SVAL(pdata
,0);
7926 if (!VALID_STAT(smb_fname
->st
)) {
7927 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7930 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7931 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7932 return NT_STATUS_NOT_A_DIRECTORY
;
7935 DEBUG(10,("smb_posix_unlink: %s %s\n",
7936 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7937 smb_fname_str_dbg(smb_fname
)));
7939 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7940 create_options
|= FILE_DIRECTORY_FILE
;
7943 status
= SMB_VFS_CREATE_FILE(
7946 0, /* root_dir_fid */
7947 smb_fname
, /* fname */
7948 DELETE_ACCESS
, /* access_mask */
7949 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7951 FILE_OPEN
, /* create_disposition*/
7952 create_options
, /* create_options */
7953 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7954 0, /* oplock_request */
7956 0, /* allocation_size */
7957 0, /* private_flags */
7962 NULL
, NULL
); /* create context */
7964 if (!NT_STATUS_IS_OK(status
)) {
7969 * Don't lie to client. If we can't really delete due to
7970 * non-POSIX opens return SHARING_VIOLATION.
7973 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7975 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7976 "lock for file %s\n", fsp_str_dbg(fsp
)));
7977 close_file(req
, fsp
, NORMAL_CLOSE
);
7978 return NT_STATUS_INVALID_PARAMETER
;
7982 * See if others still have the file open. If this is the case, then
7983 * don't delete. If all opens are POSIX delete we can set the delete
7984 * on close disposition.
7986 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7987 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7988 if (is_valid_share_mode_entry(e
)) {
7989 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7992 if (share_mode_stale_pid(lck
->data
, i
)) {
7995 /* Fail with sharing violation. */
7997 close_file(req
, fsp
, NORMAL_CLOSE
);
7998 return NT_STATUS_SHARING_VIOLATION
;
8003 * Set the delete on close.
8005 status
= smb_set_file_disposition_info(conn
,
8013 if (!NT_STATUS_IS_OK(status
)) {
8014 close_file(req
, fsp
, NORMAL_CLOSE
);
8017 return close_file(req
, fsp
, NORMAL_CLOSE
);
8020 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8021 struct smb_request
*req
,
8022 TALLOC_CTX
*mem_ctx
,
8023 uint16_t info_level
,
8025 struct smb_filename
*smb_fname
,
8026 char **ppdata
, int total_data
,
8029 char *pdata
= *ppdata
;
8030 NTSTATUS status
= NT_STATUS_OK
;
8031 int data_return_size
= 0;
8035 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8036 return NT_STATUS_INVALID_LEVEL
;
8039 if (!CAN_WRITE(conn
)) {
8040 /* Allow POSIX opens. The open path will deny
8041 * any non-readonly opens. */
8042 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8043 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8047 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8048 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8050 info_level
, total_data
));
8052 switch (info_level
) {
8054 case SMB_INFO_STANDARD
:
8056 status
= smb_set_info_standard(conn
,
8064 case SMB_INFO_SET_EA
:
8066 status
= smb_info_set_ea(conn
,
8074 case SMB_SET_FILE_BASIC_INFO
:
8075 case SMB_FILE_BASIC_INFORMATION
:
8077 status
= smb_set_file_basic_info(conn
,
8085 case SMB_FILE_ALLOCATION_INFORMATION
:
8086 case SMB_SET_FILE_ALLOCATION_INFO
:
8088 status
= smb_set_file_allocation_info(conn
, req
,
8096 case SMB_FILE_END_OF_FILE_INFORMATION
:
8097 case SMB_SET_FILE_END_OF_FILE_INFO
:
8100 * XP/Win7 both fail after the createfile with
8101 * SMB_SET_FILE_END_OF_FILE_INFO but not
8102 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8103 * The level is known here, so pass it down
8107 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8109 status
= smb_set_file_end_of_file_info(conn
, req
,
8118 case SMB_FILE_DISPOSITION_INFORMATION
:
8119 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8122 /* JRA - We used to just ignore this on a path ?
8123 * Shouldn't this be invalid level on a pathname
8126 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8127 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8130 status
= smb_set_file_disposition_info(conn
,
8138 case SMB_FILE_POSITION_INFORMATION
:
8140 status
= smb_file_position_information(conn
,
8147 case SMB_FILE_FULL_EA_INFORMATION
:
8149 status
= smb_set_file_full_ea_info(conn
,
8156 /* From tridge Samba4 :
8157 * MODE_INFORMATION in setfileinfo (I have no
8158 * idea what "mode information" on a file is - it takes a value of 0,
8159 * 2, 4 or 6. What could it be?).
8162 case SMB_FILE_MODE_INFORMATION
:
8164 status
= smb_file_mode_information(conn
,
8171 * CIFS UNIX extensions.
8174 case SMB_SET_FILE_UNIX_BASIC
:
8176 status
= smb_set_file_unix_basic(conn
, req
,
8184 case SMB_SET_FILE_UNIX_INFO2
:
8186 status
= smb_set_file_unix_info2(conn
, req
,
8194 case SMB_SET_FILE_UNIX_LINK
:
8197 /* We must have a pathname for this. */
8198 return NT_STATUS_INVALID_LEVEL
;
8200 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8201 total_data
, smb_fname
);
8205 case SMB_SET_FILE_UNIX_HLINK
:
8208 /* We must have a pathname for this. */
8209 return NT_STATUS_INVALID_LEVEL
;
8211 status
= smb_set_file_unix_hlink(conn
, req
,
8217 case SMB_FILE_RENAME_INFORMATION
:
8219 status
= smb_file_rename_information(conn
, req
,
8225 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8227 /* SMB2 rename information. */
8228 status
= smb2_file_rename_information(conn
, req
,
8234 case SMB_FILE_LINK_INFORMATION
:
8236 status
= smb_file_link_information(conn
, req
,
8242 #if defined(HAVE_POSIX_ACLS)
8243 case SMB_SET_POSIX_ACL
:
8245 status
= smb_set_posix_acl(conn
,
8254 case SMB_SET_POSIX_LOCK
:
8257 return NT_STATUS_INVALID_LEVEL
;
8259 status
= smb_set_posix_lock(conn
, req
,
8260 pdata
, total_data
, fsp
);
8264 case SMB_POSIX_PATH_OPEN
:
8267 /* We must have a pathname for this. */
8268 return NT_STATUS_INVALID_LEVEL
;
8271 status
= smb_posix_open(conn
, req
,
8279 case SMB_POSIX_PATH_UNLINK
:
8282 /* We must have a pathname for this. */
8283 return NT_STATUS_INVALID_LEVEL
;
8286 status
= smb_posix_unlink(conn
, req
,
8294 return NT_STATUS_INVALID_LEVEL
;
8297 if (!NT_STATUS_IS_OK(status
)) {
8301 *ret_data_size
= data_return_size
;
8302 return NT_STATUS_OK
;
8305 /****************************************************************************
8306 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8307 ****************************************************************************/
8309 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8310 struct smb_request
*req
,
8311 unsigned int tran_call
,
8312 char **pparams
, int total_params
,
8313 char **ppdata
, int total_data
,
8314 unsigned int max_data_bytes
)
8316 char *params
= *pparams
;
8317 char *pdata
= *ppdata
;
8318 uint16_t info_level
;
8319 struct smb_filename
*smb_fname
= NULL
;
8320 files_struct
*fsp
= NULL
;
8321 NTSTATUS status
= NT_STATUS_OK
;
8322 int data_return_size
= 0;
8325 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8329 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8330 if (total_params
< 4) {
8331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8335 fsp
= file_fsp(req
, SVAL(params
,0));
8336 /* Basic check for non-null fsp. */
8337 if (!check_fsp_open(conn
, req
, fsp
)) {
8340 info_level
= SVAL(params
,2);
8342 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8343 if (smb_fname
== NULL
) {
8344 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8348 if(fsp
->fh
->fd
== -1) {
8350 * This is actually a SETFILEINFO on a directory
8351 * handle (returned from an NT SMB). NT5.0 seems
8352 * to do this call. JRA.
8354 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8355 /* Always do lstat for UNIX calls. */
8356 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8357 DEBUG(3,("call_trans2setfilepathinfo: "
8358 "SMB_VFS_LSTAT of %s failed "
8360 smb_fname_str_dbg(smb_fname
),
8362 reply_nterror(req
, map_nt_error_from_unix(errno
));
8366 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8367 DEBUG(3,("call_trans2setfilepathinfo: "
8368 "fileinfo of %s failed (%s)\n",
8369 smb_fname_str_dbg(smb_fname
),
8371 reply_nterror(req
, map_nt_error_from_unix(errno
));
8375 } else if (fsp
->print_file
) {
8377 * Doing a DELETE_ON_CLOSE should cancel a print job.
8379 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8380 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8382 DEBUG(3,("call_trans2setfilepathinfo: "
8383 "Cancelling print job (%s)\n",
8387 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8393 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8398 * Original code - this is an open file.
8400 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8401 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8402 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8404 reply_nterror(req
, map_nt_error_from_unix(errno
));
8410 uint32_t ucf_flags
= 0;
8413 if (total_params
< 7) {
8414 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8418 info_level
= SVAL(params
,0);
8419 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8420 total_params
- 6, STR_TERMINATE
,
8422 if (!NT_STATUS_IS_OK(status
)) {
8423 reply_nterror(req
, status
);
8427 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8428 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8429 info_level
== SMB_FILE_RENAME_INFORMATION
||
8430 info_level
== SMB_POSIX_PATH_UNLINK
) {
8431 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8434 status
= filename_convert(req
, conn
,
8435 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8440 if (!NT_STATUS_IS_OK(status
)) {
8441 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8442 reply_botherror(req
,
8443 NT_STATUS_PATH_NOT_COVERED
,
8444 ERRSRV
, ERRbadpath
);
8447 reply_nterror(req
, status
);
8451 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8453 * For CIFS UNIX extensions the target name may not exist.
8456 /* Always do lstat for UNIX calls. */
8457 SMB_VFS_LSTAT(conn
, smb_fname
);
8459 } else if (!VALID_STAT(smb_fname
->st
) &&
8460 SMB_VFS_STAT(conn
, smb_fname
)) {
8461 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8463 smb_fname_str_dbg(smb_fname
),
8465 reply_nterror(req
, map_nt_error_from_unix(errno
));
8470 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8471 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8473 info_level
,total_data
));
8475 /* Realloc the parameter size */
8476 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8477 if (*pparams
== NULL
) {
8478 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8485 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8491 if (!NT_STATUS_IS_OK(status
)) {
8492 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8493 /* We have re-scheduled this call. */
8496 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8497 /* We have re-scheduled this call. */
8500 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8501 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8502 ERRSRV
, ERRbadpath
);
8505 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8506 reply_openerror(req
, status
);
8511 * Invalid EA name needs to return 2 param bytes,
8512 * not a zero-length error packet.
8514 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8515 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8518 reply_nterror(req
, status
);
8523 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8529 /****************************************************************************
8530 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8531 ****************************************************************************/
8533 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8534 char **pparams
, int total_params
,
8535 char **ppdata
, int total_data
,
8536 unsigned int max_data_bytes
)
8538 struct smb_filename
*smb_dname
= NULL
;
8539 char *params
= *pparams
;
8540 char *pdata
= *ppdata
;
8541 char *directory
= NULL
;
8542 NTSTATUS status
= NT_STATUS_OK
;
8543 struct ea_list
*ea_list
= NULL
;
8544 TALLOC_CTX
*ctx
= talloc_tos();
8546 if (!CAN_WRITE(conn
)) {
8547 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8551 if (total_params
< 5) {
8552 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8556 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8557 total_params
- 4, STR_TERMINATE
,
8559 if (!NT_STATUS_IS_OK(status
)) {
8560 reply_nterror(req
, status
);
8564 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8566 status
= filename_convert(ctx
,
8568 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8574 if (!NT_STATUS_IS_OK(status
)) {
8575 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8576 reply_botherror(req
,
8577 NT_STATUS_PATH_NOT_COVERED
,
8578 ERRSRV
, ERRbadpath
);
8581 reply_nterror(req
, status
);
8586 * OS/2 workplace shell seems to send SET_EA requests of "null"
8587 * length (4 bytes containing IVAL 4).
8588 * They seem to have no effect. Bug #3212. JRA.
8591 if (total_data
&& (total_data
!= 4)) {
8592 /* Any data in this call is an EA list. */
8593 if (total_data
< 10) {
8594 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8598 if (IVAL(pdata
,0) > total_data
) {
8599 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8600 IVAL(pdata
,0), (unsigned int)total_data
));
8601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8605 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8608 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8612 if (!lp_ea_support(SNUM(conn
))) {
8613 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8617 /* If total_data == 4 Windows doesn't care what values
8618 * are placed in that field, it just ignores them.
8619 * The System i QNTC IBM SMB client puts bad values here,
8620 * so ignore them. */
8622 status
= create_directory(conn
, req
, smb_dname
);
8624 if (!NT_STATUS_IS_OK(status
)) {
8625 reply_nterror(req
, status
);
8629 /* Try and set any given EA. */
8631 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8632 if (!NT_STATUS_IS_OK(status
)) {
8633 reply_nterror(req
, status
);
8638 /* Realloc the parameter and data sizes */
8639 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8640 if(*pparams
== NULL
) {
8641 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8648 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8651 TALLOC_FREE(smb_dname
);
8655 /****************************************************************************
8656 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8657 We don't actually do this - we just send a null response.
8658 ****************************************************************************/
8660 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8661 struct smb_request
*req
,
8662 char **pparams
, int total_params
,
8663 char **ppdata
, int total_data
,
8664 unsigned int max_data_bytes
)
8666 char *params
= *pparams
;
8667 uint16_t info_level
;
8669 if (total_params
< 6) {
8670 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8674 info_level
= SVAL(params
,4);
8675 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8677 switch (info_level
) {
8682 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8686 /* Realloc the parameter and data sizes */
8687 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8688 if (*pparams
== NULL
) {
8689 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8694 SSVAL(params
,0,fnf_handle
);
8695 SSVAL(params
,2,0); /* No changes */
8696 SSVAL(params
,4,0); /* No EA errors */
8703 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8708 /****************************************************************************
8709 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8710 changes). Currently this does nothing.
8711 ****************************************************************************/
8713 static void call_trans2findnotifynext(connection_struct
*conn
,
8714 struct smb_request
*req
,
8715 char **pparams
, int total_params
,
8716 char **ppdata
, int total_data
,
8717 unsigned int max_data_bytes
)
8719 char *params
= *pparams
;
8721 DEBUG(3,("call_trans2findnotifynext\n"));
8723 /* Realloc the parameter and data sizes */
8724 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8725 if (*pparams
== NULL
) {
8726 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8731 SSVAL(params
,0,0); /* No changes */
8732 SSVAL(params
,2,0); /* No EA errors */
8734 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8739 /****************************************************************************
8740 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8741 ****************************************************************************/
8743 static void call_trans2getdfsreferral(connection_struct
*conn
,
8744 struct smb_request
*req
,
8745 char **pparams
, int total_params
,
8746 char **ppdata
, int total_data
,
8747 unsigned int max_data_bytes
)
8749 char *params
= *pparams
;
8750 char *pathname
= NULL
;
8752 int max_referral_level
;
8753 NTSTATUS status
= NT_STATUS_OK
;
8754 TALLOC_CTX
*ctx
= talloc_tos();
8756 DEBUG(10,("call_trans2getdfsreferral\n"));
8758 if (total_params
< 3) {
8759 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8763 max_referral_level
= SVAL(params
,0);
8765 if(!lp_host_msdfs()) {
8766 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8770 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8771 total_params
- 2, STR_TERMINATE
);
8773 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8776 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8777 ppdata
,&status
)) < 0) {
8778 reply_nterror(req
, status
);
8782 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8783 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8784 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8789 #define LMCAT_SPL 0x53
8790 #define LMFUNC_GETJOBID 0x60
8792 /****************************************************************************
8793 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8794 ****************************************************************************/
8796 static void call_trans2ioctl(connection_struct
*conn
,
8797 struct smb_request
*req
,
8798 char **pparams
, int total_params
,
8799 char **ppdata
, int total_data
,
8800 unsigned int max_data_bytes
)
8802 char *pdata
= *ppdata
;
8803 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8807 /* check for an invalid fid before proceeding */
8810 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8814 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8815 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8816 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8817 if (*ppdata
== NULL
) {
8818 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8823 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8824 CAN ACCEPT THIS IN UNICODE. JRA. */
8827 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8829 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8830 lp_netbios_name(), 15,
8831 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8832 if (!NT_STATUS_IS_OK(status
)) {
8833 reply_nterror(req
, status
);
8836 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8837 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8838 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8839 if (!NT_STATUS_IS_OK(status
)) {
8840 reply_nterror(req
, status
);
8843 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8848 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8849 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8852 /****************************************************************************
8853 Reply to a SMBfindclose (stop trans2 directory search).
8854 ****************************************************************************/
8856 void reply_findclose(struct smb_request
*req
)
8859 struct smbd_server_connection
*sconn
= req
->sconn
;
8861 START_PROFILE(SMBfindclose
);
8864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8865 END_PROFILE(SMBfindclose
);
8869 dptr_num
= SVALS(req
->vwv
+0, 0);
8871 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8873 dptr_close(sconn
, &dptr_num
);
8875 reply_outbuf(req
, 0, 0);
8877 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8879 END_PROFILE(SMBfindclose
);
8883 /****************************************************************************
8884 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8885 ****************************************************************************/
8887 void reply_findnclose(struct smb_request
*req
)
8891 START_PROFILE(SMBfindnclose
);
8894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8895 END_PROFILE(SMBfindnclose
);
8899 dptr_num
= SVAL(req
->vwv
+0, 0);
8901 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8903 /* We never give out valid handles for a
8904 findnotifyfirst - so any dptr_num is ok here.
8907 reply_outbuf(req
, 0, 0);
8909 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8911 END_PROFILE(SMBfindnclose
);
8915 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8916 struct trans_state
*state
)
8918 if (get_Protocol() >= PROTOCOL_NT1
) {
8919 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8920 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8923 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8924 if (state
->call
!= TRANSACT2_QFSINFO
&&
8925 state
->call
!= TRANSACT2_SETFSINFO
) {
8926 DEBUG(0,("handle_trans2: encryption required "
8928 (unsigned int)state
->call
));
8929 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8934 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8936 /* Now we must call the relevant TRANS2 function */
8937 switch(state
->call
) {
8938 case TRANSACT2_OPEN
:
8940 START_PROFILE(Trans2_open
);
8941 call_trans2open(conn
, req
,
8942 &state
->param
, state
->total_param
,
8943 &state
->data
, state
->total_data
,
8944 state
->max_data_return
);
8945 END_PROFILE(Trans2_open
);
8949 case TRANSACT2_FINDFIRST
:
8951 START_PROFILE(Trans2_findfirst
);
8952 call_trans2findfirst(conn
, req
,
8953 &state
->param
, state
->total_param
,
8954 &state
->data
, state
->total_data
,
8955 state
->max_data_return
);
8956 END_PROFILE(Trans2_findfirst
);
8960 case TRANSACT2_FINDNEXT
:
8962 START_PROFILE(Trans2_findnext
);
8963 call_trans2findnext(conn
, req
,
8964 &state
->param
, state
->total_param
,
8965 &state
->data
, state
->total_data
,
8966 state
->max_data_return
);
8967 END_PROFILE(Trans2_findnext
);
8971 case TRANSACT2_QFSINFO
:
8973 START_PROFILE(Trans2_qfsinfo
);
8974 call_trans2qfsinfo(conn
, req
,
8975 &state
->param
, state
->total_param
,
8976 &state
->data
, state
->total_data
,
8977 state
->max_data_return
);
8978 END_PROFILE(Trans2_qfsinfo
);
8982 case TRANSACT2_SETFSINFO
:
8984 START_PROFILE(Trans2_setfsinfo
);
8985 call_trans2setfsinfo(conn
, req
,
8986 &state
->param
, state
->total_param
,
8987 &state
->data
, state
->total_data
,
8988 state
->max_data_return
);
8989 END_PROFILE(Trans2_setfsinfo
);
8993 case TRANSACT2_QPATHINFO
:
8994 case TRANSACT2_QFILEINFO
:
8996 START_PROFILE(Trans2_qpathinfo
);
8997 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8998 &state
->param
, state
->total_param
,
8999 &state
->data
, state
->total_data
,
9000 state
->max_data_return
);
9001 END_PROFILE(Trans2_qpathinfo
);
9005 case TRANSACT2_SETPATHINFO
:
9006 case TRANSACT2_SETFILEINFO
:
9008 START_PROFILE(Trans2_setpathinfo
);
9009 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9010 &state
->param
, state
->total_param
,
9011 &state
->data
, state
->total_data
,
9012 state
->max_data_return
);
9013 END_PROFILE(Trans2_setpathinfo
);
9017 case TRANSACT2_FINDNOTIFYFIRST
:
9019 START_PROFILE(Trans2_findnotifyfirst
);
9020 call_trans2findnotifyfirst(conn
, req
,
9021 &state
->param
, state
->total_param
,
9022 &state
->data
, state
->total_data
,
9023 state
->max_data_return
);
9024 END_PROFILE(Trans2_findnotifyfirst
);
9028 case TRANSACT2_FINDNOTIFYNEXT
:
9030 START_PROFILE(Trans2_findnotifynext
);
9031 call_trans2findnotifynext(conn
, req
,
9032 &state
->param
, state
->total_param
,
9033 &state
->data
, state
->total_data
,
9034 state
->max_data_return
);
9035 END_PROFILE(Trans2_findnotifynext
);
9039 case TRANSACT2_MKDIR
:
9041 START_PROFILE(Trans2_mkdir
);
9042 call_trans2mkdir(conn
, req
,
9043 &state
->param
, state
->total_param
,
9044 &state
->data
, state
->total_data
,
9045 state
->max_data_return
);
9046 END_PROFILE(Trans2_mkdir
);
9050 case TRANSACT2_GET_DFS_REFERRAL
:
9052 START_PROFILE(Trans2_get_dfs_referral
);
9053 call_trans2getdfsreferral(conn
, req
,
9054 &state
->param
, state
->total_param
,
9055 &state
->data
, state
->total_data
,
9056 state
->max_data_return
);
9057 END_PROFILE(Trans2_get_dfs_referral
);
9061 case TRANSACT2_IOCTL
:
9063 START_PROFILE(Trans2_ioctl
);
9064 call_trans2ioctl(conn
, req
,
9065 &state
->param
, state
->total_param
,
9066 &state
->data
, state
->total_data
,
9067 state
->max_data_return
);
9068 END_PROFILE(Trans2_ioctl
);
9073 /* Error in request */
9074 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9075 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9079 /****************************************************************************
9080 Reply to a SMBtrans2.
9081 ****************************************************************************/
9083 void reply_trans2(struct smb_request
*req
)
9085 connection_struct
*conn
= req
->conn
;
9090 unsigned int tran_call
;
9091 struct trans_state
*state
;
9094 START_PROFILE(SMBtrans2
);
9096 if (req
->wct
< 14) {
9097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9098 END_PROFILE(SMBtrans2
);
9102 dsoff
= SVAL(req
->vwv
+12, 0);
9103 dscnt
= SVAL(req
->vwv
+11, 0);
9104 psoff
= SVAL(req
->vwv
+10, 0);
9105 pscnt
= SVAL(req
->vwv
+9, 0);
9106 tran_call
= SVAL(req
->vwv
+14, 0);
9108 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9109 if (!NT_STATUS_IS_OK(result
)) {
9110 DEBUG(2, ("Got invalid trans2 request: %s\n",
9111 nt_errstr(result
)));
9112 reply_nterror(req
, result
);
9113 END_PROFILE(SMBtrans2
);
9118 switch (tran_call
) {
9119 /* List the allowed trans2 calls on IPC$ */
9120 case TRANSACT2_OPEN
:
9121 case TRANSACT2_GET_DFS_REFERRAL
:
9122 case TRANSACT2_QFILEINFO
:
9123 case TRANSACT2_QFSINFO
:
9124 case TRANSACT2_SETFSINFO
:
9127 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9128 END_PROFILE(SMBtrans2
);
9133 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9134 DEBUG(0, ("talloc failed\n"));
9135 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9136 END_PROFILE(SMBtrans2
);
9140 state
->cmd
= SMBtrans2
;
9142 state
->mid
= req
->mid
;
9143 state
->vuid
= req
->vuid
;
9144 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9145 state
->setup
= NULL
;
9146 state
->total_param
= SVAL(req
->vwv
+0, 0);
9147 state
->param
= NULL
;
9148 state
->total_data
= SVAL(req
->vwv
+1, 0);
9150 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9151 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9152 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9153 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9154 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9156 state
->call
= tran_call
;
9158 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9159 is so as a sanity check */
9160 if (state
->setup_count
!= 1) {
9162 * Need to have rc=0 for ioctl to get job id for OS/2.
9163 * Network printing will fail if function is not successful.
9164 * Similar function in reply.c will be used if protocol
9165 * is LANMAN1.0 instead of LM1.2X002.
9166 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9167 * outbuf doesn't have to be set(only job id is used).
9169 if ( (state
->setup_count
== 4)
9170 && (tran_call
== TRANSACT2_IOCTL
)
9171 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9172 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9173 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9175 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9176 DEBUG(2,("Transaction is %d\n",tran_call
));
9178 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9179 END_PROFILE(SMBtrans2
);
9184 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9187 if (state
->total_data
) {
9189 if (trans_oob(state
->total_data
, 0, dscnt
)
9190 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9194 /* Can't use talloc here, the core routines do realloc on the
9195 * params and data. */
9196 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9197 if (state
->data
== NULL
) {
9198 DEBUG(0,("reply_trans2: data malloc fail for %u "
9199 "bytes !\n", (unsigned int)state
->total_data
));
9201 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9202 END_PROFILE(SMBtrans2
);
9206 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9209 if (state
->total_param
) {
9211 if (trans_oob(state
->total_param
, 0, pscnt
)
9212 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9216 /* Can't use talloc here, the core routines do realloc on the
9217 * params and data. */
9218 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9219 if (state
->param
== NULL
) {
9220 DEBUG(0,("reply_trans: param malloc fail for %u "
9221 "bytes !\n", (unsigned int)state
->total_param
));
9222 SAFE_FREE(state
->data
);
9224 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9225 END_PROFILE(SMBtrans2
);
9229 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9232 state
->received_data
= dscnt
;
9233 state
->received_param
= pscnt
;
9235 if ((state
->received_param
== state
->total_param
) &&
9236 (state
->received_data
== state
->total_data
)) {
9238 handle_trans2(conn
, req
, state
);
9240 SAFE_FREE(state
->data
);
9241 SAFE_FREE(state
->param
);
9243 END_PROFILE(SMBtrans2
);
9247 DLIST_ADD(conn
->pending_trans
, state
);
9249 /* We need to send an interim response then receive the rest
9250 of the parameter/data bytes */
9251 reply_outbuf(req
, 0, 0);
9252 show_msg((char *)req
->outbuf
);
9253 END_PROFILE(SMBtrans2
);
9258 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9259 SAFE_FREE(state
->data
);
9260 SAFE_FREE(state
->param
);
9262 END_PROFILE(SMBtrans2
);
9263 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9267 /****************************************************************************
9268 Reply to a SMBtranss2
9269 ****************************************************************************/
9271 void reply_transs2(struct smb_request
*req
)
9273 connection_struct
*conn
= req
->conn
;
9274 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9275 struct trans_state
*state
;
9277 START_PROFILE(SMBtranss2
);
9279 show_msg((const char *)req
->inbuf
);
9281 /* Windows clients expect all replies to
9282 a transact secondary (SMBtranss2 0x33)
9283 to have a command code of transact
9284 (SMBtrans2 0x32). See bug #8989
9285 and also [MS-CIFS] section 2.2.4.47.2
9288 req
->cmd
= SMBtrans2
;
9291 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9292 END_PROFILE(SMBtranss2
);
9296 for (state
= conn
->pending_trans
; state
!= NULL
;
9297 state
= state
->next
) {
9298 if (state
->mid
== req
->mid
) {
9303 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9304 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9305 END_PROFILE(SMBtranss2
);
9309 /* Revise state->total_param and state->total_data in case they have
9310 changed downwards */
9312 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9313 state
->total_param
= SVAL(req
->vwv
+0, 0);
9314 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9315 state
->total_data
= SVAL(req
->vwv
+1, 0);
9317 pcnt
= SVAL(req
->vwv
+2, 0);
9318 poff
= SVAL(req
->vwv
+3, 0);
9319 pdisp
= SVAL(req
->vwv
+4, 0);
9321 dcnt
= SVAL(req
->vwv
+5, 0);
9322 doff
= SVAL(req
->vwv
+6, 0);
9323 ddisp
= SVAL(req
->vwv
+7, 0);
9325 state
->received_param
+= pcnt
;
9326 state
->received_data
+= dcnt
;
9328 if ((state
->received_data
> state
->total_data
) ||
9329 (state
->received_param
> state
->total_param
))
9333 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9334 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9337 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9341 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9342 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9345 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9348 if ((state
->received_param
< state
->total_param
) ||
9349 (state
->received_data
< state
->total_data
)) {
9350 END_PROFILE(SMBtranss2
);
9354 handle_trans2(conn
, req
, state
);
9356 DLIST_REMOVE(conn
->pending_trans
, state
);
9357 SAFE_FREE(state
->data
);
9358 SAFE_FREE(state
->param
);
9361 END_PROFILE(SMBtranss2
);
9366 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9367 DLIST_REMOVE(conn
->pending_trans
, state
);
9368 SAFE_FREE(state
->data
);
9369 SAFE_FREE(state
->param
);
9371 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9372 END_PROFILE(SMBtranss2
);