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;
2478 if (total_params
< 13) {
2479 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2483 dirtype
= SVAL(params
,0);
2484 maxentries
= SVAL(params
,2);
2485 findfirst_flags
= SVAL(params
,4);
2486 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2487 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2488 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2489 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2490 security_token_has_privilege(get_current_nttok(conn
),
2493 info_level
= SVAL(params
,6);
2495 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2496 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2497 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2499 info_level
, max_data_bytes
));
2502 /* W2K3 seems to treat zero as 1. */
2506 switch (info_level
) {
2507 case SMB_FIND_INFO_STANDARD
:
2508 case SMB_FIND_EA_SIZE
:
2509 case SMB_FIND_EA_LIST
:
2510 case SMB_FIND_FILE_DIRECTORY_INFO
:
2511 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2512 case SMB_FIND_FILE_NAMES_INFO
:
2513 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2514 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2515 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2517 case SMB_FIND_FILE_UNIX
:
2518 case SMB_FIND_FILE_UNIX_INFO2
:
2519 /* Always use filesystem for UNIX mtime query. */
2520 ask_sharemode
= false;
2521 if (!lp_unix_extensions()) {
2522 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2525 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2528 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2532 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2533 params
+12, total_params
- 12,
2534 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2535 if (!NT_STATUS_IS_OK(ntstatus
)) {
2536 reply_nterror(req
, ntstatus
);
2542 ntstatus
= filename_convert_with_privilege(ctx
,
2547 &mask_contains_wcard
,
2550 ntstatus
= filename_convert(ctx
, conn
,
2551 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2554 &mask_contains_wcard
,
2558 if (!NT_STATUS_IS_OK(ntstatus
)) {
2559 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2560 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2561 ERRSRV
, ERRbadpath
);
2564 reply_nterror(req
, ntstatus
);
2568 mask
= smb_dname
->original_lcomp
;
2570 directory
= smb_dname
->base_name
;
2572 p
= strrchr_m(directory
,'/');
2574 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2575 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2576 mask
= talloc_strdup(ctx
,"*");
2578 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2581 mask_contains_wcard
= True
;
2587 if (p
== NULL
|| p
== directory
) {
2588 /* Ensure we don't have a directory name of "". */
2589 directory
= talloc_strdup(talloc_tos(), ".");
2591 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2596 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2598 if (info_level
== SMB_FIND_EA_LIST
) {
2601 if (total_data
< 4) {
2602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2606 ea_size
= IVAL(pdata
,0);
2607 if (ea_size
!= total_data
) {
2608 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2609 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2610 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2614 if (!lp_ea_support(SNUM(conn
))) {
2615 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2619 /* Pull out the list of names. */
2620 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2622 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2627 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2628 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2632 *ppdata
= (char *)SMB_REALLOC(
2633 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2634 if(*ppdata
== NULL
) {
2635 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2639 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2641 /* Realloc the params space */
2642 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2643 if (*pparams
== NULL
) {
2644 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2649 /* Save the wildcard match and attribs we are using on this directory -
2650 needed as lanman2 assumes these are being saved between calls */
2652 ntstatus
= dptr_create(conn
,
2660 mask_contains_wcard
,
2664 if (!NT_STATUS_IS_OK(ntstatus
)) {
2665 reply_nterror(req
, ntstatus
);
2670 /* Remember this in case we have
2671 to do a findnext. */
2672 dptr_set_priv(dirptr
);
2675 dptr_num
= dptr_dnum(dirptr
);
2676 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2678 /* Initialize per TRANS2_FIND_FIRST operation data */
2679 dptr_init_search_op(dirptr
);
2681 /* We don't need to check for VOL here as this is returned by
2682 a different TRANS2 call. */
2684 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2685 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2686 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2687 dont_descend
= True
;
2690 space_remaining
= max_data_bytes
;
2691 out_of_space
= False
;
2693 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2694 bool got_exact_match
= False
;
2696 /* this is a heuristic to avoid seeking the dirptr except when
2697 absolutely necessary. It allows for a filename of about 40 chars */
2698 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2699 out_of_space
= True
;
2702 ntstatus
= get_lanman2_dir_entry(ctx
,
2706 mask
,dirtype
,info_level
,
2707 requires_resume_key
,dont_descend
,
2712 &last_entry_off
, ea_list
);
2713 if (NT_STATUS_EQUAL(ntstatus
,
2714 NT_STATUS_ILLEGAL_CHARACTER
)) {
2716 * Bad character conversion on name. Ignore this
2721 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2722 out_of_space
= true;
2724 finished
= !NT_STATUS_IS_OK(ntstatus
);
2728 if (!finished
&& !out_of_space
)
2732 * As an optimisation if we know we aren't looking
2733 * for a wildcard name (ie. the name matches the wildcard exactly)
2734 * then we can finish on any (first) match.
2735 * This speeds up large directory searches. JRA.
2741 /* Ensure space_remaining never goes -ve. */
2742 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2743 space_remaining
= 0;
2744 out_of_space
= true;
2746 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2750 /* Check if we can close the dirptr */
2751 if(close_after_first
|| (finished
&& close_if_end
)) {
2752 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2753 dptr_close(sconn
, &dptr_num
);
2757 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2758 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2759 * the protocol level is less than NT1. Tested with smbclient. JRA.
2760 * This should fix the OS/2 client bug #2335.
2763 if(numentries
== 0) {
2764 dptr_close(sconn
, &dptr_num
);
2765 if (get_Protocol() < PROTOCOL_NT1
) {
2766 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2769 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2770 ERRDOS
, ERRbadfile
);
2775 /* At this point pdata points to numentries directory entries. */
2777 /* Set up the return parameter block */
2778 SSVAL(params
,0,dptr_num
);
2779 SSVAL(params
,2,numentries
);
2780 SSVAL(params
,4,finished
);
2781 SSVAL(params
,6,0); /* Never an EA error */
2782 SSVAL(params
,8,last_entry_off
);
2784 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2787 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2788 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2790 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2794 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2795 smb_fn_name(req
->cmd
),
2796 mask
, directory
, dirtype
, numentries
) );
2799 * Force a name mangle here to ensure that the
2800 * mask as an 8.3 name is top of the mangled cache.
2801 * The reasons for this are subtle. Don't remove
2802 * this code unless you know what you are doing
2803 * (see PR#13758). JRA.
2806 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2807 char mangled_name
[13];
2808 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2816 TALLOC_FREE(smb_dname
);
2820 /****************************************************************************
2821 Reply to a TRANS2_FINDNEXT.
2822 ****************************************************************************/
2824 static void call_trans2findnext(connection_struct
*conn
,
2825 struct smb_request
*req
,
2826 char **pparams
, int total_params
,
2827 char **ppdata
, int total_data
,
2828 unsigned int max_data_bytes
)
2830 /* We must be careful here that we don't return more than the
2831 allowed number of data bytes. If this means returning fewer than
2832 maxentries then so be it. We assume that the redirector has
2833 enough room for the fixed number of parameter bytes it has
2835 char *params
= *pparams
;
2836 char *pdata
= *ppdata
;
2840 uint16_t info_level
;
2841 uint32_t resume_key
;
2842 uint16_t findnext_flags
;
2843 bool close_after_request
;
2845 bool requires_resume_key
;
2847 bool mask_contains_wcard
= False
;
2848 char *resume_name
= NULL
;
2849 const char *mask
= NULL
;
2850 const char *directory
= NULL
;
2854 int i
, last_entry_off
=0;
2855 bool finished
= False
;
2856 bool dont_descend
= False
;
2857 bool out_of_space
= False
;
2858 int space_remaining
;
2859 struct ea_list
*ea_list
= NULL
;
2860 NTSTATUS ntstatus
= NT_STATUS_OK
;
2861 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2862 TALLOC_CTX
*ctx
= talloc_tos();
2863 struct dptr_struct
*dirptr
;
2864 struct smbd_server_connection
*sconn
= req
->sconn
;
2865 bool backup_priv
= false;
2867 if (total_params
< 13) {
2868 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2872 dptr_num
= SVAL(params
,0);
2873 maxentries
= SVAL(params
,2);
2874 info_level
= SVAL(params
,4);
2875 resume_key
= IVAL(params
,6);
2876 findnext_flags
= SVAL(params
,10);
2877 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2878 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2879 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2880 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2882 if (!continue_bit
) {
2883 /* We only need resume_name if continue_bit is zero. */
2884 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2886 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2887 &mask_contains_wcard
);
2888 if (!NT_STATUS_IS_OK(ntstatus
)) {
2889 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2890 complain (it thinks we're asking for the directory above the shared
2891 path or an invalid name). Catch this as the resume name is only compared, never used in
2892 a file access. JRA. */
2893 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2894 &resume_name
, params
+12,
2898 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2899 reply_nterror(req
, ntstatus
);
2905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2907 resume_key = %d resume name = %s continue=%d level = %d\n",
2908 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2909 requires_resume_key
, resume_key
,
2910 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2913 /* W2K3 seems to treat zero as 1. */
2917 switch (info_level
) {
2918 case SMB_FIND_INFO_STANDARD
:
2919 case SMB_FIND_EA_SIZE
:
2920 case SMB_FIND_EA_LIST
:
2921 case SMB_FIND_FILE_DIRECTORY_INFO
:
2922 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2923 case SMB_FIND_FILE_NAMES_INFO
:
2924 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2925 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2926 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2928 case SMB_FIND_FILE_UNIX
:
2929 case SMB_FIND_FILE_UNIX_INFO2
:
2930 /* Always use filesystem for UNIX mtime query. */
2931 ask_sharemode
= false;
2932 if (!lp_unix_extensions()) {
2933 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2938 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2942 if (info_level
== SMB_FIND_EA_LIST
) {
2945 if (total_data
< 4) {
2946 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2950 ea_size
= IVAL(pdata
,0);
2951 if (ea_size
!= total_data
) {
2952 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2953 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2954 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2958 if (!lp_ea_support(SNUM(conn
))) {
2959 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2963 /* Pull out the list of names. */
2964 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2966 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2971 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2972 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2976 *ppdata
= (char *)SMB_REALLOC(
2977 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2978 if(*ppdata
== NULL
) {
2979 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2984 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2986 /* Realloc the params space */
2987 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2988 if(*pparams
== NULL
) {
2989 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2995 /* Check that the dptr is valid */
2996 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2997 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3001 directory
= dptr_path(sconn
, dptr_num
);
3003 /* Get the wildcard mask from the dptr */
3004 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3005 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3006 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3010 /* Get the attr mask from the dptr */
3011 dirtype
= dptr_attr(sconn
, dptr_num
);
3013 backup_priv
= dptr_get_priv(dirptr
);
3015 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3016 "backup_priv = %d\n",
3017 dptr_num
, mask
, dirtype
,
3019 dptr_TellDir(dirptr
),
3022 /* Initialize per TRANS2_FIND_NEXT operation data */
3023 dptr_init_search_op(dirptr
);
3025 /* We don't need to check for VOL here as this is returned by
3026 a different TRANS2 call. */
3028 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3029 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3030 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3031 dont_descend
= True
;
3034 space_remaining
= max_data_bytes
;
3035 out_of_space
= False
;
3042 * Seek to the correct position. We no longer use the resume key but
3043 * depend on the last file name instead.
3046 if(!continue_bit
&& resume_name
&& *resume_name
) {
3049 long current_pos
= 0;
3051 * Remember, name_to_8_3 is called by
3052 * get_lanman2_dir_entry(), so the resume name
3053 * could be mangled. Ensure we check the unmangled name.
3056 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3057 char *new_resume_name
= NULL
;
3058 mangle_lookup_name_from_8_3(ctx
,
3062 if (new_resume_name
) {
3063 resume_name
= new_resume_name
;
3068 * Fix for NT redirector problem triggered by resume key indexes
3069 * changing between directory scans. We now return a resume key of 0
3070 * and instead look for the filename to continue from (also given
3071 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3072 * findfirst/findnext (as is usual) then the directory pointer
3073 * should already be at the correct place.
3076 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3077 } /* end if resume_name && !continue_bit */
3079 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3080 bool got_exact_match
= False
;
3082 /* this is a heuristic to avoid seeking the dirptr except when
3083 absolutely necessary. It allows for a filename of about 40 chars */
3084 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3085 out_of_space
= True
;
3088 ntstatus
= get_lanman2_dir_entry(ctx
,
3092 mask
,dirtype
,info_level
,
3093 requires_resume_key
,dont_descend
,
3098 &last_entry_off
, ea_list
);
3099 if (NT_STATUS_EQUAL(ntstatus
,
3100 NT_STATUS_ILLEGAL_CHARACTER
)) {
3102 * Bad character conversion on name. Ignore this
3107 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3108 out_of_space
= true;
3110 finished
= !NT_STATUS_IS_OK(ntstatus
);
3114 if (!finished
&& !out_of_space
)
3118 * As an optimisation if we know we aren't looking
3119 * for a wildcard name (ie. the name matches the wildcard exactly)
3120 * then we can finish on any (first) match.
3121 * This speeds up large directory searches. JRA.
3127 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3130 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3131 smb_fn_name(req
->cmd
),
3132 mask
, directory
, dirtype
, numentries
) );
3134 /* Check if we can close the dirptr */
3135 if(close_after_request
|| (finished
&& close_if_end
)) {
3136 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3137 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3144 /* Set up the return parameter block */
3145 SSVAL(params
,0,numentries
);
3146 SSVAL(params
,2,finished
);
3147 SSVAL(params
,4,0); /* Never an EA error */
3148 SSVAL(params
,6,last_entry_off
);
3150 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3156 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3158 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3162 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3164 SMB_ASSERT(extended_info
!= NULL
);
3166 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3167 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3168 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3169 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3170 #ifdef SAMBA_VERSION_REVISION
3171 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3173 extended_info
->samba_subversion
= 0;
3174 #ifdef SAMBA_VERSION_RC_RELEASE
3175 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3177 #ifdef SAMBA_VERSION_PRE_RELEASE
3178 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3181 #ifdef SAMBA_VERSION_VENDOR_PATCH
3182 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3184 extended_info
->samba_gitcommitdate
= 0;
3185 #ifdef SAMBA_VERSION_COMMIT_TIME
3186 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3189 memset(extended_info
->samba_version_string
, 0,
3190 sizeof(extended_info
->samba_version_string
));
3192 snprintf (extended_info
->samba_version_string
,
3193 sizeof(extended_info
->samba_version_string
),
3194 "%s", samba_version_string());
3197 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3198 connection_struct
*conn
,
3199 TALLOC_CTX
*mem_ctx
,
3200 uint16_t info_level
,
3202 unsigned int max_data_bytes
,
3203 size_t *fixed_portion
,
3204 struct smb_filename
*fname
,
3208 char *pdata
, *end_data
;
3211 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3212 int snum
= SNUM(conn
);
3213 const char *fstype
= lp_fstype(SNUM(conn
));
3214 const char *filename
= NULL
;
3215 const uint64_t bytes_per_sector
= 512;
3216 uint32_t additional_flags
= 0;
3217 struct smb_filename smb_fname
;
3219 NTSTATUS status
= NT_STATUS_OK
;
3222 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3225 filename
= fname
->base_name
;
3229 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3230 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3231 "info level (0x%x) on IPC$.\n",
3232 (unsigned int)info_level
));
3233 return NT_STATUS_ACCESS_DENIED
;
3237 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3239 ZERO_STRUCT(smb_fname
);
3240 smb_fname
.base_name
= discard_const_p(char, filename
);
3242 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3243 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3244 return map_nt_error_from_unix(errno
);
3249 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3250 return NT_STATUS_INVALID_PARAMETER
;
3253 *ppdata
= (char *)SMB_REALLOC(
3254 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3255 if (*ppdata
== NULL
) {
3256 return NT_STATUS_NO_MEMORY
;
3260 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3261 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3265 switch (info_level
) {
3266 case SMB_INFO_ALLOCATION
:
3268 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3270 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3272 if (df_ret
== (uint64_t)-1) {
3273 return map_nt_error_from_unix(errno
);
3276 block_size
= lp_block_size(snum
);
3277 if (bsize
< block_size
) {
3278 uint64_t factor
= block_size
/bsize
;
3283 if (bsize
> block_size
) {
3284 uint64_t factor
= bsize
/block_size
;
3289 sectors_per_unit
= bsize
/bytes_per_sector
;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3292 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3293 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3295 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3296 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3297 SIVAL(pdata
,l1_cUnit
,dsize
);
3298 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3299 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3303 case SMB_INFO_VOLUME
:
3304 /* Return volume name */
3306 * Add volume serial number - hash of a combination of
3307 * the called hostname and the service name.
3309 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3311 * Win2k3 and previous mess this up by sending a name length
3312 * one byte short. I believe only older clients (OS/2 Win9x) use
3313 * this call so try fixing this by adding a terminating null to
3314 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3316 status
= srvstr_push(
3318 pdata
+l2_vol_szVolLabel
, vname
,
3319 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3320 STR_NOALIGN
|STR_TERMINATE
, &len
);
3321 if (!NT_STATUS_IS_OK(status
)) {
3324 SCVAL(pdata
,l2_vol_cch
,len
);
3325 data_len
= l2_vol_szVolLabel
+ len
;
3326 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3327 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3328 (unsigned)len
, vname
));
3331 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3332 case SMB_FS_ATTRIBUTE_INFORMATION
:
3334 additional_flags
= 0;
3335 #if defined(HAVE_SYS_QUOTAS)
3336 additional_flags
|= FILE_VOLUME_QUOTAS
;
3339 if(lp_nt_acl_support(SNUM(conn
))) {
3340 additional_flags
|= FILE_PERSISTENT_ACLS
;
3343 /* Capabilities are filled in at connection time through STATVFS call */
3344 additional_flags
|= conn
->fs_capabilities
;
3345 additional_flags
|= lp_parm_int(conn
->params
->service
,
3346 "share", "fake_fscaps",
3349 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3350 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3351 additional_flags
); /* FS ATTRIBUTES */
3353 SIVAL(pdata
,4,255); /* Max filename component length */
3354 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3355 and will think we can't do long filenames */
3356 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3357 PTR_DIFF(end_data
, pdata
+12),
3359 if (!NT_STATUS_IS_OK(status
)) {
3363 data_len
= 12 + len
;
3364 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3365 /* the client only requested a portion of the
3367 data_len
= max_data_bytes
;
3368 status
= STATUS_BUFFER_OVERFLOW
;
3370 *fixed_portion
= 16;
3373 case SMB_QUERY_FS_LABEL_INFO
:
3374 case SMB_FS_LABEL_INFORMATION
:
3375 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3376 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3377 if (!NT_STATUS_IS_OK(status
)) {
3384 case SMB_QUERY_FS_VOLUME_INFO
:
3385 case SMB_FS_VOLUME_INFORMATION
:
3388 * Add volume serial number - hash of a combination of
3389 * the called hostname and the service name.
3391 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3392 (str_checksum(get_local_machine_name())<<16));
3394 /* Max label len is 32 characters. */
3395 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3396 PTR_DIFF(end_data
, pdata
+18),
3398 if (!NT_STATUS_IS_OK(status
)) {
3401 SIVAL(pdata
,12,len
);
3404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3405 (int)strlen(vname
),vname
,
3406 lp_servicename(talloc_tos(), snum
)));
3407 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3408 /* the client only requested a portion of the
3410 data_len
= max_data_bytes
;
3411 status
= STATUS_BUFFER_OVERFLOW
;
3413 *fixed_portion
= 24;
3416 case SMB_QUERY_FS_SIZE_INFO
:
3417 case SMB_FS_SIZE_INFORMATION
:
3419 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3421 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3423 if (df_ret
== (uint64_t)-1) {
3424 return map_nt_error_from_unix(errno
);
3426 block_size
= lp_block_size(snum
);
3427 if (bsize
< block_size
) {
3428 uint64_t factor
= block_size
/bsize
;
3433 if (bsize
> block_size
) {
3434 uint64_t factor
= bsize
/block_size
;
3439 sectors_per_unit
= bsize
/bytes_per_sector
;
3440 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3441 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3442 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3443 SBIG_UINT(pdata
,0,dsize
);
3444 SBIG_UINT(pdata
,8,dfree
);
3445 SIVAL(pdata
,16,sectors_per_unit
);
3446 SIVAL(pdata
,20,bytes_per_sector
);
3447 *fixed_portion
= 24;
3451 case SMB_FS_FULL_SIZE_INFORMATION
:
3453 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3455 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3457 if (df_ret
== (uint64_t)-1) {
3458 return map_nt_error_from_unix(errno
);
3460 block_size
= lp_block_size(snum
);
3461 if (bsize
< block_size
) {
3462 uint64_t factor
= block_size
/bsize
;
3467 if (bsize
> block_size
) {
3468 uint64_t factor
= bsize
/block_size
;
3473 sectors_per_unit
= bsize
/bytes_per_sector
;
3474 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3475 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3476 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3477 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3478 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3479 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3480 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3481 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3482 *fixed_portion
= 32;
3486 case SMB_QUERY_FS_DEVICE_INFO
:
3487 case SMB_FS_DEVICE_INFORMATION
:
3489 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3491 if (!CAN_WRITE(conn
)) {
3492 characteristics
|= FILE_READ_ONLY_DEVICE
;
3495 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3496 SIVAL(pdata
,4,characteristics
);
3501 #ifdef HAVE_SYS_QUOTAS
3502 case SMB_FS_QUOTA_INFORMATION
:
3504 * what we have to send --metze:
3506 * Unknown1: 24 NULL bytes
3507 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3508 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3509 * Quota Flags: 2 byte :
3510 * Unknown3: 6 NULL bytes
3514 * details for Quota Flags:
3516 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3517 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3518 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3519 * 0x0001 Enable Quotas: enable quota for this fs
3523 /* we need to fake up a fsp here,
3524 * because its not send in this call
3527 SMB_NTQUOTA_STRUCT quotas
;
3530 ZERO_STRUCT(quotas
);
3533 fsp
.fnum
= FNUM_FIELD_INVALID
;
3536 if (get_current_uid(conn
) != 0) {
3537 DEBUG(0,("get_user_quota: access_denied "
3538 "service [%s] user [%s]\n",
3539 lp_servicename(talloc_tos(), SNUM(conn
)),
3540 conn
->session_info
->unix_info
->unix_name
));
3541 return NT_STATUS_ACCESS_DENIED
;
3544 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3545 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3546 return map_nt_error_from_unix(errno
);
3551 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3552 lp_servicename(talloc_tos(), SNUM(conn
))));
3554 /* Unknown1 24 NULL bytes*/
3555 SBIG_UINT(pdata
,0,(uint64_t)0);
3556 SBIG_UINT(pdata
,8,(uint64_t)0);
3557 SBIG_UINT(pdata
,16,(uint64_t)0);
3559 /* Default Soft Quota 8 bytes */
3560 SBIG_UINT(pdata
,24,quotas
.softlim
);
3562 /* Default Hard Quota 8 bytes */
3563 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3565 /* Quota flag 2 bytes */
3566 SSVAL(pdata
,40,quotas
.qflags
);
3568 /* Unknown3 6 NULL bytes */
3574 #endif /* HAVE_SYS_QUOTAS */
3575 case SMB_FS_OBJECTID_INFORMATION
:
3577 unsigned char objid
[16];
3578 struct smb_extended_info extended_info
;
3579 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3580 samba_extended_info_version (&extended_info
);
3581 SIVAL(pdata
,16,extended_info
.samba_magic
);
3582 SIVAL(pdata
,20,extended_info
.samba_version
);
3583 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3584 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3585 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3590 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3594 * These values match a physical Windows Server 2012
3595 * share backed by NTFS atop spinning rust.
3597 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3598 /* logical_bytes_per_sector */
3599 SIVAL(pdata
, 0, bytes_per_sector
);
3600 /* phys_bytes_per_sector_atomic */
3601 SIVAL(pdata
, 4, bytes_per_sector
);
3602 /* phys_bytes_per_sector_perf */
3603 SIVAL(pdata
, 8, bytes_per_sector
);
3604 /* fs_effective_phys_bytes_per_sector_atomic */
3605 SIVAL(pdata
, 12, bytes_per_sector
);
3607 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3608 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3609 /* byte_off_sector_align */
3610 SIVAL(pdata
, 20, 0);
3611 /* byte_off_partition_align */
3612 SIVAL(pdata
, 24, 0);
3613 *fixed_portion
= 28;
3619 * Query the version and capabilities of the CIFS UNIX extensions
3623 case SMB_QUERY_CIFS_UNIX_INFO
:
3625 bool large_write
= lp_min_receive_file_size() &&
3626 !srv_is_signing_active(xconn
);
3627 bool large_read
= !srv_is_signing_active(xconn
);
3628 int encrypt_caps
= 0;
3630 if (!lp_unix_extensions()) {
3631 return NT_STATUS_INVALID_LEVEL
;
3634 switch (conn
->encrypt_level
) {
3635 case SMB_SIGNING_OFF
:
3638 case SMB_SIGNING_IF_REQUIRED
:
3639 case SMB_SIGNING_DEFAULT
:
3640 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3642 case SMB_SIGNING_REQUIRED
:
3643 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3644 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3645 large_write
= false;
3651 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3652 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3654 /* We have POSIX ACLs, pathname, encryption,
3655 * large read/write, and locking capability. */
3657 SBIG_UINT(pdata
,4,((uint64_t)(
3658 CIFS_UNIX_POSIX_ACLS_CAP
|
3659 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3660 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3661 CIFS_UNIX_EXTATTR_CAP
|
3662 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3664 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3666 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3670 case SMB_QUERY_POSIX_FS_INFO
:
3673 vfs_statvfs_struct svfs
;
3675 if (!lp_unix_extensions()) {
3676 return NT_STATUS_INVALID_LEVEL
;
3679 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3683 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3684 SIVAL(pdata
,4,svfs
.BlockSize
);
3685 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3686 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3687 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3688 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3689 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3690 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3691 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3693 } else if (rc
== EOPNOTSUPP
) {
3694 return NT_STATUS_INVALID_LEVEL
;
3695 #endif /* EOPNOTSUPP */
3697 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3698 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3703 case SMB_QUERY_POSIX_WHOAMI
:
3709 if (!lp_unix_extensions()) {
3710 return NT_STATUS_INVALID_LEVEL
;
3713 if (max_data_bytes
< 40) {
3714 return NT_STATUS_BUFFER_TOO_SMALL
;
3717 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3718 flags
|= SMB_WHOAMI_GUEST
;
3721 /* NOTE: 8 bytes for UID/GID, irrespective of native
3722 * platform size. This matches
3723 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3725 data_len
= 4 /* flags */
3732 + 4 /* pad/reserved */
3733 + (conn
->session_info
->unix_token
->ngroups
* 8)
3735 + (conn
->session_info
->security_token
->num_sids
*
3739 SIVAL(pdata
, 0, flags
);
3740 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3742 (uint64_t)conn
->session_info
->unix_token
->uid
);
3743 SBIG_UINT(pdata
, 16,
3744 (uint64_t)conn
->session_info
->unix_token
->gid
);
3747 if (data_len
>= max_data_bytes
) {
3748 /* Potential overflow, skip the GIDs and SIDs. */
3750 SIVAL(pdata
, 24, 0); /* num_groups */
3751 SIVAL(pdata
, 28, 0); /* num_sids */
3752 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3753 SIVAL(pdata
, 36, 0); /* reserved */
3759 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3760 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3762 /* We walk the SID list twice, but this call is fairly
3763 * infrequent, and I don't expect that it's performance
3764 * sensitive -- jpeach
3766 for (i
= 0, sid_bytes
= 0;
3767 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3768 sid_bytes
+= ndr_size_dom_sid(
3769 &conn
->session_info
->security_token
->sids
[i
],
3773 /* SID list byte count */
3774 SIVAL(pdata
, 32, sid_bytes
);
3776 /* 4 bytes pad/reserved - must be zero */
3777 SIVAL(pdata
, 36, 0);
3781 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3782 SBIG_UINT(pdata
, data_len
,
3783 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3789 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3790 int sid_len
= ndr_size_dom_sid(
3791 &conn
->session_info
->security_token
->sids
[i
],
3794 sid_linearize(pdata
+ data_len
, sid_len
,
3795 &conn
->session_info
->security_token
->sids
[i
]);
3796 data_len
+= sid_len
;
3802 case SMB_MAC_QUERY_FS_INFO
:
3804 * Thursby MAC extension... ONLY on NTFS filesystems
3805 * once we do streams then we don't need this
3807 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3809 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3814 return NT_STATUS_INVALID_LEVEL
;
3817 *ret_data_len
= data_len
;
3821 /****************************************************************************
3822 Reply to a TRANS2_QFSINFO (query filesystem info).
3823 ****************************************************************************/
3825 static void call_trans2qfsinfo(connection_struct
*conn
,
3826 struct smb_request
*req
,
3827 char **pparams
, int total_params
,
3828 char **ppdata
, int total_data
,
3829 unsigned int max_data_bytes
)
3831 char *params
= *pparams
;
3832 uint16_t info_level
;
3834 size_t fixed_portion
;
3837 if (total_params
< 2) {
3838 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3842 info_level
= SVAL(params
,0);
3844 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3845 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3846 DEBUG(0,("call_trans2qfsinfo: encryption required "
3847 "and info level 0x%x sent.\n",
3848 (unsigned int)info_level
));
3849 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3854 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3856 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3863 if (!NT_STATUS_IS_OK(status
)) {
3864 reply_nterror(req
, status
);
3868 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3871 DEBUG( 4, ( "%s info_level = %d\n",
3872 smb_fn_name(req
->cmd
), info_level
) );
3877 /****************************************************************************
3878 Reply to a TRANS2_SETFSINFO (set filesystem info).
3879 ****************************************************************************/
3881 static void call_trans2setfsinfo(connection_struct
*conn
,
3882 struct smb_request
*req
,
3883 char **pparams
, int total_params
,
3884 char **ppdata
, int total_data
,
3885 unsigned int max_data_bytes
)
3887 struct smbXsrv_connection
*xconn
= req
->xconn
;
3888 char *pdata
= *ppdata
;
3889 char *params
= *pparams
;
3890 uint16_t info_level
;
3892 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3893 lp_servicename(talloc_tos(), SNUM(conn
))));
3896 if (total_params
< 4) {
3897 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3903 info_level
= SVAL(params
,2);
3906 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3907 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3908 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3909 "info level (0x%x) on IPC$.\n",
3910 (unsigned int)info_level
));
3911 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3916 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3917 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3918 DEBUG(0,("call_trans2setfsinfo: encryption required "
3919 "and info level 0x%x sent.\n",
3920 (unsigned int)info_level
));
3921 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3926 switch(info_level
) {
3927 case SMB_SET_CIFS_UNIX_INFO
:
3928 if (!lp_unix_extensions()) {
3929 DEBUG(2,("call_trans2setfsinfo: "
3930 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3931 "unix extensions off\n"));
3933 NT_STATUS_INVALID_LEVEL
);
3937 /* There should be 12 bytes of capabilities set. */
3938 if (total_data
< 12) {
3941 NT_STATUS_INVALID_PARAMETER
);
3944 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3945 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3946 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3947 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3948 /* Just print these values for now. */
3949 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3950 "major = %u, minor = %u cap_low = 0x%x, "
3952 (unsigned int)xconn
->
3953 smb1
.unix_info
.client_major
,
3954 (unsigned int)xconn
->
3955 smb1
.unix_info
.client_minor
,
3956 (unsigned int)xconn
->
3957 smb1
.unix_info
.client_cap_low
,
3958 (unsigned int)xconn
->
3959 smb1
.unix_info
.client_cap_high
));
3961 /* Here is where we must switch to posix pathname processing... */
3962 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3963 lp_set_posix_pathnames();
3964 mangle_change_to_posix();
3967 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3968 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3969 /* Client that knows how to do posix locks,
3970 * but not posix open/mkdir operations. Set a
3971 * default type for read/write checks. */
3973 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3978 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3981 size_t param_len
= 0;
3982 size_t data_len
= total_data
;
3984 if (!lp_unix_extensions()) {
3987 NT_STATUS_INVALID_LEVEL
);
3991 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3994 NT_STATUS_NOT_SUPPORTED
);
3998 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3999 DEBUG( 2,("call_trans2setfsinfo: "
4000 "request transport encryption disabled"
4001 "with 'fork echo handler = yes'\n"));
4004 NT_STATUS_NOT_SUPPORTED
);
4008 DEBUG( 4,("call_trans2setfsinfo: "
4009 "request transport encryption.\n"));
4011 status
= srv_request_encryption_setup(conn
,
4012 (unsigned char **)ppdata
,
4014 (unsigned char **)pparams
,
4017 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4018 !NT_STATUS_IS_OK(status
)) {
4019 reply_nterror(req
, status
);
4023 send_trans2_replies(conn
, req
,
4031 if (NT_STATUS_IS_OK(status
)) {
4032 /* Server-side transport
4033 * encryption is now *on*. */
4034 status
= srv_encryption_start(conn
);
4035 if (!NT_STATUS_IS_OK(status
)) {
4036 char *reason
= talloc_asprintf(talloc_tos(),
4037 "Failure in setting "
4038 "up encrypted transport: %s",
4040 exit_server_cleanly(reason
);
4046 case SMB_FS_QUOTA_INFORMATION
:
4048 files_struct
*fsp
= NULL
;
4049 SMB_NTQUOTA_STRUCT quotas
;
4051 ZERO_STRUCT(quotas
);
4054 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4055 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4056 lp_servicename(talloc_tos(), SNUM(conn
)),
4057 conn
->session_info
->unix_info
->unix_name
));
4058 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4062 /* note: normally there're 48 bytes,
4063 * but we didn't use the last 6 bytes for now
4066 fsp
= file_fsp(req
, SVAL(params
,0));
4068 if (!check_fsp_ntquota_handle(conn
, req
,
4070 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4072 req
, NT_STATUS_INVALID_HANDLE
);
4076 if (total_data
< 42) {
4077 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4081 NT_STATUS_INVALID_PARAMETER
);
4085 /* unknown_1 24 NULL bytes in pdata*/
4087 /* the soft quotas 8 bytes (uint64_t)*/
4088 quotas
.softlim
= BVAL(pdata
,24);
4090 /* the hard quotas 8 bytes (uint64_t)*/
4091 quotas
.hardlim
= BVAL(pdata
,32);
4093 /* quota_flags 2 bytes **/
4094 quotas
.qflags
= SVAL(pdata
,40);
4096 /* unknown_2 6 NULL bytes follow*/
4098 /* now set the quotas */
4099 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4100 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4101 reply_nterror(req
, map_nt_error_from_unix(errno
));
4108 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4110 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4116 * sending this reply works fine,
4117 * but I'm not sure it's the same
4118 * like windows do...
4121 reply_outbuf(req
, 10, 0);
4124 #if defined(HAVE_POSIX_ACLS)
4125 /****************************************************************************
4126 Utility function to count the number of entries in a POSIX acl.
4127 ****************************************************************************/
4129 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4131 unsigned int ace_count
= 0;
4132 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4133 SMB_ACL_ENTRY_T entry
;
4135 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4137 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4138 entry_id
= SMB_ACL_NEXT_ENTRY
;
4145 /****************************************************************************
4146 Utility function to marshall a POSIX acl into wire format.
4147 ****************************************************************************/
4149 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4151 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4152 SMB_ACL_ENTRY_T entry
;
4154 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4155 SMB_ACL_TAG_T tagtype
;
4156 SMB_ACL_PERMSET_T permset
;
4157 unsigned char perms
= 0;
4158 unsigned int own_grp
;
4161 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4162 entry_id
= SMB_ACL_NEXT_ENTRY
;
4165 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4166 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4170 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4171 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4175 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4176 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4177 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4179 SCVAL(pdata
,1,perms
);
4182 case SMB_ACL_USER_OBJ
:
4183 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4184 own_grp
= (unsigned int)pst
->st_ex_uid
;
4185 SIVAL(pdata
,2,own_grp
);
4190 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4192 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4195 own_grp
= (unsigned int)*puid
;
4196 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4197 SIVAL(pdata
,2,own_grp
);
4201 case SMB_ACL_GROUP_OBJ
:
4202 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4203 own_grp
= (unsigned int)pst
->st_ex_gid
;
4204 SIVAL(pdata
,2,own_grp
);
4209 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4211 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4214 own_grp
= (unsigned int)*pgid
;
4215 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4216 SIVAL(pdata
,2,own_grp
);
4221 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4222 SIVAL(pdata
,2,0xFFFFFFFF);
4223 SIVAL(pdata
,6,0xFFFFFFFF);
4226 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4227 SIVAL(pdata
,2,0xFFFFFFFF);
4228 SIVAL(pdata
,6,0xFFFFFFFF);
4231 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4234 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4241 /****************************************************************************
4242 Store the FILE_UNIX_BASIC info.
4243 ****************************************************************************/
4245 static char *store_file_unix_basic(connection_struct
*conn
,
4248 const SMB_STRUCT_STAT
*psbuf
)
4250 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4253 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4254 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4256 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4259 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4262 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4263 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4264 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4267 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4271 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4275 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4278 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4279 devno
= psbuf
->st_ex_rdev
;
4281 devno
= psbuf
->st_ex_dev
;
4284 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4288 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4292 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4295 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4299 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4306 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4307 * the chflags(2) (or equivalent) flags.
4309 * XXX: this really should be behind the VFS interface. To do this, we would
4310 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4311 * Each VFS module could then implement its own mapping as appropriate for the
4312 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4314 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4318 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4322 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4326 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4330 { UF_HIDDEN
, EXT_HIDDEN
},
4333 /* Do not remove. We need to guarantee that this array has at least one
4334 * entry to build on HP-UX.
4340 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4341 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4345 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4346 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4347 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4348 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4353 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4354 const uint32_t smb_fflags
,
4355 const uint32_t smb_fmask
,
4358 uint32_t max_fmask
= 0;
4361 *stat_fflags
= psbuf
->st_ex_flags
;
4363 /* For each flags requested in smb_fmask, check the state of the
4364 * corresponding flag in smb_fflags and set or clear the matching
4368 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4369 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4370 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4371 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4372 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4374 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4379 /* If smb_fmask is asking to set any bits that are not supported by
4380 * our flag mappings, we should fail.
4382 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4390 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4391 * of file flags and birth (create) time.
4393 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4396 const SMB_STRUCT_STAT
*psbuf
)
4398 uint32_t file_flags
= 0;
4399 uint32_t flags_mask
= 0;
4401 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4403 /* Create (birth) time 64 bit */
4404 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4407 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4408 SIVAL(pdata
, 0, file_flags
); /* flags */
4409 SIVAL(pdata
, 4, flags_mask
); /* mask */
4415 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4416 const struct stream_struct
*streams
,
4418 unsigned int max_data_bytes
,
4419 unsigned int *data_size
)
4422 unsigned int ofs
= 0;
4424 if (max_data_bytes
< 32) {
4425 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4428 for (i
= 0; i
< num_streams
; i
++) {
4429 unsigned int next_offset
;
4431 smb_ucs2_t
*namebuf
;
4433 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4434 streams
[i
].name
, &namelen
) ||
4437 return NT_STATUS_INVALID_PARAMETER
;
4441 * name_buf is now null-terminated, we need to marshall as not
4448 * We cannot overflow ...
4450 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4451 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4453 TALLOC_FREE(namebuf
);
4454 return STATUS_BUFFER_OVERFLOW
;
4457 SIVAL(data
, ofs
+4, namelen
);
4458 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4459 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4460 memcpy(data
+ofs
+24, namebuf
, namelen
);
4461 TALLOC_FREE(namebuf
);
4463 next_offset
= ofs
+ 24 + namelen
;
4465 if (i
== num_streams
-1) {
4466 SIVAL(data
, ofs
, 0);
4469 unsigned int align
= ndr_align_size(next_offset
, 8);
4471 if ((next_offset
+ align
) > max_data_bytes
) {
4472 DEBUG(10, ("refusing to overflow align "
4473 "reply at stream %u\n",
4475 TALLOC_FREE(namebuf
);
4476 return STATUS_BUFFER_OVERFLOW
;
4479 memset(data
+next_offset
, 0, align
);
4480 next_offset
+= align
;
4482 SIVAL(data
, ofs
, next_offset
- ofs
);
4489 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4493 return NT_STATUS_OK
;
4496 /****************************************************************************
4497 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4498 ****************************************************************************/
4500 static void call_trans2qpipeinfo(connection_struct
*conn
,
4501 struct smb_request
*req
,
4502 unsigned int tran_call
,
4503 char **pparams
, int total_params
,
4504 char **ppdata
, int total_data
,
4505 unsigned int max_data_bytes
)
4507 char *params
= *pparams
;
4508 char *pdata
= *ppdata
;
4509 unsigned int data_size
= 0;
4510 unsigned int param_size
= 2;
4511 uint16_t info_level
;
4515 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4519 if (total_params
< 4) {
4520 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4524 fsp
= file_fsp(req
, SVAL(params
,0));
4525 if (!fsp_is_np(fsp
)) {
4526 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4530 info_level
= SVAL(params
,2);
4532 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4533 if (*pparams
== NULL
) {
4534 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4539 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4543 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4544 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4545 if (*ppdata
== NULL
) {
4546 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4551 switch (info_level
) {
4552 case SMB_FILE_STANDARD_INFORMATION
:
4554 SOFF_T(pdata
,0,4096LL);
4561 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4565 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4571 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4572 TALLOC_CTX
*mem_ctx
,
4573 uint16_t info_level
,
4575 struct smb_filename
*smb_fname
,
4576 bool delete_pending
,
4577 struct timespec write_time_ts
,
4578 struct ea_list
*ea_list
,
4579 int lock_data_count
,
4582 unsigned int max_data_bytes
,
4583 size_t *fixed_portion
,
4585 unsigned int *pdata_size
)
4587 char *pdata
= *ppdata
;
4588 char *dstart
, *dend
;
4589 unsigned int data_size
;
4590 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4591 time_t create_time
, mtime
, atime
, c_time
;
4592 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4599 uint64_t file_size
= 0;
4601 uint64_t allocation_size
= 0;
4602 uint64_t file_index
= 0;
4603 uint32_t access_mask
= 0;
4606 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4607 return NT_STATUS_INVALID_LEVEL
;
4610 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4611 smb_fname_str_dbg(smb_fname
),
4613 info_level
, max_data_bytes
));
4615 mode
= dos_mode(conn
, smb_fname
);
4616 nlink
= psbuf
->st_ex_nlink
;
4618 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4622 if ((nlink
> 0) && delete_pending
) {
4626 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4627 return NT_STATUS_INVALID_PARAMETER
;
4630 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4631 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4632 if (*ppdata
== NULL
) {
4633 return NT_STATUS_NO_MEMORY
;
4637 dend
= dstart
+ data_size
- 1;
4639 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4640 update_stat_ex_mtime(psbuf
, write_time_ts
);
4643 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4644 mtime_ts
= psbuf
->st_ex_mtime
;
4645 atime_ts
= psbuf
->st_ex_atime
;
4646 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4648 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4649 dos_filetime_timespec(&create_time_ts
);
4650 dos_filetime_timespec(&mtime_ts
);
4651 dos_filetime_timespec(&atime_ts
);
4652 dos_filetime_timespec(&ctime_ts
);
4655 create_time
= convert_timespec_to_time_t(create_time_ts
);
4656 mtime
= convert_timespec_to_time_t(mtime_ts
);
4657 atime
= convert_timespec_to_time_t(atime_ts
);
4658 c_time
= convert_timespec_to_time_t(ctime_ts
);
4660 p
= strrchr_m(smb_fname
->base_name
,'/');
4662 base_name
= smb_fname
->base_name
;
4666 /* NT expects the name to be in an exact form of the *full*
4667 filename. See the trans2 torture test */
4668 if (ISDOT(base_name
)) {
4669 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4671 return NT_STATUS_NO_MEMORY
;
4674 dos_fname
= talloc_asprintf(mem_ctx
,
4676 smb_fname
->base_name
);
4678 return NT_STATUS_NO_MEMORY
;
4680 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4681 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4682 smb_fname
->stream_name
);
4684 return NT_STATUS_NO_MEMORY
;
4688 string_replace(dos_fname
, '/', '\\');
4691 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4694 /* Do we have this path open ? */
4696 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4697 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4698 if (fsp1
&& fsp1
->initial_allocation_size
) {
4699 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4703 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4704 file_size
= get_file_size_stat(psbuf
);
4708 pos
= fsp
->fh
->position_information
;
4712 access_mask
= fsp
->access_mask
;
4714 /* GENERIC_EXECUTE mapping from Windows */
4715 access_mask
= 0x12019F;
4718 /* This should be an index number - looks like
4721 I think this causes us to fail the IFSKIT
4722 BasicFileInformationTest. -tpot */
4723 file_index
= get_FileIndex(conn
, psbuf
);
4727 switch (info_level
) {
4728 case SMB_INFO_STANDARD
:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4731 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4732 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4733 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4734 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4735 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4736 SSVAL(pdata
,l1_attrFile
,mode
);
4739 case SMB_INFO_QUERY_EA_SIZE
:
4741 unsigned int ea_size
=
4742 estimate_ea_size(conn
, fsp
,
4744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4746 srv_put_dos_date2(pdata
,0,create_time
);
4747 srv_put_dos_date2(pdata
,4,atime
);
4748 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4749 SIVAL(pdata
,12,(uint32_t)file_size
);
4750 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4751 SSVAL(pdata
,20,mode
);
4752 SIVAL(pdata
,22,ea_size
);
4756 case SMB_INFO_IS_NAME_VALID
:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4759 /* os/2 needs this ? really ?*/
4760 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4762 /* This is only reached for qpathinfo */
4766 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4768 size_t total_ea_len
= 0;
4769 struct ea_list
*ea_file_list
= NULL
;
4770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4773 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4775 &total_ea_len
, &ea_file_list
);
4776 if (!NT_STATUS_IS_OK(status
)) {
4780 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4782 if (!ea_list
|| (total_ea_len
> data_size
)) {
4784 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4788 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4792 case SMB_INFO_QUERY_ALL_EAS
:
4794 /* We have data_size bytes to put EA's into. */
4795 size_t total_ea_len
= 0;
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4798 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4800 &total_ea_len
, &ea_list
);
4801 if (!NT_STATUS_IS_OK(status
)) {
4805 if (!ea_list
|| (total_ea_len
> data_size
)) {
4807 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4811 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4815 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4817 /* This is FileFullEaInformation - 0xF which maps to
4818 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4820 /* We have data_size bytes to put EA's into. */
4821 size_t total_ea_len
= 0;
4822 struct ea_list
*ea_file_list
= NULL
;
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4826 /*TODO: add filtering and index handling */
4829 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4831 &total_ea_len
, &ea_file_list
);
4832 if (!NT_STATUS_IS_OK(status
)) {
4835 if (!ea_file_list
) {
4836 return NT_STATUS_NO_EAS_ON_FILE
;
4839 status
= fill_ea_chained_buffer(mem_ctx
,
4843 conn
, ea_file_list
);
4844 if (!NT_STATUS_IS_OK(status
)) {
4850 case SMB_FILE_BASIC_INFORMATION
:
4851 case SMB_QUERY_FILE_BASIC_INFO
:
4853 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4855 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4861 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4862 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4863 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4864 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4865 SIVAL(pdata
,32,mode
);
4867 DEBUG(5,("SMB_QFBI - "));
4868 DEBUG(5,("create: %s ", ctime(&create_time
)));
4869 DEBUG(5,("access: %s ", ctime(&atime
)));
4870 DEBUG(5,("write: %s ", ctime(&mtime
)));
4871 DEBUG(5,("change: %s ", ctime(&c_time
)));
4872 DEBUG(5,("mode: %x\n", mode
));
4873 *fixed_portion
= data_size
;
4876 case SMB_FILE_STANDARD_INFORMATION
:
4877 case SMB_QUERY_FILE_STANDARD_INFO
:
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4881 SOFF_T(pdata
,0,allocation_size
);
4882 SOFF_T(pdata
,8,file_size
);
4883 SIVAL(pdata
,16,nlink
);
4884 SCVAL(pdata
,20,delete_pending
?1:0);
4885 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4886 SSVAL(pdata
,22,0); /* Padding. */
4887 *fixed_portion
= 24;
4890 case SMB_FILE_EA_INFORMATION
:
4891 case SMB_QUERY_FILE_EA_INFO
:
4893 unsigned int ea_size
=
4894 estimate_ea_size(conn
, fsp
, smb_fname
);
4895 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4898 SIVAL(pdata
,0,ea_size
);
4902 /* Get the 8.3 name - used if NT SMB was negotiated. */
4903 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4904 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4906 char mangled_name
[13];
4907 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4908 if (!name_to_8_3(base_name
,mangled_name
,
4909 True
,conn
->params
)) {
4910 return NT_STATUS_NO_MEMORY
;
4912 status
= srvstr_push(dstart
, flags2
,
4913 pdata
+4, mangled_name
,
4914 PTR_DIFF(dend
, pdata
+4),
4916 if (!NT_STATUS_IS_OK(status
)) {
4919 data_size
= 4 + len
;
4925 case SMB_QUERY_FILE_NAME_INFO
:
4928 this must be *exactly* right for ACLs on mapped drives to work
4930 status
= srvstr_push(dstart
, flags2
,
4932 PTR_DIFF(dend
, pdata
+4),
4934 if (!NT_STATUS_IS_OK(status
)) {
4937 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4938 data_size
= 4 + len
;
4943 case SMB_FILE_ALLOCATION_INFORMATION
:
4944 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4945 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4947 SOFF_T(pdata
,0,allocation_size
);
4950 case SMB_FILE_END_OF_FILE_INFORMATION
:
4951 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4954 SOFF_T(pdata
,0,file_size
);
4957 case SMB_QUERY_FILE_ALL_INFO
:
4958 case SMB_FILE_ALL_INFORMATION
:
4960 unsigned int ea_size
=
4961 estimate_ea_size(conn
, fsp
, smb_fname
);
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4963 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4964 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4965 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4966 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4967 SIVAL(pdata
,32,mode
);
4968 SIVAL(pdata
,36,0); /* padding. */
4970 SOFF_T(pdata
,0,allocation_size
);
4971 SOFF_T(pdata
,8,file_size
);
4972 SIVAL(pdata
,16,nlink
);
4973 SCVAL(pdata
,20,delete_pending
);
4974 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4977 SIVAL(pdata
,0,ea_size
);
4978 pdata
+= 4; /* EA info */
4979 status
= srvstr_push(dstart
, flags2
,
4981 PTR_DIFF(dend
, pdata
+4),
4983 if (!NT_STATUS_IS_OK(status
)) {
4988 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4989 *fixed_portion
= 10;
4993 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4995 unsigned int ea_size
=
4996 estimate_ea_size(conn
, fsp
, smb_fname
);
4997 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4998 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4999 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5000 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5001 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5002 SIVAL(pdata
, 0x20, mode
);
5003 SIVAL(pdata
, 0x24, 0); /* padding. */
5004 SBVAL(pdata
, 0x28, allocation_size
);
5005 SBVAL(pdata
, 0x30, file_size
);
5006 SIVAL(pdata
, 0x38, nlink
);
5007 SCVAL(pdata
, 0x3C, delete_pending
);
5008 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5009 SSVAL(pdata
, 0x3E, 0); /* padding */
5010 SBVAL(pdata
, 0x40, file_index
);
5011 SIVAL(pdata
, 0x48, ea_size
);
5012 SIVAL(pdata
, 0x4C, access_mask
);
5013 SBVAL(pdata
, 0x50, pos
);
5014 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5015 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5019 status
= srvstr_push(dstart
, flags2
,
5021 PTR_DIFF(dend
, pdata
+4),
5023 if (!NT_STATUS_IS_OK(status
)) {
5028 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5029 *fixed_portion
= 104;
5032 case SMB_FILE_INTERNAL_INFORMATION
:
5034 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5035 SBVAL(pdata
, 0, file_index
);
5040 case SMB_FILE_ACCESS_INFORMATION
:
5041 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5042 SIVAL(pdata
, 0, access_mask
);
5047 case SMB_FILE_NAME_INFORMATION
:
5048 /* Pathname with leading '\'. */
5051 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5052 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5053 SIVAL(pdata
,0,byte_len
);
5054 data_size
= 4 + byte_len
;
5058 case SMB_FILE_DISPOSITION_INFORMATION
:
5059 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5061 SCVAL(pdata
,0,delete_pending
);
5065 case SMB_FILE_POSITION_INFORMATION
:
5066 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5068 SOFF_T(pdata
,0,pos
);
5072 case SMB_FILE_MODE_INFORMATION
:
5073 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5074 SIVAL(pdata
,0,mode
);
5079 case SMB_FILE_ALIGNMENT_INFORMATION
:
5080 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5081 SIVAL(pdata
,0,0); /* No alignment needed. */
5087 * NT4 server just returns "invalid query" to this - if we try
5088 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5091 /* The first statement above is false - verified using Thursby
5092 * client against NT4 -- gcolley.
5094 case SMB_QUERY_FILE_STREAM_INFO
:
5095 case SMB_FILE_STREAM_INFORMATION
: {
5096 unsigned int num_streams
= 0;
5097 struct stream_struct
*streams
= NULL
;
5099 DEBUG(10,("smbd_do_qfilepathinfo: "
5100 "SMB_FILE_STREAM_INFORMATION\n"));
5102 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5103 return NT_STATUS_INVALID_PARAMETER
;
5106 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5107 talloc_tos(), &num_streams
, &streams
);
5109 if (!NT_STATUS_IS_OK(status
)) {
5110 DEBUG(10, ("could not get stream info: %s\n",
5111 nt_errstr(status
)));
5115 status
= marshall_stream_info(num_streams
, streams
,
5116 pdata
, max_data_bytes
,
5119 if (!NT_STATUS_IS_OK(status
)) {
5120 DEBUG(10, ("marshall_stream_info failed: %s\n",
5121 nt_errstr(status
)));
5122 TALLOC_FREE(streams
);
5126 TALLOC_FREE(streams
);
5128 *fixed_portion
= 32;
5132 case SMB_QUERY_COMPRESSION_INFO
:
5133 case SMB_FILE_COMPRESSION_INFORMATION
:
5134 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5135 SOFF_T(pdata
,0,file_size
);
5136 SIVAL(pdata
,8,0); /* ??? */
5137 SIVAL(pdata
,12,0); /* ??? */
5139 *fixed_portion
= 16;
5142 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5143 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5144 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5145 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5146 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5147 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5148 SOFF_T(pdata
,32,allocation_size
);
5149 SOFF_T(pdata
,40,file_size
);
5150 SIVAL(pdata
,48,mode
);
5151 SIVAL(pdata
,52,0); /* ??? */
5153 *fixed_portion
= 56;
5156 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5158 SIVAL(pdata
,0,mode
);
5165 * CIFS UNIX Extensions.
5168 case SMB_QUERY_FILE_UNIX_BASIC
:
5170 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5171 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5173 DEBUG(4,("smbd_do_qfilepathinfo: "
5174 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5175 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5179 case SMB_QUERY_FILE_UNIX_INFO2
:
5181 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5182 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5186 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5188 for (i
=0; i
<100; i
++)
5189 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5195 case SMB_QUERY_FILE_UNIX_LINK
:
5198 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5201 return NT_STATUS_NO_MEMORY
;
5204 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5206 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5207 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5210 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5212 link_len
= SMB_VFS_READLINK(conn
,
5213 smb_fname
->base_name
,
5215 if (link_len
== -1) {
5216 return map_nt_error_from_unix(errno
);
5218 buffer
[link_len
] = 0;
5219 status
= srvstr_push(dstart
, flags2
,
5221 PTR_DIFF(dend
, pdata
),
5222 STR_TERMINATE
, &len
);
5223 if (!NT_STATUS_IS_OK(status
)) {
5227 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5232 #if defined(HAVE_POSIX_ACLS)
5233 case SMB_QUERY_POSIX_ACL
:
5235 SMB_ACL_T file_acl
= NULL
;
5236 SMB_ACL_T def_acl
= NULL
;
5237 uint16_t num_file_acls
= 0;
5238 uint16_t num_def_acls
= 0;
5240 if (fsp
&& fsp
->fh
->fd
!= -1) {
5241 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5245 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5246 smb_fname
->base_name
,
5247 SMB_ACL_TYPE_ACCESS
,
5251 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5252 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5253 "not implemented on "
5254 "filesystem containing %s\n",
5255 smb_fname
->base_name
));
5256 return NT_STATUS_NOT_IMPLEMENTED
;
5259 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5260 if (fsp
&& fsp
->is_directory
) {
5262 SMB_VFS_SYS_ACL_GET_FILE(
5264 fsp
->fsp_name
->base_name
,
5265 SMB_ACL_TYPE_DEFAULT
,
5269 SMB_VFS_SYS_ACL_GET_FILE(
5271 smb_fname
->base_name
,
5272 SMB_ACL_TYPE_DEFAULT
,
5275 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5278 num_file_acls
= count_acl_entries(conn
, file_acl
);
5279 num_def_acls
= count_acl_entries(conn
, def_acl
);
5281 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5282 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5284 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5285 SMB_POSIX_ACL_HEADER_SIZE
) ));
5287 TALLOC_FREE(file_acl
);
5290 TALLOC_FREE(def_acl
);
5292 return NT_STATUS_BUFFER_TOO_SMALL
;
5295 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5296 SSVAL(pdata
,2,num_file_acls
);
5297 SSVAL(pdata
,4,num_def_acls
);
5298 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5300 TALLOC_FREE(file_acl
);
5303 TALLOC_FREE(def_acl
);
5305 return NT_STATUS_INTERNAL_ERROR
;
5307 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5309 TALLOC_FREE(file_acl
);
5312 TALLOC_FREE(def_acl
);
5314 return NT_STATUS_INTERNAL_ERROR
;
5318 TALLOC_FREE(file_acl
);
5321 TALLOC_FREE(def_acl
);
5323 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5329 case SMB_QUERY_POSIX_LOCK
:
5334 enum brl_type lock_type
;
5336 /* We need an open file with a real fd for this. */
5337 if (!fsp
|| fsp
->fh
->fd
== -1) {
5338 return NT_STATUS_INVALID_LEVEL
;
5341 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5342 return NT_STATUS_INVALID_PARAMETER
;
5345 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5346 case POSIX_LOCK_TYPE_READ
:
5347 lock_type
= READ_LOCK
;
5349 case POSIX_LOCK_TYPE_WRITE
:
5350 lock_type
= WRITE_LOCK
;
5352 case POSIX_LOCK_TYPE_UNLOCK
:
5354 /* There's no point in asking for an unlock... */
5355 return NT_STATUS_INVALID_PARAMETER
;
5358 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5359 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5360 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5362 status
= query_lock(fsp
,
5369 if (ERROR_WAS_LOCK_DENIED(status
)) {
5370 /* Here we need to report who has it locked... */
5371 data_size
= POSIX_LOCK_DATA_SIZE
;
5373 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5374 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5375 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5376 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5377 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5379 } else if (NT_STATUS_IS_OK(status
)) {
5380 /* For success we just return a copy of what we sent
5381 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5382 data_size
= POSIX_LOCK_DATA_SIZE
;
5383 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5384 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5392 return NT_STATUS_INVALID_LEVEL
;
5395 *pdata_size
= data_size
;
5396 return NT_STATUS_OK
;
5399 /****************************************************************************
5400 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5401 file name or file id).
5402 ****************************************************************************/
5404 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5405 struct smb_request
*req
,
5406 unsigned int tran_call
,
5407 char **pparams
, int total_params
,
5408 char **ppdata
, int total_data
,
5409 unsigned int max_data_bytes
)
5411 char *params
= *pparams
;
5412 char *pdata
= *ppdata
;
5413 uint16_t info_level
;
5414 unsigned int data_size
= 0;
5415 unsigned int param_size
= 2;
5416 struct smb_filename
*smb_fname
= NULL
;
5417 bool delete_pending
= False
;
5418 struct timespec write_time_ts
;
5419 files_struct
*fsp
= NULL
;
5420 struct file_id fileid
;
5421 struct ea_list
*ea_list
= NULL
;
5422 int lock_data_count
= 0;
5423 char *lock_data
= NULL
;
5424 size_t fixed_portion
;
5425 NTSTATUS status
= NT_STATUS_OK
;
5428 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5432 ZERO_STRUCT(write_time_ts
);
5434 if (tran_call
== TRANSACT2_QFILEINFO
) {
5435 if (total_params
< 4) {
5436 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5441 call_trans2qpipeinfo(conn
, req
, tran_call
,
5442 pparams
, total_params
,
5448 fsp
= file_fsp(req
, SVAL(params
,0));
5449 info_level
= SVAL(params
,2);
5451 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5453 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5454 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5458 /* Initial check for valid fsp ptr. */
5459 if (!check_fsp_open(conn
, req
, fsp
)) {
5463 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5464 if (smb_fname
== NULL
) {
5465 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5469 if(fsp
->fake_file_handle
) {
5471 * This is actually for the QUOTA_FAKE_FILE --metze
5474 /* We know this name is ok, it's already passed the checks. */
5476 } else if(fsp
->fh
->fd
== -1) {
5478 * This is actually a QFILEINFO on a directory
5479 * handle (returned from an NT SMB). NT5.0 seems
5480 * to do this call. JRA.
5483 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5484 /* Always do lstat for UNIX calls. */
5485 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5486 DEBUG(3,("call_trans2qfilepathinfo: "
5487 "SMB_VFS_LSTAT of %s failed "
5489 smb_fname_str_dbg(smb_fname
),
5492 map_nt_error_from_unix(errno
));
5495 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5496 DEBUG(3,("call_trans2qfilepathinfo: "
5497 "SMB_VFS_STAT of %s failed (%s)\n",
5498 smb_fname_str_dbg(smb_fname
),
5501 map_nt_error_from_unix(errno
));
5505 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5506 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5509 * Original code - this is an open file.
5511 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5512 DEBUG(3, ("fstat of %s failed (%s)\n",
5513 fsp_fnum_dbg(fsp
), strerror(errno
)));
5515 map_nt_error_from_unix(errno
));
5518 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5519 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5525 uint32_t ucf_flags
= 0;
5528 if (total_params
< 7) {
5529 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5533 info_level
= SVAL(params
,0);
5535 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5537 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5538 if (!lp_unix_extensions()) {
5539 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5542 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5543 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5544 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5545 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5549 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5551 STR_TERMINATE
, &status
);
5552 if (!NT_STATUS_IS_OK(status
)) {
5553 reply_nterror(req
, status
);
5557 status
= filename_convert(req
,
5559 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5564 if (!NT_STATUS_IS_OK(status
)) {
5565 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5566 reply_botherror(req
,
5567 NT_STATUS_PATH_NOT_COVERED
,
5568 ERRSRV
, ERRbadpath
);
5571 reply_nterror(req
, status
);
5575 /* If this is a stream, check if there is a delete_pending. */
5576 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5577 && is_ntfs_stream_smb_fname(smb_fname
)) {
5578 struct smb_filename
*smb_fname_base
;
5580 /* Create an smb_filename with stream_name == NULL. */
5581 smb_fname_base
= synthetic_smb_fname(
5582 talloc_tos(), smb_fname
->base_name
,
5584 if (smb_fname_base
== NULL
) {
5585 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5589 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5590 /* Always do lstat for UNIX calls. */
5591 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5592 DEBUG(3,("call_trans2qfilepathinfo: "
5593 "SMB_VFS_LSTAT of %s failed "
5595 smb_fname_str_dbg(smb_fname_base
),
5597 TALLOC_FREE(smb_fname_base
);
5599 map_nt_error_from_unix(errno
));
5603 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5604 DEBUG(3,("call_trans2qfilepathinfo: "
5605 "fileinfo of %s failed "
5607 smb_fname_str_dbg(smb_fname_base
),
5609 TALLOC_FREE(smb_fname_base
);
5611 map_nt_error_from_unix(errno
));
5616 status
= file_name_hash(conn
,
5617 smb_fname_str_dbg(smb_fname_base
),
5619 if (!NT_STATUS_IS_OK(status
)) {
5620 TALLOC_FREE(smb_fname_base
);
5621 reply_nterror(req
, status
);
5625 fileid
= vfs_file_id_from_sbuf(conn
,
5626 &smb_fname_base
->st
);
5627 TALLOC_FREE(smb_fname_base
);
5628 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5629 if (delete_pending
) {
5630 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5635 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5636 /* Always do lstat for UNIX calls. */
5637 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5638 DEBUG(3,("call_trans2qfilepathinfo: "
5639 "SMB_VFS_LSTAT of %s failed (%s)\n",
5640 smb_fname_str_dbg(smb_fname
),
5643 map_nt_error_from_unix(errno
));
5648 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5649 DEBUG(3,("call_trans2qfilepathinfo: "
5650 "SMB_VFS_STAT of %s failed (%s)\n",
5651 smb_fname_str_dbg(smb_fname
),
5654 map_nt_error_from_unix(errno
));
5659 status
= file_name_hash(conn
,
5660 smb_fname_str_dbg(smb_fname
),
5662 if (!NT_STATUS_IS_OK(status
)) {
5663 reply_nterror(req
, status
);
5667 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5668 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5669 if (delete_pending
) {
5670 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5675 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5676 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5678 info_level
,tran_call
,total_data
));
5680 /* Pull out any data sent here before we realloc. */
5681 switch (info_level
) {
5682 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5684 /* Pull any EA list from the data portion. */
5687 if (total_data
< 4) {
5689 req
, NT_STATUS_INVALID_PARAMETER
);
5692 ea_size
= IVAL(pdata
,0);
5694 if (total_data
> 0 && ea_size
!= total_data
) {
5695 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5696 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5698 req
, NT_STATUS_INVALID_PARAMETER
);
5702 if (!lp_ea_support(SNUM(conn
))) {
5703 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5707 /* Pull out the list of names. */
5708 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5711 req
, NT_STATUS_INVALID_PARAMETER
);
5717 case SMB_QUERY_POSIX_LOCK
:
5719 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5720 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5724 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5726 req
, NT_STATUS_INVALID_PARAMETER
);
5730 /* Copy the lock range data. */
5731 lock_data
= (char *)talloc_memdup(
5732 req
, pdata
, total_data
);
5734 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5737 lock_data_count
= total_data
;
5743 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5744 if (*pparams
== NULL
) {
5745 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5752 * draft-leach-cifs-v1-spec-02.txt
5753 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5756 * The requested information is placed in the Data portion of the
5757 * transaction response. For the information levels greater than 0x100,
5758 * the transaction response has 1 parameter word which should be
5759 * ignored by the client.
5761 * However Windows only follows this rule for the IS_NAME_VALID call.
5763 switch (info_level
) {
5764 case SMB_INFO_IS_NAME_VALID
:
5769 if ((info_level
& 0xFF00) == 0xFF00) {
5771 * We use levels that start with 0xFF00
5772 * internally to represent SMB2 specific levels
5774 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5778 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5780 delete_pending
, write_time_ts
,
5782 lock_data_count
, lock_data
,
5783 req
->flags2
, max_data_bytes
,
5785 ppdata
, &data_size
);
5786 if (!NT_STATUS_IS_OK(status
)) {
5787 reply_nterror(req
, status
);
5790 if (fixed_portion
> max_data_bytes
) {
5791 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5795 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5801 /****************************************************************************
5802 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5804 ****************************************************************************/
5806 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5807 connection_struct
*conn
,
5808 struct smb_request
*req
,
5809 bool overwrite_if_exists
,
5810 const struct smb_filename
*smb_fname_old
,
5811 struct smb_filename
*smb_fname_new
)
5813 NTSTATUS status
= NT_STATUS_OK
;
5815 /* source must already exist. */
5816 if (!VALID_STAT(smb_fname_old
->st
)) {
5817 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5820 if (VALID_STAT(smb_fname_new
->st
)) {
5821 if (overwrite_if_exists
) {
5822 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5823 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5825 status
= unlink_internals(conn
,
5827 FILE_ATTRIBUTE_NORMAL
,
5830 if (!NT_STATUS_IS_OK(status
)) {
5834 /* Disallow if newname already exists. */
5835 return NT_STATUS_OBJECT_NAME_COLLISION
;
5839 /* No links from a directory. */
5840 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5841 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5844 /* Setting a hardlink to/from a stream isn't currently supported. */
5845 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5846 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5847 return NT_STATUS_INVALID_PARAMETER
;
5850 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5851 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5853 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5854 smb_fname_new
->base_name
) != 0) {
5855 status
= map_nt_error_from_unix(errno
);
5856 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5857 nt_errstr(status
), smb_fname_old
->base_name
,
5858 smb_fname_new
->base_name
));
5863 /****************************************************************************
5864 Deal with setting the time from any of the setfilepathinfo functions.
5865 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5866 calling this function.
5867 ****************************************************************************/
5869 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5871 const struct smb_filename
*smb_fname
,
5872 struct smb_file_time
*ft
,
5873 bool setting_write_time
)
5875 struct smb_filename smb_fname_base
;
5877 FILE_NOTIFY_CHANGE_LAST_ACCESS
5878 |FILE_NOTIFY_CHANGE_LAST_WRITE
5879 |FILE_NOTIFY_CHANGE_CREATION
;
5881 if (!VALID_STAT(smb_fname
->st
)) {
5882 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5885 /* get some defaults (no modifications) if any info is zero or -1. */
5886 if (null_timespec(ft
->create_time
)) {
5887 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5890 if (null_timespec(ft
->atime
)) {
5891 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5894 if (null_timespec(ft
->mtime
)) {
5895 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5898 if (!setting_write_time
) {
5899 /* ft->mtime comes from change time, not write time. */
5900 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5903 /* Ensure the resolution is the correct for
5904 * what we can store on this filesystem. */
5906 round_timespec(conn
->ts_res
, &ft
->create_time
);
5907 round_timespec(conn
->ts_res
, &ft
->ctime
);
5908 round_timespec(conn
->ts_res
, &ft
->atime
);
5909 round_timespec(conn
->ts_res
, &ft
->mtime
);
5911 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5912 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5913 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5914 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5915 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5916 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5917 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5918 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5920 if (setting_write_time
) {
5922 * This was a Windows setfileinfo on an open file.
5923 * NT does this a lot. We also need to
5924 * set the time here, as it can be read by
5925 * FindFirst/FindNext and with the patch for bug #2045
5926 * in smbd/fileio.c it ensures that this timestamp is
5927 * kept sticky even after a write. We save the request
5928 * away and will set it on file close and after a write. JRA.
5931 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5932 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5935 if (fsp
->base_fsp
) {
5936 set_sticky_write_time_fsp(fsp
->base_fsp
,
5939 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5942 set_sticky_write_time_path(
5943 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5948 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5950 /* Always call ntimes on the base, even if a stream was passed in. */
5951 smb_fname_base
= *smb_fname
;
5952 smb_fname_base
.stream_name
= NULL
;
5954 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5955 return map_nt_error_from_unix(errno
);
5958 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5959 smb_fname
->base_name
);
5960 return NT_STATUS_OK
;
5963 /****************************************************************************
5964 Deal with setting the dosmode from any of the setfilepathinfo functions.
5965 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5966 done before calling this function.
5967 ****************************************************************************/
5969 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5970 const struct smb_filename
*smb_fname
,
5973 struct smb_filename
*smb_fname_base
;
5976 if (!VALID_STAT(smb_fname
->st
)) {
5977 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5980 /* Always operate on the base_name, even if a stream was passed in. */
5981 smb_fname_base
= synthetic_smb_fname(
5982 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5983 if (smb_fname_base
== NULL
) {
5984 return NT_STATUS_NO_MEMORY
;
5988 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5989 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5991 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5995 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5997 /* check the mode isn't different, before changing it */
5998 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5999 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6000 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6001 (unsigned int)dosmode
));
6003 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6005 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6007 smb_fname_str_dbg(smb_fname_base
),
6009 status
= map_nt_error_from_unix(errno
);
6013 status
= NT_STATUS_OK
;
6015 TALLOC_FREE(smb_fname_base
);
6019 /****************************************************************************
6020 Deal with setting the size from any of the setfilepathinfo functions.
6021 ****************************************************************************/
6023 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6024 struct smb_request
*req
,
6026 const struct smb_filename
*smb_fname
,
6027 const SMB_STRUCT_STAT
*psbuf
,
6029 bool fail_after_createfile
)
6031 NTSTATUS status
= NT_STATUS_OK
;
6032 struct smb_filename
*smb_fname_tmp
= NULL
;
6033 files_struct
*new_fsp
= NULL
;
6035 if (!VALID_STAT(*psbuf
)) {
6036 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6039 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6041 if (size
== get_file_size_stat(psbuf
)) {
6042 return NT_STATUS_OK
;
6045 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6046 smb_fname_str_dbg(smb_fname
), (double)size
));
6048 if (fsp
&& fsp
->fh
->fd
!= -1) {
6049 /* Handle based call. */
6050 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6051 return NT_STATUS_ACCESS_DENIED
;
6054 if (vfs_set_filelen(fsp
, size
) == -1) {
6055 return map_nt_error_from_unix(errno
);
6057 trigger_write_time_update_immediate(fsp
);
6058 return NT_STATUS_OK
;
6061 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6062 if (smb_fname_tmp
== NULL
) {
6063 return NT_STATUS_NO_MEMORY
;
6066 smb_fname_tmp
->st
= *psbuf
;
6068 status
= SMB_VFS_CREATE_FILE(
6071 0, /* root_dir_fid */
6072 smb_fname_tmp
, /* fname */
6073 FILE_WRITE_DATA
, /* access_mask */
6074 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6076 FILE_OPEN
, /* create_disposition*/
6077 0, /* create_options */
6078 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6079 0, /* oplock_request */
6081 0, /* allocation_size */
6082 0, /* private_flags */
6085 &new_fsp
, /* result */
6087 NULL
, NULL
); /* create context */
6089 TALLOC_FREE(smb_fname_tmp
);
6091 if (!NT_STATUS_IS_OK(status
)) {
6092 /* NB. We check for open_was_deferred in the caller. */
6096 /* See RAW-SFILEINFO-END-OF-FILE */
6097 if (fail_after_createfile
) {
6098 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6099 return NT_STATUS_INVALID_LEVEL
;
6102 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6103 status
= map_nt_error_from_unix(errno
);
6104 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6108 trigger_write_time_update_immediate(new_fsp
);
6109 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6110 return NT_STATUS_OK
;
6113 /****************************************************************************
6114 Deal with SMB_INFO_SET_EA.
6115 ****************************************************************************/
6117 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6121 const struct smb_filename
*smb_fname
)
6123 struct ea_list
*ea_list
= NULL
;
6124 TALLOC_CTX
*ctx
= NULL
;
6125 NTSTATUS status
= NT_STATUS_OK
;
6127 if (total_data
< 10) {
6129 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6130 length. They seem to have no effect. Bug #3212. JRA */
6132 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6133 /* We're done. We only get EA info in this call. */
6134 return NT_STATUS_OK
;
6137 return NT_STATUS_INVALID_PARAMETER
;
6140 if (IVAL(pdata
,0) > total_data
) {
6141 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6142 IVAL(pdata
,0), (unsigned int)total_data
));
6143 return NT_STATUS_INVALID_PARAMETER
;
6147 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6149 return NT_STATUS_INVALID_PARAMETER
;
6152 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6157 /****************************************************************************
6158 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6159 ****************************************************************************/
6161 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6166 struct ea_list
*ea_list
= NULL
;
6170 return NT_STATUS_INVALID_HANDLE
;
6173 if (!lp_ea_support(SNUM(conn
))) {
6174 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6175 "EA's not supported.\n",
6176 (unsigned int)total_data
));
6177 return NT_STATUS_EAS_NOT_SUPPORTED
;
6180 if (total_data
< 10) {
6181 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6183 (unsigned int)total_data
));
6184 return NT_STATUS_INVALID_PARAMETER
;
6187 ea_list
= read_nttrans_ea_list(talloc_tos(),
6192 return NT_STATUS_INVALID_PARAMETER
;
6195 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6197 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6198 smb_fname_str_dbg(fsp
->fsp_name
),
6199 nt_errstr(status
) ));
6205 /****************************************************************************
6206 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6207 ****************************************************************************/
6209 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6213 struct smb_filename
*smb_fname
)
6215 NTSTATUS status
= NT_STATUS_OK
;
6216 bool delete_on_close
;
6217 uint32_t dosmode
= 0;
6219 if (total_data
< 1) {
6220 return NT_STATUS_INVALID_PARAMETER
;
6224 return NT_STATUS_INVALID_HANDLE
;
6227 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6228 dosmode
= dos_mode(conn
, smb_fname
);
6230 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6231 "delete_on_close = %u\n",
6232 smb_fname_str_dbg(smb_fname
),
6233 (unsigned int)dosmode
,
6234 (unsigned int)delete_on_close
));
6236 if (delete_on_close
) {
6237 status
= can_set_delete_on_close(fsp
, dosmode
);
6238 if (!NT_STATUS_IS_OK(status
)) {
6243 /* The set is across all open files on this dev/inode pair. */
6244 if (!set_delete_on_close(fsp
, delete_on_close
,
6245 conn
->session_info
->security_token
,
6246 conn
->session_info
->unix_token
)) {
6247 return NT_STATUS_ACCESS_DENIED
;
6249 return NT_STATUS_OK
;
6252 /****************************************************************************
6253 Deal with SMB_FILE_POSITION_INFORMATION.
6254 ****************************************************************************/
6256 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6261 uint64_t position_information
;
6263 if (total_data
< 8) {
6264 return NT_STATUS_INVALID_PARAMETER
;
6268 /* Ignore on pathname based set. */
6269 return NT_STATUS_OK
;
6272 position_information
= (uint64_t)IVAL(pdata
,0);
6273 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6275 DEBUG(10,("smb_file_position_information: Set file position "
6276 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6277 (double)position_information
));
6278 fsp
->fh
->position_information
= position_information
;
6279 return NT_STATUS_OK
;
6282 /****************************************************************************
6283 Deal with SMB_FILE_MODE_INFORMATION.
6284 ****************************************************************************/
6286 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6292 if (total_data
< 4) {
6293 return NT_STATUS_INVALID_PARAMETER
;
6295 mode
= IVAL(pdata
,0);
6296 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6297 return NT_STATUS_INVALID_PARAMETER
;
6299 return NT_STATUS_OK
;
6302 /****************************************************************************
6303 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6304 ****************************************************************************/
6306 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6307 struct smb_request
*req
,
6310 const struct smb_filename
*smb_fname
)
6312 char *link_target
= NULL
;
6313 const char *newname
= smb_fname
->base_name
;
6314 TALLOC_CTX
*ctx
= talloc_tos();
6316 /* Set a symbolic link. */
6317 /* Don't allow this if follow links is false. */
6319 if (total_data
== 0) {
6320 return NT_STATUS_INVALID_PARAMETER
;
6323 if (!lp_follow_symlinks(SNUM(conn
))) {
6324 return NT_STATUS_ACCESS_DENIED
;
6327 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6328 total_data
, STR_TERMINATE
);
6331 return NT_STATUS_INVALID_PARAMETER
;
6334 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6335 newname
, link_target
));
6337 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6338 return map_nt_error_from_unix(errno
);
6341 return NT_STATUS_OK
;
6344 /****************************************************************************
6345 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6346 ****************************************************************************/
6348 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6349 struct smb_request
*req
,
6350 const char *pdata
, int total_data
,
6351 struct smb_filename
*smb_fname_new
)
6353 char *oldname
= NULL
;
6354 struct smb_filename
*smb_fname_old
= NULL
;
6355 TALLOC_CTX
*ctx
= talloc_tos();
6356 NTSTATUS status
= NT_STATUS_OK
;
6358 /* Set a hard link. */
6359 if (total_data
== 0) {
6360 return NT_STATUS_INVALID_PARAMETER
;
6363 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6364 total_data
, STR_TERMINATE
, &status
);
6365 if (!NT_STATUS_IS_OK(status
)) {
6369 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6370 smb_fname_str_dbg(smb_fname_new
), oldname
));
6372 status
= filename_convert(ctx
,
6374 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6379 if (!NT_STATUS_IS_OK(status
)) {
6383 return hardlink_internals(ctx
, conn
, req
, false,
6384 smb_fname_old
, smb_fname_new
);
6387 /****************************************************************************
6388 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6389 ****************************************************************************/
6391 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6392 struct smb_request
*req
,
6396 struct smb_filename
*smb_fname_src
)
6400 char *newname
= NULL
;
6401 struct smb_filename
*smb_fname_dst
= NULL
;
6402 NTSTATUS status
= NT_STATUS_OK
;
6403 TALLOC_CTX
*ctx
= talloc_tos();
6406 return NT_STATUS_INVALID_HANDLE
;
6409 if (total_data
< 20) {
6410 return NT_STATUS_INVALID_PARAMETER
;
6413 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6414 len
= IVAL(pdata
,16);
6416 if (len
> (total_data
- 20) || (len
== 0)) {
6417 return NT_STATUS_INVALID_PARAMETER
;
6420 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6421 &pdata
[20], len
, STR_TERMINATE
,
6423 if (!NT_STATUS_IS_OK(status
)) {
6427 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6430 status
= filename_convert(ctx
,
6432 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6437 if (!NT_STATUS_IS_OK(status
)) {
6441 if (fsp
->base_fsp
) {
6442 /* newname must be a stream name. */
6443 if (newname
[0] != ':') {
6444 return NT_STATUS_NOT_SUPPORTED
;
6447 /* Create an smb_fname to call rename_internals_fsp() with. */
6448 smb_fname_dst
= synthetic_smb_fname(
6449 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6451 if (smb_fname_dst
== NULL
) {
6452 status
= NT_STATUS_NO_MEMORY
;
6457 * Set the original last component, since
6458 * rename_internals_fsp() requires it.
6460 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6462 if (smb_fname_dst
->original_lcomp
== NULL
) {
6463 status
= NT_STATUS_NO_MEMORY
;
6469 DEBUG(10,("smb2_file_rename_information: "
6470 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6471 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6472 smb_fname_str_dbg(smb_fname_dst
)));
6473 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6474 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6478 TALLOC_FREE(smb_fname_dst
);
6482 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6483 struct smb_request
*req
,
6487 struct smb_filename
*smb_fname_src
)
6491 char *newname
= NULL
;
6492 struct smb_filename
*smb_fname_dst
= NULL
;
6493 NTSTATUS status
= NT_STATUS_OK
;
6494 TALLOC_CTX
*ctx
= talloc_tos();
6497 return NT_STATUS_INVALID_HANDLE
;
6500 if (total_data
< 20) {
6501 return NT_STATUS_INVALID_PARAMETER
;
6504 overwrite
= (CVAL(pdata
,0) ? true : false);
6505 len
= IVAL(pdata
,16);
6507 if (len
> (total_data
- 20) || (len
== 0)) {
6508 return NT_STATUS_INVALID_PARAMETER
;
6511 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6512 &pdata
[20], len
, STR_TERMINATE
,
6514 if (!NT_STATUS_IS_OK(status
)) {
6518 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6521 status
= filename_convert(ctx
,
6523 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6528 if (!NT_STATUS_IS_OK(status
)) {
6532 if (fsp
->base_fsp
) {
6533 /* No stream names. */
6534 return NT_STATUS_NOT_SUPPORTED
;
6537 DEBUG(10,("smb_file_link_information: "
6538 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6539 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6540 smb_fname_str_dbg(smb_fname_dst
)));
6541 status
= hardlink_internals(ctx
,
6548 TALLOC_FREE(smb_fname_dst
);
6552 /****************************************************************************
6553 Deal with SMB_FILE_RENAME_INFORMATION.
6554 ****************************************************************************/
6556 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6557 struct smb_request
*req
,
6561 struct smb_filename
*smb_fname_src
)
6566 char *newname
= NULL
;
6567 struct smb_filename
*smb_fname_dst
= NULL
;
6568 bool dest_has_wcard
= False
;
6569 NTSTATUS status
= NT_STATUS_OK
;
6571 TALLOC_CTX
*ctx
= talloc_tos();
6573 if (total_data
< 13) {
6574 return NT_STATUS_INVALID_PARAMETER
;
6577 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6578 root_fid
= IVAL(pdata
,4);
6579 len
= IVAL(pdata
,8);
6581 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6582 return NT_STATUS_INVALID_PARAMETER
;
6585 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6588 if (!NT_STATUS_IS_OK(status
)) {
6592 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6595 status
= resolve_dfspath_wcard(ctx
, conn
,
6596 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6599 !conn
->sconn
->using_smb2
,
6602 if (!NT_STATUS_IS_OK(status
)) {
6606 /* Check the new name has no '/' characters. */
6607 if (strchr_m(newname
, '/')) {
6608 return NT_STATUS_NOT_SUPPORTED
;
6611 if (fsp
&& fsp
->base_fsp
) {
6612 /* newname must be a stream name. */
6613 if (newname
[0] != ':') {
6614 return NT_STATUS_NOT_SUPPORTED
;
6617 /* Create an smb_fname to call rename_internals_fsp() with. */
6618 smb_fname_dst
= synthetic_smb_fname(
6619 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6621 if (smb_fname_dst
== NULL
) {
6622 status
= NT_STATUS_NO_MEMORY
;
6627 * Set the original last component, since
6628 * rename_internals_fsp() requires it.
6630 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6632 if (smb_fname_dst
->original_lcomp
== NULL
) {
6633 status
= NT_STATUS_NO_MEMORY
;
6639 * Build up an smb_fname_dst based on the filename passed in.
6640 * We basically just strip off the last component, and put on
6641 * the newname instead.
6643 char *base_name
= NULL
;
6645 /* newname must *not* be a stream name. */
6646 if (newname
[0] == ':') {
6647 return NT_STATUS_NOT_SUPPORTED
;
6651 * Strip off the last component (filename) of the path passed
6654 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6656 return NT_STATUS_NO_MEMORY
;
6658 p
= strrchr_m(base_name
, '/');
6662 base_name
= talloc_strdup(ctx
, "");
6664 return NT_STATUS_NO_MEMORY
;
6667 /* Append the new name. */
6668 base_name
= talloc_asprintf_append(base_name
,
6672 return NT_STATUS_NO_MEMORY
;
6675 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6678 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6681 /* If an error we expect this to be
6682 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6684 if (!NT_STATUS_IS_OK(status
)) {
6685 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6689 /* Create an smb_fname to call rename_internals_fsp() */
6690 smb_fname_dst
= synthetic_smb_fname(
6691 ctx
, base_name
, NULL
, NULL
);
6692 if (smb_fname_dst
== NULL
) {
6693 status
= NT_STATUS_NO_MEMORY
;
6700 DEBUG(10,("smb_file_rename_information: "
6701 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6702 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6703 smb_fname_str_dbg(smb_fname_dst
)));
6704 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6707 DEBUG(10,("smb_file_rename_information: "
6708 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6709 smb_fname_str_dbg(smb_fname_src
),
6710 smb_fname_str_dbg(smb_fname_dst
)));
6711 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6712 smb_fname_dst
, 0, overwrite
, false,
6714 FILE_WRITE_ATTRIBUTES
);
6717 TALLOC_FREE(smb_fname_dst
);
6721 /****************************************************************************
6722 Deal with SMB_SET_POSIX_ACL.
6723 ****************************************************************************/
6725 #if defined(HAVE_POSIX_ACLS)
6726 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6730 const struct smb_filename
*smb_fname
)
6732 uint16_t posix_acl_version
;
6733 uint16_t num_file_acls
;
6734 uint16_t num_def_acls
;
6735 bool valid_file_acls
= True
;
6736 bool valid_def_acls
= True
;
6738 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6739 return NT_STATUS_INVALID_PARAMETER
;
6741 posix_acl_version
= SVAL(pdata
,0);
6742 num_file_acls
= SVAL(pdata
,2);
6743 num_def_acls
= SVAL(pdata
,4);
6745 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6746 valid_file_acls
= False
;
6750 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6751 valid_def_acls
= False
;
6755 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6756 return NT_STATUS_INVALID_PARAMETER
;
6759 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6760 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6761 return NT_STATUS_INVALID_PARAMETER
;
6764 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6765 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6766 (unsigned int)num_file_acls
,
6767 (unsigned int)num_def_acls
));
6769 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6770 smb_fname
->base_name
, num_file_acls
,
6771 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6772 return map_nt_error_from_unix(errno
);
6775 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6776 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6777 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6778 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6779 return map_nt_error_from_unix(errno
);
6781 return NT_STATUS_OK
;
6785 /****************************************************************************
6786 Deal with SMB_SET_POSIX_LOCK.
6787 ****************************************************************************/
6789 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6790 struct smb_request
*req
,
6798 bool blocking_lock
= False
;
6799 enum brl_type lock_type
;
6801 NTSTATUS status
= NT_STATUS_OK
;
6803 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6804 return NT_STATUS_INVALID_HANDLE
;
6807 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6808 return NT_STATUS_INVALID_PARAMETER
;
6811 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6812 case POSIX_LOCK_TYPE_READ
:
6813 lock_type
= READ_LOCK
;
6815 case POSIX_LOCK_TYPE_WRITE
:
6816 /* Return the right POSIX-mappable error code for files opened read-only. */
6817 if (!fsp
->can_write
) {
6818 return NT_STATUS_INVALID_HANDLE
;
6820 lock_type
= WRITE_LOCK
;
6822 case POSIX_LOCK_TYPE_UNLOCK
:
6823 lock_type
= UNLOCK_LOCK
;
6826 return NT_STATUS_INVALID_PARAMETER
;
6829 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6830 blocking_lock
= False
;
6831 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6832 blocking_lock
= True
;
6834 return NT_STATUS_INVALID_PARAMETER
;
6837 if (!lp_blocking_locks(SNUM(conn
))) {
6838 blocking_lock
= False
;
6841 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6842 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6843 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6844 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6845 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6847 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6848 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6850 (unsigned int)lock_type
,
6851 (unsigned long long)smblctx
,
6855 if (lock_type
== UNLOCK_LOCK
) {
6856 status
= do_unlock(req
->sconn
->msg_ctx
,
6863 uint64_t block_smblctx
;
6865 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6876 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6878 * A blocking lock was requested. Package up
6879 * this smb into a queued request and push it
6880 * onto the blocking lock queue.
6882 if(push_blocking_lock_request(br_lck
,
6885 -1, /* infinite timeout. */
6893 TALLOC_FREE(br_lck
);
6897 TALLOC_FREE(br_lck
);
6903 /****************************************************************************
6904 Deal with SMB_SET_FILE_BASIC_INFO.
6905 ****************************************************************************/
6907 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6911 const struct smb_filename
*smb_fname
)
6913 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6914 struct smb_file_time ft
;
6915 uint32_t dosmode
= 0;
6916 NTSTATUS status
= NT_STATUS_OK
;
6920 if (total_data
< 36) {
6921 return NT_STATUS_INVALID_PARAMETER
;
6924 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6925 if (!NT_STATUS_IS_OK(status
)) {
6929 /* Set the attributes */
6930 dosmode
= IVAL(pdata
,32);
6931 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6932 if (!NT_STATUS_IS_OK(status
)) {
6937 ft
.create_time
= interpret_long_date(pdata
);
6940 ft
.atime
= interpret_long_date(pdata
+8);
6943 ft
.mtime
= interpret_long_date(pdata
+16);
6946 ft
.ctime
= interpret_long_date(pdata
+24);
6948 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6949 smb_fname_str_dbg(smb_fname
)));
6951 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6955 /****************************************************************************
6956 Deal with SMB_INFO_STANDARD.
6957 ****************************************************************************/
6959 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6963 const struct smb_filename
*smb_fname
)
6966 struct smb_file_time ft
;
6970 if (total_data
< 12) {
6971 return NT_STATUS_INVALID_PARAMETER
;
6975 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6977 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6979 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6981 DEBUG(10,("smb_set_info_standard: file %s\n",
6982 smb_fname_str_dbg(smb_fname
)));
6984 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6985 if (!NT_STATUS_IS_OK(status
)) {
6989 return smb_set_file_time(conn
,
6996 /****************************************************************************
6997 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6998 ****************************************************************************/
7000 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7001 struct smb_request
*req
,
7005 struct smb_filename
*smb_fname
)
7007 uint64_t allocation_size
= 0;
7008 NTSTATUS status
= NT_STATUS_OK
;
7009 files_struct
*new_fsp
= NULL
;
7011 if (!VALID_STAT(smb_fname
->st
)) {
7012 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7015 if (total_data
< 8) {
7016 return NT_STATUS_INVALID_PARAMETER
;
7019 allocation_size
= (uint64_t)IVAL(pdata
,0);
7020 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7021 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7022 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7023 (double)allocation_size
));
7025 if (allocation_size
) {
7026 allocation_size
= smb_roundup(conn
, allocation_size
);
7029 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7030 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7031 (double)allocation_size
));
7033 if (fsp
&& fsp
->fh
->fd
!= -1) {
7034 /* Open file handle. */
7035 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7036 return NT_STATUS_ACCESS_DENIED
;
7039 /* Only change if needed. */
7040 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7041 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7042 return map_nt_error_from_unix(errno
);
7045 /* But always update the time. */
7047 * This is equivalent to a write. Ensure it's seen immediately
7048 * if there are no pending writes.
7050 trigger_write_time_update_immediate(fsp
);
7051 return NT_STATUS_OK
;
7054 /* Pathname or stat or directory file. */
7055 status
= SMB_VFS_CREATE_FILE(
7058 0, /* root_dir_fid */
7059 smb_fname
, /* fname */
7060 FILE_WRITE_DATA
, /* access_mask */
7061 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7063 FILE_OPEN
, /* create_disposition*/
7064 0, /* create_options */
7065 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7066 0, /* oplock_request */
7068 0, /* allocation_size */
7069 0, /* private_flags */
7072 &new_fsp
, /* result */
7074 NULL
, NULL
); /* create context */
7076 if (!NT_STATUS_IS_OK(status
)) {
7077 /* NB. We check for open_was_deferred in the caller. */
7081 /* Only change if needed. */
7082 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7083 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7084 status
= map_nt_error_from_unix(errno
);
7085 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7090 /* Changing the allocation size should set the last mod time. */
7092 * This is equivalent to a write. Ensure it's seen immediately
7093 * if there are no pending writes.
7095 trigger_write_time_update_immediate(new_fsp
);
7096 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7097 return NT_STATUS_OK
;
7100 /****************************************************************************
7101 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7102 ****************************************************************************/
7104 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7105 struct smb_request
*req
,
7109 const struct smb_filename
*smb_fname
,
7110 bool fail_after_createfile
)
7114 if (total_data
< 8) {
7115 return NT_STATUS_INVALID_PARAMETER
;
7118 size
= IVAL(pdata
,0);
7119 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7120 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7121 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7124 return smb_set_file_size(conn
, req
,
7129 fail_after_createfile
);
7132 /****************************************************************************
7133 Allow a UNIX info mknod.
7134 ****************************************************************************/
7136 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7139 const struct smb_filename
*smb_fname
)
7141 uint32_t file_type
= IVAL(pdata
,56);
7142 #if defined(HAVE_MAKEDEV)
7143 uint32_t dev_major
= IVAL(pdata
,60);
7144 uint32_t dev_minor
= IVAL(pdata
,68);
7146 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7147 uint32_t raw_unixmode
= IVAL(pdata
,84);
7151 if (total_data
< 100) {
7152 return NT_STATUS_INVALID_PARAMETER
;
7155 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7156 PERM_NEW_FILE
, &unixmode
);
7157 if (!NT_STATUS_IS_OK(status
)) {
7161 #if defined(HAVE_MAKEDEV)
7162 dev
= makedev(dev_major
, dev_minor
);
7165 switch (file_type
) {
7166 #if defined(S_IFIFO)
7167 case UNIX_TYPE_FIFO
:
7168 unixmode
|= S_IFIFO
;
7171 #if defined(S_IFSOCK)
7172 case UNIX_TYPE_SOCKET
:
7173 unixmode
|= S_IFSOCK
;
7176 #if defined(S_IFCHR)
7177 case UNIX_TYPE_CHARDEV
:
7178 unixmode
|= S_IFCHR
;
7181 #if defined(S_IFBLK)
7182 case UNIX_TYPE_BLKDEV
:
7183 unixmode
|= S_IFBLK
;
7187 return NT_STATUS_INVALID_PARAMETER
;
7190 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7191 "%.0f mode 0%o for file %s\n", (double)dev
,
7192 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7194 /* Ok - do the mknod. */
7195 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7196 return map_nt_error_from_unix(errno
);
7199 /* If any of the other "set" calls fail we
7200 * don't want to end up with a half-constructed mknod.
7203 if (lp_inherit_permissions(SNUM(conn
))) {
7205 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7207 return NT_STATUS_NO_MEMORY
;
7209 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7211 TALLOC_FREE(parent
);
7214 return NT_STATUS_OK
;
7217 /****************************************************************************
7218 Deal with SMB_SET_FILE_UNIX_BASIC.
7219 ****************************************************************************/
7221 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7222 struct smb_request
*req
,
7226 const struct smb_filename
*smb_fname
)
7228 struct smb_file_time ft
;
7229 uint32_t raw_unixmode
;
7232 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7233 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7234 NTSTATUS status
= NT_STATUS_OK
;
7235 bool delete_on_fail
= False
;
7236 enum perm_type ptype
;
7237 files_struct
*all_fsps
= NULL
;
7238 bool modify_mtime
= true;
7240 struct smb_filename
*smb_fname_tmp
= NULL
;
7241 SMB_STRUCT_STAT sbuf
;
7245 if (total_data
< 100) {
7246 return NT_STATUS_INVALID_PARAMETER
;
7249 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7250 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7251 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7252 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7255 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7256 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7257 set_owner
= (uid_t
)IVAL(pdata
,40);
7258 set_grp
= (gid_t
)IVAL(pdata
,48);
7259 raw_unixmode
= IVAL(pdata
,84);
7261 if (VALID_STAT(smb_fname
->st
)) {
7262 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7263 ptype
= PERM_EXISTING_DIR
;
7265 ptype
= PERM_EXISTING_FILE
;
7268 ptype
= PERM_NEW_FILE
;
7271 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7273 if (!NT_STATUS_IS_OK(status
)) {
7277 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7278 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7279 smb_fname_str_dbg(smb_fname
), (double)size
,
7280 (unsigned int)set_owner
, (unsigned int)set_grp
,
7281 (int)raw_unixmode
));
7283 sbuf
= smb_fname
->st
;
7285 if (!VALID_STAT(sbuf
)) {
7287 * The only valid use of this is to create character and block
7288 * devices, and named pipes. This is deprecated (IMHO) and
7289 * a new info level should be used for mknod. JRA.
7292 status
= smb_unix_mknod(conn
,
7296 if (!NT_STATUS_IS_OK(status
)) {
7300 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7301 if (smb_fname_tmp
== NULL
) {
7302 return NT_STATUS_NO_MEMORY
;
7305 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7306 status
= map_nt_error_from_unix(errno
);
7307 TALLOC_FREE(smb_fname_tmp
);
7308 SMB_VFS_UNLINK(conn
, smb_fname
);
7312 sbuf
= smb_fname_tmp
->st
;
7313 smb_fname
= smb_fname_tmp
;
7315 /* Ensure we don't try and change anything else. */
7316 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7317 size
= get_file_size_stat(&sbuf
);
7318 ft
.atime
= sbuf
.st_ex_atime
;
7319 ft
.mtime
= sbuf
.st_ex_mtime
;
7321 * We continue here as we might want to change the
7324 delete_on_fail
= True
;
7328 /* Horrible backwards compatibility hack as an old server bug
7329 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7333 size
= get_file_size_stat(&sbuf
);
7338 * Deal with the UNIX specific mode set.
7341 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7344 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7345 "setting mode 0%o for file %s\n",
7346 (unsigned int)unixmode
,
7347 smb_fname_str_dbg(smb_fname
)));
7348 if (fsp
&& fsp
->fh
->fd
!= -1) {
7349 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7351 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7354 return map_nt_error_from_unix(errno
);
7359 * Deal with the UNIX specific uid set.
7362 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7363 (sbuf
.st_ex_uid
!= set_owner
)) {
7366 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7367 "changing owner %u for path %s\n",
7368 (unsigned int)set_owner
,
7369 smb_fname_str_dbg(smb_fname
)));
7371 if (fsp
&& fsp
->fh
->fd
!= -1) {
7372 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7375 * UNIX extensions calls must always operate
7378 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7379 set_owner
, (gid_t
)-1);
7383 status
= map_nt_error_from_unix(errno
);
7384 if (delete_on_fail
) {
7385 SMB_VFS_UNLINK(conn
, smb_fname
);
7392 * Deal with the UNIX specific gid set.
7395 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7396 (sbuf
.st_ex_gid
!= set_grp
)) {
7399 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7400 "changing group %u for file %s\n",
7401 (unsigned int)set_owner
,
7402 smb_fname_str_dbg(smb_fname
)));
7403 if (fsp
&& fsp
->fh
->fd
!= -1) {
7404 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7407 * UNIX extensions calls must always operate
7410 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7414 status
= map_nt_error_from_unix(errno
);
7415 if (delete_on_fail
) {
7416 SMB_VFS_UNLINK(conn
, smb_fname
);
7422 /* Deal with any size changes. */
7424 status
= smb_set_file_size(conn
, req
,
7430 if (!NT_STATUS_IS_OK(status
)) {
7434 /* Deal with any time changes. */
7435 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7436 /* No change, don't cancel anything. */
7440 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7441 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7442 all_fsps
= file_find_di_next(all_fsps
)) {
7444 * We're setting the time explicitly for UNIX.
7445 * Cancel any pending changes over all handles.
7447 all_fsps
->update_write_time_on_close
= false;
7448 TALLOC_FREE(all_fsps
->update_write_time_event
);
7452 * Override the "setting_write_time"
7453 * parameter here as it almost does what
7454 * we need. Just remember if we modified
7455 * mtime and send the notify ourselves.
7457 if (null_timespec(ft
.mtime
)) {
7458 modify_mtime
= false;
7461 status
= smb_set_file_time(conn
,
7467 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7468 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7473 /****************************************************************************
7474 Deal with SMB_SET_FILE_UNIX_INFO2.
7475 ****************************************************************************/
7477 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7478 struct smb_request
*req
,
7482 const struct smb_filename
*smb_fname
)
7485 uint32_t smb_fflags
;
7488 if (total_data
< 116) {
7489 return NT_STATUS_INVALID_PARAMETER
;
7492 /* Start by setting all the fields that are common between UNIX_BASIC
7495 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7497 if (!NT_STATUS_IS_OK(status
)) {
7501 smb_fflags
= IVAL(pdata
, 108);
7502 smb_fmask
= IVAL(pdata
, 112);
7504 /* NB: We should only attempt to alter the file flags if the client
7505 * sends a non-zero mask.
7507 if (smb_fmask
!= 0) {
7508 int stat_fflags
= 0;
7510 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7511 smb_fmask
, &stat_fflags
)) {
7512 /* Client asked to alter a flag we don't understand. */
7513 return NT_STATUS_INVALID_PARAMETER
;
7516 if (fsp
&& fsp
->fh
->fd
!= -1) {
7517 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7518 return NT_STATUS_NOT_SUPPORTED
;
7520 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7521 stat_fflags
) != 0) {
7522 return map_nt_error_from_unix(errno
);
7527 /* XXX: need to add support for changing the create_time here. You
7528 * can do this for paths on Darwin with setattrlist(2). The right way
7529 * to hook this up is probably by extending the VFS utimes interface.
7532 return NT_STATUS_OK
;
7535 /****************************************************************************
7536 Create a directory with POSIX semantics.
7537 ****************************************************************************/
7539 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7540 struct smb_request
*req
,
7543 struct smb_filename
*smb_fname
,
7544 int *pdata_return_size
)
7546 NTSTATUS status
= NT_STATUS_OK
;
7547 uint32_t raw_unixmode
= 0;
7548 uint32_t mod_unixmode
= 0;
7549 mode_t unixmode
= (mode_t
)0;
7550 files_struct
*fsp
= NULL
;
7551 uint16_t info_level_return
= 0;
7553 char *pdata
= *ppdata
;
7555 if (total_data
< 18) {
7556 return NT_STATUS_INVALID_PARAMETER
;
7559 raw_unixmode
= IVAL(pdata
,8);
7560 /* Next 4 bytes are not yet defined. */
7562 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7563 PERM_NEW_DIR
, &unixmode
);
7564 if (!NT_STATUS_IS_OK(status
)) {
7568 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7570 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7571 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7573 status
= SMB_VFS_CREATE_FILE(
7576 0, /* root_dir_fid */
7577 smb_fname
, /* fname */
7578 FILE_READ_ATTRIBUTES
, /* access_mask */
7579 FILE_SHARE_NONE
, /* share_access */
7580 FILE_CREATE
, /* create_disposition*/
7581 FILE_DIRECTORY_FILE
, /* create_options */
7582 mod_unixmode
, /* file_attributes */
7583 0, /* oplock_request */
7585 0, /* allocation_size */
7586 0, /* private_flags */
7591 NULL
, NULL
); /* create context */
7593 if (NT_STATUS_IS_OK(status
)) {
7594 close_file(req
, fsp
, NORMAL_CLOSE
);
7597 info_level_return
= SVAL(pdata
,16);
7599 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7600 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7601 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7602 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7604 *pdata_return_size
= 12;
7607 /* Realloc the data size */
7608 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7609 if (*ppdata
== NULL
) {
7610 *pdata_return_size
= 0;
7611 return NT_STATUS_NO_MEMORY
;
7615 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7616 SSVAL(pdata
,2,0); /* No fnum. */
7617 SIVAL(pdata
,4,info
); /* Was directory created. */
7619 switch (info_level_return
) {
7620 case SMB_QUERY_FILE_UNIX_BASIC
:
7621 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7622 SSVAL(pdata
,10,0); /* Padding. */
7623 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7626 case SMB_QUERY_FILE_UNIX_INFO2
:
7627 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7628 SSVAL(pdata
,10,0); /* Padding. */
7629 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7633 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7634 SSVAL(pdata
,10,0); /* Padding. */
7641 /****************************************************************************
7642 Open/Create a file with POSIX semantics.
7643 ****************************************************************************/
7645 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7646 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7648 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7649 struct smb_request
*req
,
7652 struct smb_filename
*smb_fname
,
7653 int *pdata_return_size
)
7655 bool extended_oplock_granted
= False
;
7656 char *pdata
= *ppdata
;
7658 uint32_t wire_open_mode
= 0;
7659 uint32_t raw_unixmode
= 0;
7660 uint32_t mod_unixmode
= 0;
7661 uint32_t create_disp
= 0;
7662 uint32_t access_mask
= 0;
7663 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7664 NTSTATUS status
= NT_STATUS_OK
;
7665 mode_t unixmode
= (mode_t
)0;
7666 files_struct
*fsp
= NULL
;
7667 int oplock_request
= 0;
7669 uint16_t info_level_return
= 0;
7671 if (total_data
< 18) {
7672 return NT_STATUS_INVALID_PARAMETER
;
7675 flags
= IVAL(pdata
,0);
7676 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7677 if (oplock_request
) {
7678 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7681 wire_open_mode
= IVAL(pdata
,4);
7683 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7684 return smb_posix_mkdir(conn
, req
,
7691 switch (wire_open_mode
& SMB_ACCMODE
) {
7693 access_mask
= SMB_O_RDONLY_MAPPING
;
7696 access_mask
= SMB_O_WRONLY_MAPPING
;
7699 access_mask
= (SMB_O_RDONLY_MAPPING
|
7700 SMB_O_WRONLY_MAPPING
);
7703 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7704 (unsigned int)wire_open_mode
));
7705 return NT_STATUS_INVALID_PARAMETER
;
7708 wire_open_mode
&= ~SMB_ACCMODE
;
7710 /* First take care of O_CREAT|O_EXCL interactions. */
7711 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7712 case (SMB_O_CREAT
| SMB_O_EXCL
):
7713 /* File exists fail. File not exist create. */
7714 create_disp
= FILE_CREATE
;
7717 /* File exists open. File not exist create. */
7718 create_disp
= FILE_OPEN_IF
;
7721 /* O_EXCL on its own without O_CREAT is undefined.
7722 We deliberately ignore it as some versions of
7723 Linux CIFSFS can send a bare O_EXCL on the
7724 wire which other filesystems in the kernel
7725 ignore. See bug 9519 for details. */
7730 /* File exists open. File not exist fail. */
7731 create_disp
= FILE_OPEN
;
7734 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7735 (unsigned int)wire_open_mode
));
7736 return NT_STATUS_INVALID_PARAMETER
;
7739 /* Next factor in the effects of O_TRUNC. */
7740 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7742 if (wire_open_mode
& SMB_O_TRUNC
) {
7743 switch (create_disp
) {
7745 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7746 /* Leave create_disp alone as
7747 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7749 /* File exists fail. File not exist create. */
7752 /* SMB_O_CREAT | SMB_O_TRUNC */
7753 /* File exists overwrite. File not exist create. */
7754 create_disp
= FILE_OVERWRITE_IF
;
7758 /* File exists overwrite. File not exist fail. */
7759 create_disp
= FILE_OVERWRITE
;
7762 /* Cannot get here. */
7763 smb_panic("smb_posix_open: logic error");
7764 return NT_STATUS_INVALID_PARAMETER
;
7768 raw_unixmode
= IVAL(pdata
,8);
7769 /* Next 4 bytes are not yet defined. */
7771 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7772 (VALID_STAT(smb_fname
->st
) ?
7773 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7776 if (!NT_STATUS_IS_OK(status
)) {
7780 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7782 if (wire_open_mode
& SMB_O_SYNC
) {
7783 create_options
|= FILE_WRITE_THROUGH
;
7785 if (wire_open_mode
& SMB_O_APPEND
) {
7786 access_mask
|= FILE_APPEND_DATA
;
7788 if (wire_open_mode
& SMB_O_DIRECT
) {
7789 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7792 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7793 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7794 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7795 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7797 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7798 create_options
|= FILE_DIRECTORY_FILE
;
7801 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7802 smb_fname_str_dbg(smb_fname
),
7803 (unsigned int)wire_open_mode
,
7804 (unsigned int)unixmode
));
7806 status
= SMB_VFS_CREATE_FILE(
7809 0, /* root_dir_fid */
7810 smb_fname
, /* fname */
7811 access_mask
, /* access_mask */
7812 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7814 create_disp
, /* create_disposition*/
7815 create_options
, /* create_options */
7816 mod_unixmode
, /* file_attributes */
7817 oplock_request
, /* oplock_request */
7819 0, /* allocation_size */
7820 0, /* private_flags */
7825 NULL
, NULL
); /* create context */
7827 if (!NT_STATUS_IS_OK(status
)) {
7831 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7832 extended_oplock_granted
= True
;
7835 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7836 extended_oplock_granted
= True
;
7839 info_level_return
= SVAL(pdata
,16);
7841 /* Allocate the correct return size. */
7843 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7844 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7845 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7846 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7848 *pdata_return_size
= 12;
7851 /* Realloc the data size */
7852 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7853 if (*ppdata
== NULL
) {
7854 close_file(req
, fsp
, ERROR_CLOSE
);
7855 *pdata_return_size
= 0;
7856 return NT_STATUS_NO_MEMORY
;
7860 if (extended_oplock_granted
) {
7861 if (flags
& REQUEST_BATCH_OPLOCK
) {
7862 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7864 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7866 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7867 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7869 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7872 SSVAL(pdata
,2,fsp
->fnum
);
7873 SIVAL(pdata
,4,info
); /* Was file created etc. */
7875 switch (info_level_return
) {
7876 case SMB_QUERY_FILE_UNIX_BASIC
:
7877 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7878 SSVAL(pdata
,10,0); /* padding. */
7879 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7882 case SMB_QUERY_FILE_UNIX_INFO2
:
7883 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7884 SSVAL(pdata
,10,0); /* padding. */
7885 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7889 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7890 SSVAL(pdata
,10,0); /* padding. */
7893 return NT_STATUS_OK
;
7896 /****************************************************************************
7897 Delete a file with POSIX semantics.
7898 ****************************************************************************/
7900 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7901 struct smb_request
*req
,
7904 struct smb_filename
*smb_fname
)
7906 NTSTATUS status
= NT_STATUS_OK
;
7907 files_struct
*fsp
= NULL
;
7911 int create_options
= 0;
7913 struct share_mode_lock
*lck
= NULL
;
7915 if (total_data
< 2) {
7916 return NT_STATUS_INVALID_PARAMETER
;
7919 flags
= SVAL(pdata
,0);
7921 if (!VALID_STAT(smb_fname
->st
)) {
7922 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7925 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7926 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7927 return NT_STATUS_NOT_A_DIRECTORY
;
7930 DEBUG(10,("smb_posix_unlink: %s %s\n",
7931 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7932 smb_fname_str_dbg(smb_fname
)));
7934 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7935 create_options
|= FILE_DIRECTORY_FILE
;
7938 status
= SMB_VFS_CREATE_FILE(
7941 0, /* root_dir_fid */
7942 smb_fname
, /* fname */
7943 DELETE_ACCESS
, /* access_mask */
7944 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7946 FILE_OPEN
, /* create_disposition*/
7947 create_options
, /* create_options */
7948 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7949 0, /* oplock_request */
7951 0, /* allocation_size */
7952 0, /* private_flags */
7957 NULL
, NULL
); /* create context */
7959 if (!NT_STATUS_IS_OK(status
)) {
7964 * Don't lie to client. If we can't really delete due to
7965 * non-POSIX opens return SHARING_VIOLATION.
7968 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7970 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7971 "lock for file %s\n", fsp_str_dbg(fsp
)));
7972 close_file(req
, fsp
, NORMAL_CLOSE
);
7973 return NT_STATUS_INVALID_PARAMETER
;
7977 * See if others still have the file open. If this is the case, then
7978 * don't delete. If all opens are POSIX delete we can set the delete
7979 * on close disposition.
7981 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7982 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7983 if (is_valid_share_mode_entry(e
)) {
7984 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7987 if (share_mode_stale_pid(lck
->data
, i
)) {
7990 /* Fail with sharing violation. */
7992 close_file(req
, fsp
, NORMAL_CLOSE
);
7993 return NT_STATUS_SHARING_VIOLATION
;
7998 * Set the delete on close.
8000 status
= smb_set_file_disposition_info(conn
,
8008 if (!NT_STATUS_IS_OK(status
)) {
8009 close_file(req
, fsp
, NORMAL_CLOSE
);
8012 return close_file(req
, fsp
, NORMAL_CLOSE
);
8015 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8016 struct smb_request
*req
,
8017 TALLOC_CTX
*mem_ctx
,
8018 uint16_t info_level
,
8020 struct smb_filename
*smb_fname
,
8021 char **ppdata
, int total_data
,
8024 char *pdata
= *ppdata
;
8025 NTSTATUS status
= NT_STATUS_OK
;
8026 int data_return_size
= 0;
8030 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8031 return NT_STATUS_INVALID_LEVEL
;
8034 if (!CAN_WRITE(conn
)) {
8035 /* Allow POSIX opens. The open path will deny
8036 * any non-readonly opens. */
8037 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8038 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8042 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8043 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8045 info_level
, total_data
));
8047 switch (info_level
) {
8049 case SMB_INFO_STANDARD
:
8051 status
= smb_set_info_standard(conn
,
8059 case SMB_INFO_SET_EA
:
8061 status
= smb_info_set_ea(conn
,
8069 case SMB_SET_FILE_BASIC_INFO
:
8070 case SMB_FILE_BASIC_INFORMATION
:
8072 status
= smb_set_file_basic_info(conn
,
8080 case SMB_FILE_ALLOCATION_INFORMATION
:
8081 case SMB_SET_FILE_ALLOCATION_INFO
:
8083 status
= smb_set_file_allocation_info(conn
, req
,
8091 case SMB_FILE_END_OF_FILE_INFORMATION
:
8092 case SMB_SET_FILE_END_OF_FILE_INFO
:
8095 * XP/Win7 both fail after the createfile with
8096 * SMB_SET_FILE_END_OF_FILE_INFO but not
8097 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8098 * The level is known here, so pass it down
8102 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8104 status
= smb_set_file_end_of_file_info(conn
, req
,
8113 case SMB_FILE_DISPOSITION_INFORMATION
:
8114 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8117 /* JRA - We used to just ignore this on a path ?
8118 * Shouldn't this be invalid level on a pathname
8121 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8122 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8125 status
= smb_set_file_disposition_info(conn
,
8133 case SMB_FILE_POSITION_INFORMATION
:
8135 status
= smb_file_position_information(conn
,
8142 case SMB_FILE_FULL_EA_INFORMATION
:
8144 status
= smb_set_file_full_ea_info(conn
,
8151 /* From tridge Samba4 :
8152 * MODE_INFORMATION in setfileinfo (I have no
8153 * idea what "mode information" on a file is - it takes a value of 0,
8154 * 2, 4 or 6. What could it be?).
8157 case SMB_FILE_MODE_INFORMATION
:
8159 status
= smb_file_mode_information(conn
,
8166 * CIFS UNIX extensions.
8169 case SMB_SET_FILE_UNIX_BASIC
:
8171 status
= smb_set_file_unix_basic(conn
, req
,
8179 case SMB_SET_FILE_UNIX_INFO2
:
8181 status
= smb_set_file_unix_info2(conn
, req
,
8189 case SMB_SET_FILE_UNIX_LINK
:
8192 /* We must have a pathname for this. */
8193 return NT_STATUS_INVALID_LEVEL
;
8195 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8196 total_data
, smb_fname
);
8200 case SMB_SET_FILE_UNIX_HLINK
:
8203 /* We must have a pathname for this. */
8204 return NT_STATUS_INVALID_LEVEL
;
8206 status
= smb_set_file_unix_hlink(conn
, req
,
8212 case SMB_FILE_RENAME_INFORMATION
:
8214 status
= smb_file_rename_information(conn
, req
,
8220 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8222 /* SMB2 rename information. */
8223 status
= smb2_file_rename_information(conn
, req
,
8229 case SMB_FILE_LINK_INFORMATION
:
8231 status
= smb_file_link_information(conn
, req
,
8237 #if defined(HAVE_POSIX_ACLS)
8238 case SMB_SET_POSIX_ACL
:
8240 status
= smb_set_posix_acl(conn
,
8249 case SMB_SET_POSIX_LOCK
:
8252 return NT_STATUS_INVALID_LEVEL
;
8254 status
= smb_set_posix_lock(conn
, req
,
8255 pdata
, total_data
, fsp
);
8259 case SMB_POSIX_PATH_OPEN
:
8262 /* We must have a pathname for this. */
8263 return NT_STATUS_INVALID_LEVEL
;
8266 status
= smb_posix_open(conn
, req
,
8274 case SMB_POSIX_PATH_UNLINK
:
8277 /* We must have a pathname for this. */
8278 return NT_STATUS_INVALID_LEVEL
;
8281 status
= smb_posix_unlink(conn
, req
,
8289 return NT_STATUS_INVALID_LEVEL
;
8292 if (!NT_STATUS_IS_OK(status
)) {
8296 *ret_data_size
= data_return_size
;
8297 return NT_STATUS_OK
;
8300 /****************************************************************************
8301 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8302 ****************************************************************************/
8304 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8305 struct smb_request
*req
,
8306 unsigned int tran_call
,
8307 char **pparams
, int total_params
,
8308 char **ppdata
, int total_data
,
8309 unsigned int max_data_bytes
)
8311 char *params
= *pparams
;
8312 char *pdata
= *ppdata
;
8313 uint16_t info_level
;
8314 struct smb_filename
*smb_fname
= NULL
;
8315 files_struct
*fsp
= NULL
;
8316 NTSTATUS status
= NT_STATUS_OK
;
8317 int data_return_size
= 0;
8320 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8324 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8325 if (total_params
< 4) {
8326 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8330 fsp
= file_fsp(req
, SVAL(params
,0));
8331 /* Basic check for non-null fsp. */
8332 if (!check_fsp_open(conn
, req
, fsp
)) {
8335 info_level
= SVAL(params
,2);
8337 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8338 if (smb_fname
== NULL
) {
8339 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8343 if(fsp
->fh
->fd
== -1) {
8345 * This is actually a SETFILEINFO on a directory
8346 * handle (returned from an NT SMB). NT5.0 seems
8347 * to do this call. JRA.
8349 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8350 /* Always do lstat for UNIX calls. */
8351 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8352 DEBUG(3,("call_trans2setfilepathinfo: "
8353 "SMB_VFS_LSTAT of %s failed "
8355 smb_fname_str_dbg(smb_fname
),
8357 reply_nterror(req
, map_nt_error_from_unix(errno
));
8361 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8362 DEBUG(3,("call_trans2setfilepathinfo: "
8363 "fileinfo of %s failed (%s)\n",
8364 smb_fname_str_dbg(smb_fname
),
8366 reply_nterror(req
, map_nt_error_from_unix(errno
));
8370 } else if (fsp
->print_file
) {
8372 * Doing a DELETE_ON_CLOSE should cancel a print job.
8374 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8375 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8377 DEBUG(3,("call_trans2setfilepathinfo: "
8378 "Cancelling print job (%s)\n",
8382 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8388 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8393 * Original code - this is an open file.
8395 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8396 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8397 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8399 reply_nterror(req
, map_nt_error_from_unix(errno
));
8405 uint32_t ucf_flags
= 0;
8408 if (total_params
< 7) {
8409 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8413 info_level
= SVAL(params
,0);
8414 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8415 total_params
- 6, STR_TERMINATE
,
8417 if (!NT_STATUS_IS_OK(status
)) {
8418 reply_nterror(req
, status
);
8422 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8423 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8424 info_level
== SMB_FILE_RENAME_INFORMATION
||
8425 info_level
== SMB_POSIX_PATH_UNLINK
) {
8426 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8429 status
= filename_convert(req
, conn
,
8430 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8435 if (!NT_STATUS_IS_OK(status
)) {
8436 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8437 reply_botherror(req
,
8438 NT_STATUS_PATH_NOT_COVERED
,
8439 ERRSRV
, ERRbadpath
);
8442 reply_nterror(req
, status
);
8446 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8448 * For CIFS UNIX extensions the target name may not exist.
8451 /* Always do lstat for UNIX calls. */
8452 SMB_VFS_LSTAT(conn
, smb_fname
);
8454 } else if (!VALID_STAT(smb_fname
->st
) &&
8455 SMB_VFS_STAT(conn
, smb_fname
)) {
8456 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8458 smb_fname_str_dbg(smb_fname
),
8460 reply_nterror(req
, map_nt_error_from_unix(errno
));
8465 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8466 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8468 info_level
,total_data
));
8470 /* Realloc the parameter size */
8471 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8472 if (*pparams
== NULL
) {
8473 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8480 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8486 if (!NT_STATUS_IS_OK(status
)) {
8487 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8488 /* We have re-scheduled this call. */
8491 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8492 /* We have re-scheduled this call. */
8495 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8496 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8497 ERRSRV
, ERRbadpath
);
8500 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8501 reply_openerror(req
, status
);
8506 * Invalid EA name needs to return 2 param bytes,
8507 * not a zero-length error packet.
8509 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8510 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8513 reply_nterror(req
, status
);
8518 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8524 /****************************************************************************
8525 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8526 ****************************************************************************/
8528 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8529 char **pparams
, int total_params
,
8530 char **ppdata
, int total_data
,
8531 unsigned int max_data_bytes
)
8533 struct smb_filename
*smb_dname
= NULL
;
8534 char *params
= *pparams
;
8535 char *pdata
= *ppdata
;
8536 char *directory
= NULL
;
8537 NTSTATUS status
= NT_STATUS_OK
;
8538 struct ea_list
*ea_list
= NULL
;
8539 TALLOC_CTX
*ctx
= talloc_tos();
8541 if (!CAN_WRITE(conn
)) {
8542 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8546 if (total_params
< 5) {
8547 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8551 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8552 total_params
- 4, STR_TERMINATE
,
8554 if (!NT_STATUS_IS_OK(status
)) {
8555 reply_nterror(req
, status
);
8559 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8561 status
= filename_convert(ctx
,
8563 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8569 if (!NT_STATUS_IS_OK(status
)) {
8570 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8571 reply_botherror(req
,
8572 NT_STATUS_PATH_NOT_COVERED
,
8573 ERRSRV
, ERRbadpath
);
8576 reply_nterror(req
, status
);
8581 * OS/2 workplace shell seems to send SET_EA requests of "null"
8582 * length (4 bytes containing IVAL 4).
8583 * They seem to have no effect. Bug #3212. JRA.
8586 if (total_data
&& (total_data
!= 4)) {
8587 /* Any data in this call is an EA list. */
8588 if (total_data
< 10) {
8589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8593 if (IVAL(pdata
,0) > total_data
) {
8594 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8595 IVAL(pdata
,0), (unsigned int)total_data
));
8596 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8600 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8603 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8607 if (!lp_ea_support(SNUM(conn
))) {
8608 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8612 /* If total_data == 4 Windows doesn't care what values
8613 * are placed in that field, it just ignores them.
8614 * The System i QNTC IBM SMB client puts bad values here,
8615 * so ignore them. */
8617 status
= create_directory(conn
, req
, smb_dname
);
8619 if (!NT_STATUS_IS_OK(status
)) {
8620 reply_nterror(req
, status
);
8624 /* Try and set any given EA. */
8626 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8627 if (!NT_STATUS_IS_OK(status
)) {
8628 reply_nterror(req
, status
);
8633 /* Realloc the parameter and data sizes */
8634 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8635 if(*pparams
== NULL
) {
8636 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8643 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8646 TALLOC_FREE(smb_dname
);
8650 /****************************************************************************
8651 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8652 We don't actually do this - we just send a null response.
8653 ****************************************************************************/
8655 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8656 struct smb_request
*req
,
8657 char **pparams
, int total_params
,
8658 char **ppdata
, int total_data
,
8659 unsigned int max_data_bytes
)
8661 char *params
= *pparams
;
8662 uint16_t info_level
;
8664 if (total_params
< 6) {
8665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8669 info_level
= SVAL(params
,4);
8670 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8672 switch (info_level
) {
8677 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8681 /* Realloc the parameter and data sizes */
8682 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8683 if (*pparams
== NULL
) {
8684 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8689 SSVAL(params
,0,fnf_handle
);
8690 SSVAL(params
,2,0); /* No changes */
8691 SSVAL(params
,4,0); /* No EA errors */
8698 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8703 /****************************************************************************
8704 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8705 changes). Currently this does nothing.
8706 ****************************************************************************/
8708 static void call_trans2findnotifynext(connection_struct
*conn
,
8709 struct smb_request
*req
,
8710 char **pparams
, int total_params
,
8711 char **ppdata
, int total_data
,
8712 unsigned int max_data_bytes
)
8714 char *params
= *pparams
;
8716 DEBUG(3,("call_trans2findnotifynext\n"));
8718 /* Realloc the parameter and data sizes */
8719 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8720 if (*pparams
== NULL
) {
8721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8726 SSVAL(params
,0,0); /* No changes */
8727 SSVAL(params
,2,0); /* No EA errors */
8729 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8734 /****************************************************************************
8735 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8736 ****************************************************************************/
8738 static void call_trans2getdfsreferral(connection_struct
*conn
,
8739 struct smb_request
*req
,
8740 char **pparams
, int total_params
,
8741 char **ppdata
, int total_data
,
8742 unsigned int max_data_bytes
)
8744 char *params
= *pparams
;
8745 char *pathname
= NULL
;
8747 int max_referral_level
;
8748 NTSTATUS status
= NT_STATUS_OK
;
8749 TALLOC_CTX
*ctx
= talloc_tos();
8751 DEBUG(10,("call_trans2getdfsreferral\n"));
8753 if (total_params
< 3) {
8754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8758 max_referral_level
= SVAL(params
,0);
8760 if(!lp_host_msdfs()) {
8761 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8765 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8766 total_params
- 2, STR_TERMINATE
);
8768 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8771 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8772 ppdata
,&status
)) < 0) {
8773 reply_nterror(req
, status
);
8777 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8778 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8779 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8784 #define LMCAT_SPL 0x53
8785 #define LMFUNC_GETJOBID 0x60
8787 /****************************************************************************
8788 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8789 ****************************************************************************/
8791 static void call_trans2ioctl(connection_struct
*conn
,
8792 struct smb_request
*req
,
8793 char **pparams
, int total_params
,
8794 char **ppdata
, int total_data
,
8795 unsigned int max_data_bytes
)
8797 char *pdata
= *ppdata
;
8798 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8802 /* check for an invalid fid before proceeding */
8805 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8809 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8810 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8811 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8812 if (*ppdata
== NULL
) {
8813 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8818 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8819 CAN ACCEPT THIS IN UNICODE. JRA. */
8822 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8824 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8825 lp_netbios_name(), 15,
8826 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8827 if (!NT_STATUS_IS_OK(status
)) {
8828 reply_nterror(req
, status
);
8831 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8832 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8833 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8834 if (!NT_STATUS_IS_OK(status
)) {
8835 reply_nterror(req
, status
);
8838 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8843 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8844 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8847 /****************************************************************************
8848 Reply to a SMBfindclose (stop trans2 directory search).
8849 ****************************************************************************/
8851 void reply_findclose(struct smb_request
*req
)
8854 struct smbd_server_connection
*sconn
= req
->sconn
;
8856 START_PROFILE(SMBfindclose
);
8859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8860 END_PROFILE(SMBfindclose
);
8864 dptr_num
= SVALS(req
->vwv
+0, 0);
8866 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8868 dptr_close(sconn
, &dptr_num
);
8870 reply_outbuf(req
, 0, 0);
8872 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8874 END_PROFILE(SMBfindclose
);
8878 /****************************************************************************
8879 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8880 ****************************************************************************/
8882 void reply_findnclose(struct smb_request
*req
)
8886 START_PROFILE(SMBfindnclose
);
8889 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8890 END_PROFILE(SMBfindnclose
);
8894 dptr_num
= SVAL(req
->vwv
+0, 0);
8896 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8898 /* We never give out valid handles for a
8899 findnotifyfirst - so any dptr_num is ok here.
8902 reply_outbuf(req
, 0, 0);
8904 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8906 END_PROFILE(SMBfindnclose
);
8910 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8911 struct trans_state
*state
)
8913 if (get_Protocol() >= PROTOCOL_NT1
) {
8914 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8915 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8918 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8919 if (state
->call
!= TRANSACT2_QFSINFO
&&
8920 state
->call
!= TRANSACT2_SETFSINFO
) {
8921 DEBUG(0,("handle_trans2: encryption required "
8923 (unsigned int)state
->call
));
8924 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8929 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8931 /* Now we must call the relevant TRANS2 function */
8932 switch(state
->call
) {
8933 case TRANSACT2_OPEN
:
8935 START_PROFILE(Trans2_open
);
8936 call_trans2open(conn
, req
,
8937 &state
->param
, state
->total_param
,
8938 &state
->data
, state
->total_data
,
8939 state
->max_data_return
);
8940 END_PROFILE(Trans2_open
);
8944 case TRANSACT2_FINDFIRST
:
8946 START_PROFILE(Trans2_findfirst
);
8947 call_trans2findfirst(conn
, req
,
8948 &state
->param
, state
->total_param
,
8949 &state
->data
, state
->total_data
,
8950 state
->max_data_return
);
8951 END_PROFILE(Trans2_findfirst
);
8955 case TRANSACT2_FINDNEXT
:
8957 START_PROFILE(Trans2_findnext
);
8958 call_trans2findnext(conn
, req
,
8959 &state
->param
, state
->total_param
,
8960 &state
->data
, state
->total_data
,
8961 state
->max_data_return
);
8962 END_PROFILE(Trans2_findnext
);
8966 case TRANSACT2_QFSINFO
:
8968 START_PROFILE(Trans2_qfsinfo
);
8969 call_trans2qfsinfo(conn
, req
,
8970 &state
->param
, state
->total_param
,
8971 &state
->data
, state
->total_data
,
8972 state
->max_data_return
);
8973 END_PROFILE(Trans2_qfsinfo
);
8977 case TRANSACT2_SETFSINFO
:
8979 START_PROFILE(Trans2_setfsinfo
);
8980 call_trans2setfsinfo(conn
, req
,
8981 &state
->param
, state
->total_param
,
8982 &state
->data
, state
->total_data
,
8983 state
->max_data_return
);
8984 END_PROFILE(Trans2_setfsinfo
);
8988 case TRANSACT2_QPATHINFO
:
8989 case TRANSACT2_QFILEINFO
:
8991 START_PROFILE(Trans2_qpathinfo
);
8992 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8993 &state
->param
, state
->total_param
,
8994 &state
->data
, state
->total_data
,
8995 state
->max_data_return
);
8996 END_PROFILE(Trans2_qpathinfo
);
9000 case TRANSACT2_SETPATHINFO
:
9001 case TRANSACT2_SETFILEINFO
:
9003 START_PROFILE(Trans2_setpathinfo
);
9004 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9005 &state
->param
, state
->total_param
,
9006 &state
->data
, state
->total_data
,
9007 state
->max_data_return
);
9008 END_PROFILE(Trans2_setpathinfo
);
9012 case TRANSACT2_FINDNOTIFYFIRST
:
9014 START_PROFILE(Trans2_findnotifyfirst
);
9015 call_trans2findnotifyfirst(conn
, req
,
9016 &state
->param
, state
->total_param
,
9017 &state
->data
, state
->total_data
,
9018 state
->max_data_return
);
9019 END_PROFILE(Trans2_findnotifyfirst
);
9023 case TRANSACT2_FINDNOTIFYNEXT
:
9025 START_PROFILE(Trans2_findnotifynext
);
9026 call_trans2findnotifynext(conn
, req
,
9027 &state
->param
, state
->total_param
,
9028 &state
->data
, state
->total_data
,
9029 state
->max_data_return
);
9030 END_PROFILE(Trans2_findnotifynext
);
9034 case TRANSACT2_MKDIR
:
9036 START_PROFILE(Trans2_mkdir
);
9037 call_trans2mkdir(conn
, req
,
9038 &state
->param
, state
->total_param
,
9039 &state
->data
, state
->total_data
,
9040 state
->max_data_return
);
9041 END_PROFILE(Trans2_mkdir
);
9045 case TRANSACT2_GET_DFS_REFERRAL
:
9047 START_PROFILE(Trans2_get_dfs_referral
);
9048 call_trans2getdfsreferral(conn
, req
,
9049 &state
->param
, state
->total_param
,
9050 &state
->data
, state
->total_data
,
9051 state
->max_data_return
);
9052 END_PROFILE(Trans2_get_dfs_referral
);
9056 case TRANSACT2_IOCTL
:
9058 START_PROFILE(Trans2_ioctl
);
9059 call_trans2ioctl(conn
, req
,
9060 &state
->param
, state
->total_param
,
9061 &state
->data
, state
->total_data
,
9062 state
->max_data_return
);
9063 END_PROFILE(Trans2_ioctl
);
9068 /* Error in request */
9069 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9070 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9074 /****************************************************************************
9075 Reply to a SMBtrans2.
9076 ****************************************************************************/
9078 void reply_trans2(struct smb_request
*req
)
9080 connection_struct
*conn
= req
->conn
;
9085 unsigned int tran_call
;
9086 struct trans_state
*state
;
9089 START_PROFILE(SMBtrans2
);
9091 if (req
->wct
< 14) {
9092 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9093 END_PROFILE(SMBtrans2
);
9097 dsoff
= SVAL(req
->vwv
+12, 0);
9098 dscnt
= SVAL(req
->vwv
+11, 0);
9099 psoff
= SVAL(req
->vwv
+10, 0);
9100 pscnt
= SVAL(req
->vwv
+9, 0);
9101 tran_call
= SVAL(req
->vwv
+14, 0);
9103 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9104 if (!NT_STATUS_IS_OK(result
)) {
9105 DEBUG(2, ("Got invalid trans2 request: %s\n",
9106 nt_errstr(result
)));
9107 reply_nterror(req
, result
);
9108 END_PROFILE(SMBtrans2
);
9113 switch (tran_call
) {
9114 /* List the allowed trans2 calls on IPC$ */
9115 case TRANSACT2_OPEN
:
9116 case TRANSACT2_GET_DFS_REFERRAL
:
9117 case TRANSACT2_QFILEINFO
:
9118 case TRANSACT2_QFSINFO
:
9119 case TRANSACT2_SETFSINFO
:
9122 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9123 END_PROFILE(SMBtrans2
);
9128 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9129 DEBUG(0, ("talloc failed\n"));
9130 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9131 END_PROFILE(SMBtrans2
);
9135 state
->cmd
= SMBtrans2
;
9137 state
->mid
= req
->mid
;
9138 state
->vuid
= req
->vuid
;
9139 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9140 state
->setup
= NULL
;
9141 state
->total_param
= SVAL(req
->vwv
+0, 0);
9142 state
->param
= NULL
;
9143 state
->total_data
= SVAL(req
->vwv
+1, 0);
9145 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9146 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9147 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9148 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9149 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9151 state
->call
= tran_call
;
9153 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9154 is so as a sanity check */
9155 if (state
->setup_count
!= 1) {
9157 * Need to have rc=0 for ioctl to get job id for OS/2.
9158 * Network printing will fail if function is not successful.
9159 * Similar function in reply.c will be used if protocol
9160 * is LANMAN1.0 instead of LM1.2X002.
9161 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9162 * outbuf doesn't have to be set(only job id is used).
9164 if ( (state
->setup_count
== 4)
9165 && (tran_call
== TRANSACT2_IOCTL
)
9166 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9167 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9168 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9170 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9171 DEBUG(2,("Transaction is %d\n",tran_call
));
9173 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9174 END_PROFILE(SMBtrans2
);
9179 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9182 if (state
->total_data
) {
9184 if (trans_oob(state
->total_data
, 0, dscnt
)
9185 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9189 /* Can't use talloc here, the core routines do realloc on the
9190 * params and data. */
9191 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9192 if (state
->data
== NULL
) {
9193 DEBUG(0,("reply_trans2: data malloc fail for %u "
9194 "bytes !\n", (unsigned int)state
->total_data
));
9196 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9197 END_PROFILE(SMBtrans2
);
9201 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9204 if (state
->total_param
) {
9206 if (trans_oob(state
->total_param
, 0, pscnt
)
9207 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9211 /* Can't use talloc here, the core routines do realloc on the
9212 * params and data. */
9213 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9214 if (state
->param
== NULL
) {
9215 DEBUG(0,("reply_trans: param malloc fail for %u "
9216 "bytes !\n", (unsigned int)state
->total_param
));
9217 SAFE_FREE(state
->data
);
9219 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9220 END_PROFILE(SMBtrans2
);
9224 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9227 state
->received_data
= dscnt
;
9228 state
->received_param
= pscnt
;
9230 if ((state
->received_param
== state
->total_param
) &&
9231 (state
->received_data
== state
->total_data
)) {
9233 handle_trans2(conn
, req
, state
);
9235 SAFE_FREE(state
->data
);
9236 SAFE_FREE(state
->param
);
9238 END_PROFILE(SMBtrans2
);
9242 DLIST_ADD(conn
->pending_trans
, state
);
9244 /* We need to send an interim response then receive the rest
9245 of the parameter/data bytes */
9246 reply_outbuf(req
, 0, 0);
9247 show_msg((char *)req
->outbuf
);
9248 END_PROFILE(SMBtrans2
);
9253 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9254 SAFE_FREE(state
->data
);
9255 SAFE_FREE(state
->param
);
9257 END_PROFILE(SMBtrans2
);
9258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9262 /****************************************************************************
9263 Reply to a SMBtranss2
9264 ****************************************************************************/
9266 void reply_transs2(struct smb_request
*req
)
9268 connection_struct
*conn
= req
->conn
;
9269 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9270 struct trans_state
*state
;
9272 START_PROFILE(SMBtranss2
);
9274 show_msg((const char *)req
->inbuf
);
9276 /* Windows clients expect all replies to
9277 a transact secondary (SMBtranss2 0x33)
9278 to have a command code of transact
9279 (SMBtrans2 0x32). See bug #8989
9280 and also [MS-CIFS] section 2.2.4.47.2
9283 req
->cmd
= SMBtrans2
;
9286 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9287 END_PROFILE(SMBtranss2
);
9291 for (state
= conn
->pending_trans
; state
!= NULL
;
9292 state
= state
->next
) {
9293 if (state
->mid
== req
->mid
) {
9298 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9300 END_PROFILE(SMBtranss2
);
9304 /* Revise state->total_param and state->total_data in case they have
9305 changed downwards */
9307 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9308 state
->total_param
= SVAL(req
->vwv
+0, 0);
9309 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9310 state
->total_data
= SVAL(req
->vwv
+1, 0);
9312 pcnt
= SVAL(req
->vwv
+2, 0);
9313 poff
= SVAL(req
->vwv
+3, 0);
9314 pdisp
= SVAL(req
->vwv
+4, 0);
9316 dcnt
= SVAL(req
->vwv
+5, 0);
9317 doff
= SVAL(req
->vwv
+6, 0);
9318 ddisp
= SVAL(req
->vwv
+7, 0);
9320 state
->received_param
+= pcnt
;
9321 state
->received_data
+= dcnt
;
9323 if ((state
->received_data
> state
->total_data
) ||
9324 (state
->received_param
> state
->total_param
))
9328 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9329 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9332 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9336 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9337 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9340 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9343 if ((state
->received_param
< state
->total_param
) ||
9344 (state
->received_data
< state
->total_data
)) {
9345 END_PROFILE(SMBtranss2
);
9349 handle_trans2(conn
, req
, state
);
9351 DLIST_REMOVE(conn
->pending_trans
, state
);
9352 SAFE_FREE(state
->data
);
9353 SAFE_FREE(state
->param
);
9356 END_PROFILE(SMBtranss2
);
9361 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9362 DLIST_REMOVE(conn
->pending_trans
, state
);
9363 SAFE_FREE(state
->data
);
9364 SAFE_FREE(state
->param
);
9366 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9367 END_PROFILE(SMBtranss2
);