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
*)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
;
1092 uint32 create_disposition
;
1093 uint32 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
)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 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
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
)file_size
);
1709 SIVAL(p
,16,(uint32
)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
)file_size
);
1748 SIVAL(p
,16,(uint32
)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
)file_size
);
1798 SIVAL(p
,16,(uint32
)allocation_size
);
1800 p
+= 22; /* p now points to the EA area. */
1802 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1804 &ea_len
, &file_list
);
1805 if (!NT_STATUS_IS_OK(status
)) {
1808 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1810 /* We need to determine if this entry will fit in the space available. */
1811 /* Max string size is 255 bytes. */
1812 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1813 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1814 "(wanted %u, had %d)\n",
1815 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1817 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1820 /* Push the ea_data followed by the name. */
1821 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1823 status
= srvstr_push(base_data
, flags2
,
1824 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1825 STR_TERMINATE
| STR_NOALIGN
, &len
);
1826 if (!NT_STATUS_IS_OK(status
)) {
1829 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1842 SCVAL(nameptr
,0,len
);
1844 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1848 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1850 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1852 SIVAL(p
,0,reskey
); p
+= 4;
1853 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1854 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1855 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1856 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1857 SOFF_T(p
,0,file_size
); p
+= 8;
1858 SOFF_T(p
,0,allocation_size
); p
+= 8;
1859 SIVAL(p
,0,mode
); p
+= 4;
1860 q
= p
; p
+= 4; /* q is placeholder for name length. */
1861 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1862 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1864 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1866 SIVAL(p
,0,ea_size
); /* Extended attributes */
1869 /* Clear the short name buffer. This is
1870 * IMPORTANT as not doing so will trigger
1871 * a Win2k client bug. JRA.
1873 if (!was_8_3
&& check_mangled_names
) {
1874 char mangled_name
[13]; /* mangled 8.3 name. */
1875 if (!name_to_8_3(fname
,mangled_name
,True
,
1877 /* Error - mangle failed ! */
1878 memset(mangled_name
,'\0',12);
1880 mangled_name
[12] = 0;
1881 status
= srvstr_push(base_data
, flags2
,
1882 p
+2, mangled_name
, 24,
1883 STR_UPPER
|STR_UNICODE
, &len
);
1884 if (!NT_STATUS_IS_OK(status
)) {
1888 memset(p
+ 2 + len
,'\0',24 - len
);
1895 status
= srvstr_push(base_data
, flags2
, p
,
1896 fname
, PTR_DIFF(end_data
, p
),
1897 STR_TERMINATE_ASCII
, &len
);
1898 if (!NT_STATUS_IS_OK(status
)) {
1904 len
= PTR_DIFF(p
, pdata
);
1905 pad
= (len
+ (align
-1)) & ~(align
-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1913 * set padding to zero
1916 memset(p
, 0, pad
- len
);
1923 case SMB_FIND_FILE_DIRECTORY_INFO
:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1926 SIVAL(p
,0,reskey
); p
+= 4;
1927 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1928 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1929 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1930 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1931 SOFF_T(p
,0,file_size
); p
+= 8;
1932 SOFF_T(p
,0,allocation_size
); p
+= 8;
1933 SIVAL(p
,0,mode
); p
+= 4;
1934 status
= srvstr_push(base_data
, flags2
,
1935 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1936 STR_TERMINATE_ASCII
, &len
);
1937 if (!NT_STATUS_IS_OK(status
)) {
1943 len
= PTR_DIFF(p
, pdata
);
1944 pad
= (len
+ (align
-1)) & ~(align
-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1952 * set padding to zero
1955 memset(p
, 0, pad
- len
);
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1965 SIVAL(p
,0,reskey
); p
+= 4;
1966 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1967 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1968 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1969 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1970 SOFF_T(p
,0,file_size
); p
+= 8;
1971 SOFF_T(p
,0,allocation_size
); p
+= 8;
1972 SIVAL(p
,0,mode
); p
+= 4;
1973 q
= p
; p
+= 4; /* q is placeholder for name length. */
1975 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1977 SIVAL(p
,0,ea_size
); /* Extended attributes */
1980 status
= srvstr_push(base_data
, flags2
, p
,
1981 fname
, PTR_DIFF(end_data
, p
),
1982 STR_TERMINATE_ASCII
, &len
);
1983 if (!NT_STATUS_IS_OK(status
)) {
1989 len
= PTR_DIFF(p
, pdata
);
1990 pad
= (len
+ (align
-1)) & ~(align
-1);
1992 * offset to the next entry, the caller
1993 * will overwrite it for the last entry
1994 * that's why we always include the padding
1998 * set padding to zero
2001 memset(p
, 0, pad
- len
);
2008 case SMB_FIND_FILE_NAMES_INFO
:
2009 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2011 SIVAL(p
,0,reskey
); p
+= 4;
2013 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2014 acl on a dir (tridge) */
2015 status
= srvstr_push(base_data
, flags2
, p
,
2016 fname
, PTR_DIFF(end_data
, p
),
2017 STR_TERMINATE_ASCII
, &len
);
2018 if (!NT_STATUS_IS_OK(status
)) {
2024 len
= PTR_DIFF(p
, pdata
);
2025 pad
= (len
+ (align
-1)) & ~(align
-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2033 * set padding to zero
2036 memset(p
, 0, pad
- len
);
2043 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2044 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2046 SIVAL(p
,0,reskey
); p
+= 4;
2047 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2048 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2049 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2050 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2051 SOFF_T(p
,0,file_size
); p
+= 8;
2052 SOFF_T(p
,0,allocation_size
); p
+= 8;
2053 SIVAL(p
,0,mode
); p
+= 4;
2054 q
= p
; p
+= 4; /* q is placeholder for name length. */
2055 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2056 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2058 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2060 SIVAL(p
,0,ea_size
); /* Extended attributes */
2063 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2064 SBVAL(p
,0,file_index
); p
+= 8;
2065 status
= srvstr_push(base_data
, flags2
, p
,
2066 fname
, PTR_DIFF(end_data
, p
),
2067 STR_TERMINATE_ASCII
, &len
);
2068 if (!NT_STATUS_IS_OK(status
)) {
2074 len
= PTR_DIFF(p
, pdata
);
2075 pad
= (len
+ (align
-1)) & ~(align
-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2083 * set padding to zero
2086 memset(p
, 0, pad
- len
);
2093 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2095 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2097 SIVAL(p
,0,reskey
); p
+= 4;
2098 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2099 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2100 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2101 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2102 SOFF_T(p
,0,file_size
); p
+= 8;
2103 SOFF_T(p
,0,allocation_size
); p
+= 8;
2104 SIVAL(p
,0,mode
); p
+= 4;
2105 q
= p
; p
+= 4; /* q is placeholder for name length */
2106 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2107 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2108 } else if (readdir_attr_data
&&
2109 readdir_attr_data
->type
== RDATTR_AAPL
) {
2111 * OS X specific SMB2 extension negotiated via
2112 * AAPL create context: return max_access in
2115 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2117 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2119 SIVAL(p
,0,ea_size
); /* Extended attributes */
2123 if (readdir_attr_data
&&
2124 readdir_attr_data
->type
== RDATTR_AAPL
) {
2126 * OS X specific SMB2 extension negotiated via
2127 * AAPL create context: return resource fork
2128 * length and compressed FinderInfo in
2131 * According to documentation short_name_len
2132 * should be 0, but on the wire behaviour
2133 * shows its set to 24 by clients.
2137 /* Resourefork length */
2138 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2140 /* Compressed FinderInfo */
2141 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2142 } else if (!was_8_3
&& check_mangled_names
) {
2143 char mangled_name
[13]; /* mangled 8.3 name. */
2144 if (!name_to_8_3(fname
,mangled_name
,True
,
2146 /* Error - mangle failed ! */
2147 memset(mangled_name
,'\0',12);
2149 mangled_name
[12] = 0;
2150 status
= srvstr_push(base_data
, flags2
,
2151 p
+2, mangled_name
, 24,
2152 STR_UPPER
|STR_UNICODE
, &len
);
2153 if (!NT_STATUS_IS_OK(status
)) {
2158 memset(p
+ 2 + len
,'\0',24 - len
);
2162 /* Clear the short name buffer. This is
2163 * IMPORTANT as not doing so will trigger
2164 * a Win2k client bug. JRA.
2171 if (readdir_attr_data
&&
2172 readdir_attr_data
->type
== RDATTR_AAPL
) {
2174 * OS X specific SMB2 extension negotiated via
2175 * AAPL create context: return UNIX mode in
2178 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2179 SSVAL(p
, 0, aapl_mode
);
2185 SBVAL(p
,0,file_index
); p
+= 8;
2186 status
= srvstr_push(base_data
, flags2
, p
,
2187 fname
, PTR_DIFF(end_data
, p
),
2188 STR_TERMINATE_ASCII
, &len
);
2189 if (!NT_STATUS_IS_OK(status
)) {
2195 len
= PTR_DIFF(p
, pdata
);
2196 pad
= (len
+ (align
-1)) & ~(align
-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2204 * set padding to zero
2207 memset(p
, 0, pad
- len
);
2214 /* CIFS UNIX Extension. */
2216 case SMB_FIND_FILE_UNIX
:
2217 case SMB_FIND_FILE_UNIX_INFO2
:
2219 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2221 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (info_level
== SMB_FIND_FILE_UNIX
) {
2224 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2225 p
= store_file_unix_basic(conn
, p
,
2226 NULL
, &smb_fname
->st
);
2227 status
= srvstr_push(base_data
, flags2
, p
,
2228 fname
, PTR_DIFF(end_data
, p
),
2229 STR_TERMINATE
, &len
);
2230 if (!NT_STATUS_IS_OK(status
)) {
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2235 p
= store_file_unix_basic_info2(conn
, p
,
2236 NULL
, &smb_fname
->st
);
2239 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2240 PTR_DIFF(end_data
, p
), 0, &len
);
2241 if (!NT_STATUS_IS_OK(status
)) {
2244 SIVAL(nameptr
, 0, len
);
2249 len
= PTR_DIFF(p
, pdata
);
2250 pad
= (len
+ (align
-1)) & ~(align
-1);
2252 * offset to the next entry, the caller
2253 * will overwrite it for the last entry
2254 * that's why we always include the padding
2258 * set padding to zero
2261 memset(p
, 0, pad
- len
);
2266 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2271 return NT_STATUS_INVALID_LEVEL
;
2274 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2275 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2276 "(wanted %u, had %d)\n",
2277 (unsigned int)PTR_DIFF(p
,pdata
),
2279 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2282 /* Setup the last entry pointer, as an offset from base_data */
2283 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2284 /* Advance the data pointer to the next slot */
2287 return NT_STATUS_OK
;
2290 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2291 connection_struct
*conn
,
2292 struct dptr_struct
*dirptr
,
2294 const char *path_mask
,
2297 int requires_resume_key
,
2305 int space_remaining
,
2306 bool *got_exact_match
,
2307 int *_last_entry_off
,
2308 struct ea_list
*name_list
)
2311 const char *mask
= NULL
;
2312 long prev_dirpos
= 0;
2315 struct smb_filename
*smb_fname
= NULL
;
2316 struct smbd_dirptr_lanman2_state state
;
2318 uint64_t last_entry_off
= 0;
2323 state
.info_level
= info_level
;
2324 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2325 state
.has_wild
= dptr_has_wild(dirptr
);
2326 state
.got_exact_match
= false;
2328 *got_exact_match
= false;
2330 p
= strrchr_m(path_mask
,'/');
2341 ok
= smbd_dirptr_get_entry(ctx
,
2347 smbd_dirptr_lanman2_match_fn
,
2348 smbd_dirptr_lanman2_mode_fn
,
2355 return NT_STATUS_END_OF_FILE
;
2358 *got_exact_match
= state
.got_exact_match
;
2360 status
= smbd_marshall_dir_entry(ctx
,
2365 state
.check_mangled_names
,
2366 requires_resume_key
,
2378 TALLOC_FREE(smb_fname
);
2379 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2380 dptr_SeekDir(dirptr
, prev_dirpos
);
2383 if (!NT_STATUS_IS_OK(status
)) {
2387 *_last_entry_off
= last_entry_off
;
2388 return NT_STATUS_OK
;
2391 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2392 connection_struct
*conn
,
2393 struct dptr_struct
*dirptr
,
2395 const char *path_mask
,
2398 bool requires_resume_key
,
2404 int space_remaining
,
2405 bool *got_exact_match
,
2406 int *last_entry_off
,
2407 struct ea_list
*name_list
)
2410 const bool do_pad
= true;
2412 if (info_level
>= 1 && info_level
<= 3) {
2413 /* No alignment on earlier info levels. */
2417 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2418 path_mask
, dirtype
, info_level
,
2419 requires_resume_key
, dont_descend
, ask_sharemode
,
2421 ppdata
, base_data
, end_data
,
2424 last_entry_off
, name_list
);
2427 /****************************************************************************
2428 Reply to a TRANS2_FINDFIRST.
2429 ****************************************************************************/
2431 static void call_trans2findfirst(connection_struct
*conn
,
2432 struct smb_request
*req
,
2433 char **pparams
, int total_params
,
2434 char **ppdata
, int total_data
,
2435 unsigned int max_data_bytes
)
2437 /* We must be careful here that we don't return more than the
2438 allowed number of data bytes. If this means returning fewer than
2439 maxentries then so be it. We assume that the redirector has
2440 enough room for the fixed number of parameter bytes it has
2442 struct smb_filename
*smb_dname
= NULL
;
2443 char *params
= *pparams
;
2444 char *pdata
= *ppdata
;
2448 uint16 findfirst_flags
;
2449 bool close_after_first
;
2451 bool requires_resume_key
;
2453 char *directory
= NULL
;
2456 int last_entry_off
=0;
2460 bool finished
= False
;
2461 bool dont_descend
= False
;
2462 bool out_of_space
= False
;
2463 int space_remaining
;
2464 bool mask_contains_wcard
= False
;
2465 struct ea_list
*ea_list
= NULL
;
2466 NTSTATUS ntstatus
= NT_STATUS_OK
;
2467 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2468 TALLOC_CTX
*ctx
= talloc_tos();
2469 struct dptr_struct
*dirptr
= NULL
;
2470 struct smbd_server_connection
*sconn
= req
->sconn
;
2471 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2472 bool backup_priv
= false;
2474 if (total_params
< 13) {
2475 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2479 dirtype
= SVAL(params
,0);
2480 maxentries
= SVAL(params
,2);
2481 findfirst_flags
= SVAL(params
,4);
2482 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2483 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2484 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2485 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2486 security_token_has_privilege(get_current_nttok(conn
),
2489 info_level
= SVAL(params
,6);
2491 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2492 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2493 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2495 info_level
, max_data_bytes
));
2498 /* W2K3 seems to treat zero as 1. */
2502 switch (info_level
) {
2503 case SMB_FIND_INFO_STANDARD
:
2504 case SMB_FIND_EA_SIZE
:
2505 case SMB_FIND_EA_LIST
:
2506 case SMB_FIND_FILE_DIRECTORY_INFO
:
2507 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2508 case SMB_FIND_FILE_NAMES_INFO
:
2509 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2510 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2511 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2513 case SMB_FIND_FILE_UNIX
:
2514 case SMB_FIND_FILE_UNIX_INFO2
:
2515 /* Always use filesystem for UNIX mtime query. */
2516 ask_sharemode
= false;
2517 if (!lp_unix_extensions()) {
2518 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2521 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2524 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2528 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2529 params
+12, total_params
- 12,
2530 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2531 if (!NT_STATUS_IS_OK(ntstatus
)) {
2532 reply_nterror(req
, ntstatus
);
2538 ntstatus
= filename_convert_with_privilege(ctx
,
2543 &mask_contains_wcard
,
2546 ntstatus
= filename_convert(ctx
, conn
,
2547 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2550 &mask_contains_wcard
,
2554 if (!NT_STATUS_IS_OK(ntstatus
)) {
2555 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2556 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2557 ERRSRV
, ERRbadpath
);
2560 reply_nterror(req
, ntstatus
);
2564 mask
= smb_dname
->original_lcomp
;
2566 directory
= smb_dname
->base_name
;
2568 p
= strrchr_m(directory
,'/');
2570 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2571 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2572 mask
= talloc_strdup(ctx
,"*");
2574 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2577 mask_contains_wcard
= True
;
2583 if (p
== NULL
|| p
== directory
) {
2584 /* Ensure we don't have a directory name of "". */
2585 directory
= talloc_strdup(talloc_tos(), ".");
2587 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2592 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2594 if (info_level
== SMB_FIND_EA_LIST
) {
2597 if (total_data
< 4) {
2598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2602 ea_size
= IVAL(pdata
,0);
2603 if (ea_size
!= total_data
) {
2604 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2605 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2606 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2610 if (!lp_ea_support(SNUM(conn
))) {
2611 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2615 /* Pull out the list of names. */
2616 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2618 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2623 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2624 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2628 *ppdata
= (char *)SMB_REALLOC(
2629 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2630 if(*ppdata
== NULL
) {
2631 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2635 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2637 /* Realloc the params space */
2638 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2639 if (*pparams
== NULL
) {
2640 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2645 /* Save the wildcard match and attribs we are using on this directory -
2646 needed as lanman2 assumes these are being saved between calls */
2648 ntstatus
= dptr_create(conn
,
2656 mask_contains_wcard
,
2660 if (!NT_STATUS_IS_OK(ntstatus
)) {
2661 reply_nterror(req
, ntstatus
);
2666 /* Remember this in case we have
2667 to do a findnext. */
2668 dptr_set_priv(dirptr
);
2671 dptr_num
= dptr_dnum(dirptr
);
2672 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2674 /* Initialize per TRANS2_FIND_FIRST operation data */
2675 dptr_init_search_op(dirptr
);
2677 /* We don't need to check for VOL here as this is returned by
2678 a different TRANS2 call. */
2680 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2681 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2682 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2683 dont_descend
= True
;
2686 space_remaining
= max_data_bytes
;
2687 out_of_space
= False
;
2689 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2690 bool got_exact_match
= False
;
2692 /* this is a heuristic to avoid seeking the dirptr except when
2693 absolutely necessary. It allows for a filename of about 40 chars */
2694 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2695 out_of_space
= True
;
2698 ntstatus
= get_lanman2_dir_entry(ctx
,
2702 mask
,dirtype
,info_level
,
2703 requires_resume_key
,dont_descend
,
2708 &last_entry_off
, ea_list
);
2709 if (NT_STATUS_EQUAL(ntstatus
,
2710 NT_STATUS_ILLEGAL_CHARACTER
)) {
2712 * Bad character conversion on name. Ignore this
2717 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2718 out_of_space
= true;
2720 finished
= !NT_STATUS_IS_OK(ntstatus
);
2724 if (!finished
&& !out_of_space
)
2728 * As an optimisation if we know we aren't looking
2729 * for a wildcard name (ie. the name matches the wildcard exactly)
2730 * then we can finish on any (first) match.
2731 * This speeds up large directory searches. JRA.
2737 /* Ensure space_remaining never goes -ve. */
2738 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2739 space_remaining
= 0;
2740 out_of_space
= true;
2742 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2746 /* Check if we can close the dirptr */
2747 if(close_after_first
|| (finished
&& close_if_end
)) {
2748 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2749 dptr_close(sconn
, &dptr_num
);
2753 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2754 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2755 * the protocol level is less than NT1. Tested with smbclient. JRA.
2756 * This should fix the OS/2 client bug #2335.
2759 if(numentries
== 0) {
2760 dptr_close(sconn
, &dptr_num
);
2761 if (get_Protocol() < PROTOCOL_NT1
) {
2762 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2765 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2766 ERRDOS
, ERRbadfile
);
2771 /* At this point pdata points to numentries directory entries. */
2773 /* Set up the return parameter block */
2774 SSVAL(params
,0,dptr_num
);
2775 SSVAL(params
,2,numentries
);
2776 SSVAL(params
,4,finished
);
2777 SSVAL(params
,6,0); /* Never an EA error */
2778 SSVAL(params
,8,last_entry_off
);
2780 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2783 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2784 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2786 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2790 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2791 smb_fn_name(req
->cmd
),
2792 mask
, directory
, dirtype
, numentries
) );
2795 * Force a name mangle here to ensure that the
2796 * mask as an 8.3 name is top of the mangled cache.
2797 * The reasons for this are subtle. Don't remove
2798 * this code unless you know what you are doing
2799 * (see PR#13758). JRA.
2802 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2803 char mangled_name
[13];
2804 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2812 TALLOC_FREE(smb_dname
);
2816 /****************************************************************************
2817 Reply to a TRANS2_FINDNEXT.
2818 ****************************************************************************/
2820 static void call_trans2findnext(connection_struct
*conn
,
2821 struct smb_request
*req
,
2822 char **pparams
, int total_params
,
2823 char **ppdata
, int total_data
,
2824 unsigned int max_data_bytes
)
2826 /* We must be careful here that we don't return more than the
2827 allowed number of data bytes. If this means returning fewer than
2828 maxentries then so be it. We assume that the redirector has
2829 enough room for the fixed number of parameter bytes it has
2831 char *params
= *pparams
;
2832 char *pdata
= *ppdata
;
2838 uint16 findnext_flags
;
2839 bool close_after_request
;
2841 bool requires_resume_key
;
2843 bool mask_contains_wcard
= False
;
2844 char *resume_name
= NULL
;
2845 const char *mask
= NULL
;
2846 const char *directory
= NULL
;
2850 int i
, last_entry_off
=0;
2851 bool finished
= False
;
2852 bool dont_descend
= False
;
2853 bool out_of_space
= False
;
2854 int space_remaining
;
2855 struct ea_list
*ea_list
= NULL
;
2856 NTSTATUS ntstatus
= NT_STATUS_OK
;
2857 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2858 TALLOC_CTX
*ctx
= talloc_tos();
2859 struct dptr_struct
*dirptr
;
2860 struct smbd_server_connection
*sconn
= req
->sconn
;
2861 bool backup_priv
= false;
2863 if (total_params
< 13) {
2864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2868 dptr_num
= SVAL(params
,0);
2869 maxentries
= SVAL(params
,2);
2870 info_level
= SVAL(params
,4);
2871 resume_key
= IVAL(params
,6);
2872 findnext_flags
= SVAL(params
,10);
2873 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2874 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2875 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2876 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2878 if (!continue_bit
) {
2879 /* We only need resume_name if continue_bit is zero. */
2880 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2882 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2883 &mask_contains_wcard
);
2884 if (!NT_STATUS_IS_OK(ntstatus
)) {
2885 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2886 complain (it thinks we're asking for the directory above the shared
2887 path or an invalid name). Catch this as the resume name is only compared, never used in
2888 a file access. JRA. */
2889 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2890 &resume_name
, params
+12,
2894 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2895 reply_nterror(req
, ntstatus
);
2901 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2902 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2903 resume_key = %d resume name = %s continue=%d level = %d\n",
2904 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2905 requires_resume_key
, resume_key
,
2906 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2909 /* W2K3 seems to treat zero as 1. */
2913 switch (info_level
) {
2914 case SMB_FIND_INFO_STANDARD
:
2915 case SMB_FIND_EA_SIZE
:
2916 case SMB_FIND_EA_LIST
:
2917 case SMB_FIND_FILE_DIRECTORY_INFO
:
2918 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2919 case SMB_FIND_FILE_NAMES_INFO
:
2920 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2921 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2922 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2924 case SMB_FIND_FILE_UNIX
:
2925 case SMB_FIND_FILE_UNIX_INFO2
:
2926 /* Always use filesystem for UNIX mtime query. */
2927 ask_sharemode
= false;
2928 if (!lp_unix_extensions()) {
2929 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2934 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2938 if (info_level
== SMB_FIND_EA_LIST
) {
2941 if (total_data
< 4) {
2942 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2946 ea_size
= IVAL(pdata
,0);
2947 if (ea_size
!= total_data
) {
2948 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2949 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2950 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2954 if (!lp_ea_support(SNUM(conn
))) {
2955 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2959 /* Pull out the list of names. */
2960 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2967 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2968 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2972 *ppdata
= (char *)SMB_REALLOC(
2973 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2974 if(*ppdata
== NULL
) {
2975 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2980 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2982 /* Realloc the params space */
2983 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2984 if(*pparams
== NULL
) {
2985 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2991 /* Check that the dptr is valid */
2992 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2993 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2997 directory
= dptr_path(sconn
, dptr_num
);
2999 /* Get the wildcard mask from the dptr */
3000 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3001 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3002 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3006 /* Get the attr mask from the dptr */
3007 dirtype
= dptr_attr(sconn
, dptr_num
);
3009 backup_priv
= dptr_get_priv(dirptr
);
3011 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3012 "backup_priv = %d\n",
3013 dptr_num
, mask
, dirtype
,
3015 dptr_TellDir(dirptr
),
3018 /* Initialize per TRANS2_FIND_NEXT operation data */
3019 dptr_init_search_op(dirptr
);
3021 /* We don't need to check for VOL here as this is returned by
3022 a different TRANS2 call. */
3024 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3025 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3026 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3027 dont_descend
= True
;
3030 space_remaining
= max_data_bytes
;
3031 out_of_space
= False
;
3038 * Seek to the correct position. We no longer use the resume key but
3039 * depend on the last file name instead.
3042 if(!continue_bit
&& resume_name
&& *resume_name
) {
3045 long current_pos
= 0;
3047 * Remember, name_to_8_3 is called by
3048 * get_lanman2_dir_entry(), so the resume name
3049 * could be mangled. Ensure we check the unmangled name.
3052 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3053 char *new_resume_name
= NULL
;
3054 mangle_lookup_name_from_8_3(ctx
,
3058 if (new_resume_name
) {
3059 resume_name
= new_resume_name
;
3064 * Fix for NT redirector problem triggered by resume key indexes
3065 * changing between directory scans. We now return a resume key of 0
3066 * and instead look for the filename to continue from (also given
3067 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3068 * findfirst/findnext (as is usual) then the directory pointer
3069 * should already be at the correct place.
3072 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3073 } /* end if resume_name && !continue_bit */
3075 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3076 bool got_exact_match
= False
;
3078 /* this is a heuristic to avoid seeking the dirptr except when
3079 absolutely necessary. It allows for a filename of about 40 chars */
3080 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3081 out_of_space
= True
;
3084 ntstatus
= get_lanman2_dir_entry(ctx
,
3088 mask
,dirtype
,info_level
,
3089 requires_resume_key
,dont_descend
,
3094 &last_entry_off
, ea_list
);
3095 if (NT_STATUS_EQUAL(ntstatus
,
3096 NT_STATUS_ILLEGAL_CHARACTER
)) {
3098 * Bad character conversion on name. Ignore this
3103 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3104 out_of_space
= true;
3106 finished
= !NT_STATUS_IS_OK(ntstatus
);
3110 if (!finished
&& !out_of_space
)
3114 * As an optimisation if we know we aren't looking
3115 * for a wildcard name (ie. the name matches the wildcard exactly)
3116 * then we can finish on any (first) match.
3117 * This speeds up large directory searches. JRA.
3123 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3126 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3127 smb_fn_name(req
->cmd
),
3128 mask
, directory
, dirtype
, numentries
) );
3130 /* Check if we can close the dirptr */
3131 if(close_after_request
|| (finished
&& close_if_end
)) {
3132 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3133 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3140 /* Set up the return parameter block */
3141 SSVAL(params
,0,numentries
);
3142 SSVAL(params
,2,finished
);
3143 SSVAL(params
,4,0); /* Never an EA error */
3144 SSVAL(params
,6,last_entry_off
);
3146 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3152 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3154 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3158 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3160 SMB_ASSERT(extended_info
!= NULL
);
3162 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3163 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3164 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3165 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3166 #ifdef SAMBA_VERSION_REVISION
3167 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3169 extended_info
->samba_subversion
= 0;
3170 #ifdef SAMBA_VERSION_RC_RELEASE
3171 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3173 #ifdef SAMBA_VERSION_PRE_RELEASE
3174 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3177 #ifdef SAMBA_VERSION_VENDOR_PATCH
3178 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3180 extended_info
->samba_gitcommitdate
= 0;
3181 #ifdef SAMBA_VERSION_COMMIT_TIME
3182 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3185 memset(extended_info
->samba_version_string
, 0,
3186 sizeof(extended_info
->samba_version_string
));
3188 snprintf (extended_info
->samba_version_string
,
3189 sizeof(extended_info
->samba_version_string
),
3190 "%s", samba_version_string());
3193 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3194 connection_struct
*conn
,
3195 TALLOC_CTX
*mem_ctx
,
3196 uint16_t info_level
,
3198 unsigned int max_data_bytes
,
3199 size_t *fixed_portion
,
3200 struct smb_filename
*fname
,
3204 char *pdata
, *end_data
;
3207 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3208 int snum
= SNUM(conn
);
3209 const char *fstype
= lp_fstype(SNUM(conn
));
3210 const char *filename
= NULL
;
3211 uint32 additional_flags
= 0;
3212 struct smb_filename smb_fname
;
3214 NTSTATUS status
= NT_STATUS_OK
;
3217 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3220 filename
= fname
->base_name
;
3224 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3225 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3226 "info level (0x%x) on IPC$.\n",
3227 (unsigned int)info_level
));
3228 return NT_STATUS_ACCESS_DENIED
;
3232 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3234 ZERO_STRUCT(smb_fname
);
3235 smb_fname
.base_name
= discard_const_p(char, filename
);
3237 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3238 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3239 return map_nt_error_from_unix(errno
);
3244 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3245 return NT_STATUS_INVALID_PARAMETER
;
3248 *ppdata
= (char *)SMB_REALLOC(
3249 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3250 if (*ppdata
== NULL
) {
3251 return NT_STATUS_NO_MEMORY
;
3255 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3256 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3260 switch (info_level
) {
3261 case SMB_INFO_ALLOCATION
:
3263 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3265 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3267 if (df_ret
== (uint64_t)-1) {
3268 return map_nt_error_from_unix(errno
);
3271 block_size
= lp_block_size(snum
);
3272 if (bsize
< block_size
) {
3273 uint64_t factor
= block_size
/bsize
;
3278 if (bsize
> block_size
) {
3279 uint64_t factor
= bsize
/block_size
;
3284 bytes_per_sector
= 512;
3285 sectors_per_unit
= bsize
/bytes_per_sector
;
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3289 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3291 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3292 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3293 SIVAL(pdata
,l1_cUnit
,dsize
);
3294 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3295 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3299 case SMB_INFO_VOLUME
:
3300 /* Return volume name */
3302 * Add volume serial number - hash of a combination of
3303 * the called hostname and the service name.
3305 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3307 * Win2k3 and previous mess this up by sending a name length
3308 * one byte short. I believe only older clients (OS/2 Win9x) use
3309 * this call so try fixing this by adding a terminating null to
3310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3312 status
= srvstr_push(
3314 pdata
+l2_vol_szVolLabel
, vname
,
3315 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3316 STR_NOALIGN
|STR_TERMINATE
, &len
);
3317 if (!NT_STATUS_IS_OK(status
)) {
3320 SCVAL(pdata
,l2_vol_cch
,len
);
3321 data_len
= l2_vol_szVolLabel
+ len
;
3322 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3323 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3324 (unsigned)len
, vname
));
3327 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3328 case SMB_FS_ATTRIBUTE_INFORMATION
:
3330 additional_flags
= 0;
3331 #if defined(HAVE_SYS_QUOTAS)
3332 additional_flags
|= FILE_VOLUME_QUOTAS
;
3335 if(lp_nt_acl_support(SNUM(conn
))) {
3336 additional_flags
|= FILE_PERSISTENT_ACLS
;
3339 /* Capabilities are filled in at connection time through STATVFS call */
3340 additional_flags
|= conn
->fs_capabilities
;
3341 additional_flags
|= lp_parm_int(conn
->params
->service
,
3342 "share", "fake_fscaps",
3345 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3346 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3347 additional_flags
); /* FS ATTRIBUTES */
3349 SIVAL(pdata
,4,255); /* Max filename component length */
3350 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3351 and will think we can't do long filenames */
3352 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3353 PTR_DIFF(end_data
, pdata
+12),
3355 if (!NT_STATUS_IS_OK(status
)) {
3359 data_len
= 12 + len
;
3360 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3361 /* the client only requested a portion of the
3363 data_len
= max_data_bytes
;
3364 status
= STATUS_BUFFER_OVERFLOW
;
3366 *fixed_portion
= 16;
3369 case SMB_QUERY_FS_LABEL_INFO
:
3370 case SMB_FS_LABEL_INFORMATION
:
3371 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3372 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3373 if (!NT_STATUS_IS_OK(status
)) {
3380 case SMB_QUERY_FS_VOLUME_INFO
:
3381 case SMB_FS_VOLUME_INFORMATION
:
3384 * Add volume serial number - hash of a combination of
3385 * the called hostname and the service name.
3387 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3388 (str_checksum(get_local_machine_name())<<16));
3390 /* Max label len is 32 characters. */
3391 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3392 PTR_DIFF(end_data
, pdata
+18),
3394 if (!NT_STATUS_IS_OK(status
)) {
3397 SIVAL(pdata
,12,len
);
3400 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3401 (int)strlen(vname
),vname
,
3402 lp_servicename(talloc_tos(), snum
)));
3403 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3404 /* the client only requested a portion of the
3406 data_len
= max_data_bytes
;
3407 status
= STATUS_BUFFER_OVERFLOW
;
3409 *fixed_portion
= 24;
3412 case SMB_QUERY_FS_SIZE_INFO
:
3413 case SMB_FS_SIZE_INFORMATION
:
3415 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3417 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3419 if (df_ret
== (uint64_t)-1) {
3420 return map_nt_error_from_unix(errno
);
3422 block_size
= lp_block_size(snum
);
3423 if (bsize
< block_size
) {
3424 uint64_t factor
= block_size
/bsize
;
3429 if (bsize
> block_size
) {
3430 uint64_t factor
= bsize
/block_size
;
3435 bytes_per_sector
= 512;
3436 sectors_per_unit
= bsize
/bytes_per_sector
;
3437 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3438 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3439 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3440 SBIG_UINT(pdata
,0,dsize
);
3441 SBIG_UINT(pdata
,8,dfree
);
3442 SIVAL(pdata
,16,sectors_per_unit
);
3443 SIVAL(pdata
,20,bytes_per_sector
);
3444 *fixed_portion
= 24;
3448 case SMB_FS_FULL_SIZE_INFORMATION
:
3450 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3452 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3454 if (df_ret
== (uint64_t)-1) {
3455 return map_nt_error_from_unix(errno
);
3457 block_size
= lp_block_size(snum
);
3458 if (bsize
< block_size
) {
3459 uint64_t factor
= block_size
/bsize
;
3464 if (bsize
> block_size
) {
3465 uint64_t factor
= bsize
/block_size
;
3470 bytes_per_sector
= 512;
3471 sectors_per_unit
= bsize
/bytes_per_sector
;
3472 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3473 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3474 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3475 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3476 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3477 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3478 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3479 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3480 *fixed_portion
= 32;
3484 case SMB_QUERY_FS_DEVICE_INFO
:
3485 case SMB_FS_DEVICE_INFORMATION
:
3487 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3489 if (!CAN_WRITE(conn
)) {
3490 characteristics
|= FILE_READ_ONLY_DEVICE
;
3493 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3494 SIVAL(pdata
,4,characteristics
);
3499 #ifdef HAVE_SYS_QUOTAS
3500 case SMB_FS_QUOTA_INFORMATION
:
3502 * what we have to send --metze:
3504 * Unknown1: 24 NULL bytes
3505 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3506 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3507 * Quota Flags: 2 byte :
3508 * Unknown3: 6 NULL bytes
3512 * details for Quota Flags:
3514 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3515 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3516 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3517 * 0x0001 Enable Quotas: enable quota for this fs
3521 /* we need to fake up a fsp here,
3522 * because its not send in this call
3525 SMB_NTQUOTA_STRUCT quotas
;
3528 ZERO_STRUCT(quotas
);
3531 fsp
.fnum
= FNUM_FIELD_INVALID
;
3534 if (get_current_uid(conn
) != 0) {
3535 DEBUG(0,("get_user_quota: access_denied "
3536 "service [%s] user [%s]\n",
3537 lp_servicename(talloc_tos(), SNUM(conn
)),
3538 conn
->session_info
->unix_info
->unix_name
));
3539 return NT_STATUS_ACCESS_DENIED
;
3542 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3543 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3544 return map_nt_error_from_unix(errno
);
3549 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3550 lp_servicename(talloc_tos(), SNUM(conn
))));
3552 /* Unknown1 24 NULL bytes*/
3553 SBIG_UINT(pdata
,0,(uint64_t)0);
3554 SBIG_UINT(pdata
,8,(uint64_t)0);
3555 SBIG_UINT(pdata
,16,(uint64_t)0);
3557 /* Default Soft Quota 8 bytes */
3558 SBIG_UINT(pdata
,24,quotas
.softlim
);
3560 /* Default Hard Quota 8 bytes */
3561 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3563 /* Quota flag 2 bytes */
3564 SSVAL(pdata
,40,quotas
.qflags
);
3566 /* Unknown3 6 NULL bytes */
3572 #endif /* HAVE_SYS_QUOTAS */
3573 case SMB_FS_OBJECTID_INFORMATION
:
3575 unsigned char objid
[16];
3576 struct smb_extended_info extended_info
;
3577 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3578 samba_extended_info_version (&extended_info
);
3579 SIVAL(pdata
,16,extended_info
.samba_magic
);
3580 SIVAL(pdata
,20,extended_info
.samba_version
);
3581 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3582 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3583 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3589 * Query the version and capabilities of the CIFS UNIX extensions
3593 case SMB_QUERY_CIFS_UNIX_INFO
:
3595 bool large_write
= lp_min_receive_file_size() &&
3596 !srv_is_signing_active(xconn
);
3597 bool large_read
= !srv_is_signing_active(xconn
);
3598 int encrypt_caps
= 0;
3600 if (!lp_unix_extensions()) {
3601 return NT_STATUS_INVALID_LEVEL
;
3604 switch (conn
->encrypt_level
) {
3605 case SMB_SIGNING_OFF
:
3608 case SMB_SIGNING_IF_REQUIRED
:
3609 case SMB_SIGNING_DEFAULT
:
3610 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3612 case SMB_SIGNING_REQUIRED
:
3613 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3614 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3615 large_write
= false;
3621 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3622 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3624 /* We have POSIX ACLs, pathname, encryption,
3625 * large read/write, and locking capability. */
3627 SBIG_UINT(pdata
,4,((uint64_t)(
3628 CIFS_UNIX_POSIX_ACLS_CAP
|
3629 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3630 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3631 CIFS_UNIX_EXTATTR_CAP
|
3632 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3634 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3636 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3640 case SMB_QUERY_POSIX_FS_INFO
:
3643 vfs_statvfs_struct svfs
;
3645 if (!lp_unix_extensions()) {
3646 return NT_STATUS_INVALID_LEVEL
;
3649 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3653 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3654 SIVAL(pdata
,4,svfs
.BlockSize
);
3655 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3656 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3657 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3658 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3659 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3660 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3661 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3663 } else if (rc
== EOPNOTSUPP
) {
3664 return NT_STATUS_INVALID_LEVEL
;
3665 #endif /* EOPNOTSUPP */
3667 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3668 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3673 case SMB_QUERY_POSIX_WHOAMI
:
3679 if (!lp_unix_extensions()) {
3680 return NT_STATUS_INVALID_LEVEL
;
3683 if (max_data_bytes
< 40) {
3684 return NT_STATUS_BUFFER_TOO_SMALL
;
3687 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3688 flags
|= SMB_WHOAMI_GUEST
;
3691 /* NOTE: 8 bytes for UID/GID, irrespective of native
3692 * platform size. This matches
3693 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3695 data_len
= 4 /* flags */
3702 + 4 /* pad/reserved */
3703 + (conn
->session_info
->unix_token
->ngroups
* 8)
3705 + (conn
->session_info
->security_token
->num_sids
*
3709 SIVAL(pdata
, 0, flags
);
3710 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3712 (uint64_t)conn
->session_info
->unix_token
->uid
);
3713 SBIG_UINT(pdata
, 16,
3714 (uint64_t)conn
->session_info
->unix_token
->gid
);
3717 if (data_len
>= max_data_bytes
) {
3718 /* Potential overflow, skip the GIDs and SIDs. */
3720 SIVAL(pdata
, 24, 0); /* num_groups */
3721 SIVAL(pdata
, 28, 0); /* num_sids */
3722 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3723 SIVAL(pdata
, 36, 0); /* reserved */
3729 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3730 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3732 /* We walk the SID list twice, but this call is fairly
3733 * infrequent, and I don't expect that it's performance
3734 * sensitive -- jpeach
3736 for (i
= 0, sid_bytes
= 0;
3737 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3738 sid_bytes
+= ndr_size_dom_sid(
3739 &conn
->session_info
->security_token
->sids
[i
],
3743 /* SID list byte count */
3744 SIVAL(pdata
, 32, sid_bytes
);
3746 /* 4 bytes pad/reserved - must be zero */
3747 SIVAL(pdata
, 36, 0);
3751 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3752 SBIG_UINT(pdata
, data_len
,
3753 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3759 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3760 int sid_len
= ndr_size_dom_sid(
3761 &conn
->session_info
->security_token
->sids
[i
],
3764 sid_linearize(pdata
+ data_len
, sid_len
,
3765 &conn
->session_info
->security_token
->sids
[i
]);
3766 data_len
+= sid_len
;
3772 case SMB_MAC_QUERY_FS_INFO
:
3774 * Thursby MAC extension... ONLY on NTFS filesystems
3775 * once we do streams then we don't need this
3777 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3779 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3784 return NT_STATUS_INVALID_LEVEL
;
3787 *ret_data_len
= data_len
;
3791 /****************************************************************************
3792 Reply to a TRANS2_QFSINFO (query filesystem info).
3793 ****************************************************************************/
3795 static void call_trans2qfsinfo(connection_struct
*conn
,
3796 struct smb_request
*req
,
3797 char **pparams
, int total_params
,
3798 char **ppdata
, int total_data
,
3799 unsigned int max_data_bytes
)
3801 char *params
= *pparams
;
3802 uint16_t info_level
;
3804 size_t fixed_portion
;
3807 if (total_params
< 2) {
3808 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3812 info_level
= SVAL(params
,0);
3814 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3815 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3816 DEBUG(0,("call_trans2qfsinfo: encryption required "
3817 "and info level 0x%x sent.\n",
3818 (unsigned int)info_level
));
3819 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3824 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3826 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3833 if (!NT_STATUS_IS_OK(status
)) {
3834 reply_nterror(req
, status
);
3838 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3841 DEBUG( 4, ( "%s info_level = %d\n",
3842 smb_fn_name(req
->cmd
), info_level
) );
3847 /****************************************************************************
3848 Reply to a TRANS2_SETFSINFO (set filesystem info).
3849 ****************************************************************************/
3851 static void call_trans2setfsinfo(connection_struct
*conn
,
3852 struct smb_request
*req
,
3853 char **pparams
, int total_params
,
3854 char **ppdata
, int total_data
,
3855 unsigned int max_data_bytes
)
3857 struct smbXsrv_connection
*xconn
= req
->xconn
;
3858 char *pdata
= *ppdata
;
3859 char *params
= *pparams
;
3862 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3863 lp_servicename(talloc_tos(), SNUM(conn
))));
3866 if (total_params
< 4) {
3867 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3869 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3873 info_level
= SVAL(params
,2);
3876 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3877 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3878 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3879 "info level (0x%x) on IPC$.\n",
3880 (unsigned int)info_level
));
3881 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3886 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3887 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3888 DEBUG(0,("call_trans2setfsinfo: encryption required "
3889 "and info level 0x%x sent.\n",
3890 (unsigned int)info_level
));
3891 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3896 switch(info_level
) {
3897 case SMB_SET_CIFS_UNIX_INFO
:
3898 if (!lp_unix_extensions()) {
3899 DEBUG(2,("call_trans2setfsinfo: "
3900 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3901 "unix extensions off\n"));
3903 NT_STATUS_INVALID_LEVEL
);
3907 /* There should be 12 bytes of capabilities set. */
3908 if (total_data
< 12) {
3911 NT_STATUS_INVALID_PARAMETER
);
3914 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3915 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3916 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3917 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3918 /* Just print these values for now. */
3919 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3920 "major = %u, minor = %u cap_low = 0x%x, "
3922 (unsigned int)xconn
->
3923 smb1
.unix_info
.client_major
,
3924 (unsigned int)xconn
->
3925 smb1
.unix_info
.client_minor
,
3926 (unsigned int)xconn
->
3927 smb1
.unix_info
.client_cap_low
,
3928 (unsigned int)xconn
->
3929 smb1
.unix_info
.client_cap_high
));
3931 /* Here is where we must switch to posix pathname processing... */
3932 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3933 lp_set_posix_pathnames();
3934 mangle_change_to_posix();
3937 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3938 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3939 /* Client that knows how to do posix locks,
3940 * but not posix open/mkdir operations. Set a
3941 * default type for read/write checks. */
3943 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3948 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3951 size_t param_len
= 0;
3952 size_t data_len
= total_data
;
3954 if (!lp_unix_extensions()) {
3957 NT_STATUS_INVALID_LEVEL
);
3961 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3964 NT_STATUS_NOT_SUPPORTED
);
3968 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3969 DEBUG( 2,("call_trans2setfsinfo: "
3970 "request transport encryption disabled"
3971 "with 'fork echo handler = yes'\n"));
3974 NT_STATUS_NOT_SUPPORTED
);
3978 DEBUG( 4,("call_trans2setfsinfo: "
3979 "request transport encryption.\n"));
3981 status
= srv_request_encryption_setup(conn
,
3982 (unsigned char **)ppdata
,
3984 (unsigned char **)pparams
,
3987 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3988 !NT_STATUS_IS_OK(status
)) {
3989 reply_nterror(req
, status
);
3993 send_trans2_replies(conn
, req
,
4001 if (NT_STATUS_IS_OK(status
)) {
4002 /* Server-side transport
4003 * encryption is now *on*. */
4004 status
= srv_encryption_start(conn
);
4005 if (!NT_STATUS_IS_OK(status
)) {
4006 char *reason
= talloc_asprintf(talloc_tos(),
4007 "Failure in setting "
4008 "up encrypted transport: %s",
4010 exit_server_cleanly(reason
);
4016 case SMB_FS_QUOTA_INFORMATION
:
4018 files_struct
*fsp
= NULL
;
4019 SMB_NTQUOTA_STRUCT quotas
;
4021 ZERO_STRUCT(quotas
);
4024 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4025 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4026 lp_servicename(talloc_tos(), SNUM(conn
)),
4027 conn
->session_info
->unix_info
->unix_name
));
4028 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4032 /* note: normally there're 48 bytes,
4033 * but we didn't use the last 6 bytes for now
4036 fsp
= file_fsp(req
, SVAL(params
,0));
4038 if (!check_fsp_ntquota_handle(conn
, req
,
4040 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4042 req
, NT_STATUS_INVALID_HANDLE
);
4046 if (total_data
< 42) {
4047 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4051 NT_STATUS_INVALID_PARAMETER
);
4055 /* unknown_1 24 NULL bytes in pdata*/
4057 /* the soft quotas 8 bytes (uint64_t)*/
4058 quotas
.softlim
= BVAL(pdata
,24);
4060 /* the hard quotas 8 bytes (uint64_t)*/
4061 quotas
.hardlim
= BVAL(pdata
,32);
4063 /* quota_flags 2 bytes **/
4064 quotas
.qflags
= SVAL(pdata
,40);
4066 /* unknown_2 6 NULL bytes follow*/
4068 /* now set the quotas */
4069 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4070 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4071 reply_nterror(req
, map_nt_error_from_unix(errno
));
4078 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4080 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4086 * sending this reply works fine,
4087 * but I'm not sure it's the same
4088 * like windows do...
4091 reply_outbuf(req
, 10, 0);
4094 #if defined(HAVE_POSIX_ACLS)
4095 /****************************************************************************
4096 Utility function to count the number of entries in a POSIX acl.
4097 ****************************************************************************/
4099 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4101 unsigned int ace_count
= 0;
4102 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4103 SMB_ACL_ENTRY_T entry
;
4105 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4107 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4108 entry_id
= SMB_ACL_NEXT_ENTRY
;
4115 /****************************************************************************
4116 Utility function to marshall a POSIX acl into wire format.
4117 ****************************************************************************/
4119 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4121 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4122 SMB_ACL_ENTRY_T entry
;
4124 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4125 SMB_ACL_TAG_T tagtype
;
4126 SMB_ACL_PERMSET_T permset
;
4127 unsigned char perms
= 0;
4128 unsigned int own_grp
;
4131 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4132 entry_id
= SMB_ACL_NEXT_ENTRY
;
4135 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4136 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4140 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4141 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4145 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4146 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4147 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4149 SCVAL(pdata
,1,perms
);
4152 case SMB_ACL_USER_OBJ
:
4153 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4154 own_grp
= (unsigned int)pst
->st_ex_uid
;
4155 SIVAL(pdata
,2,own_grp
);
4160 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4162 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4165 own_grp
= (unsigned int)*puid
;
4166 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4167 SIVAL(pdata
,2,own_grp
);
4171 case SMB_ACL_GROUP_OBJ
:
4172 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4173 own_grp
= (unsigned int)pst
->st_ex_gid
;
4174 SIVAL(pdata
,2,own_grp
);
4179 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4181 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4184 own_grp
= (unsigned int)*pgid
;
4185 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4186 SIVAL(pdata
,2,own_grp
);
4191 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4192 SIVAL(pdata
,2,0xFFFFFFFF);
4193 SIVAL(pdata
,6,0xFFFFFFFF);
4196 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4197 SIVAL(pdata
,2,0xFFFFFFFF);
4198 SIVAL(pdata
,6,0xFFFFFFFF);
4201 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4204 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4211 /****************************************************************************
4212 Store the FILE_UNIX_BASIC info.
4213 ****************************************************************************/
4215 static char *store_file_unix_basic(connection_struct
*conn
,
4218 const SMB_STRUCT_STAT
*psbuf
)
4220 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4223 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4224 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4226 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4229 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4232 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4233 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4234 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4237 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4241 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4245 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4248 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4249 devno
= psbuf
->st_ex_rdev
;
4251 devno
= psbuf
->st_ex_dev
;
4254 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4258 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4262 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4265 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4269 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4276 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4277 * the chflags(2) (or equivalent) flags.
4279 * XXX: this really should be behind the VFS interface. To do this, we would
4280 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4281 * Each VFS module could then implement its own mapping as appropriate for the
4282 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4284 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4288 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4292 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4296 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4300 { UF_HIDDEN
, EXT_HIDDEN
},
4303 /* Do not remove. We need to guarantee that this array has at least one
4304 * entry to build on HP-UX.
4310 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4311 uint32
*smb_fflags
, uint32
*smb_fmask
)
4315 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4316 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4317 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4318 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4323 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4324 const uint32 smb_fflags
,
4325 const uint32 smb_fmask
,
4328 uint32 max_fmask
= 0;
4331 *stat_fflags
= psbuf
->st_ex_flags
;
4333 /* For each flags requested in smb_fmask, check the state of the
4334 * corresponding flag in smb_fflags and set or clear the matching
4338 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4339 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4340 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4341 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4342 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4344 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4349 /* If smb_fmask is asking to set any bits that are not supported by
4350 * our flag mappings, we should fail.
4352 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4360 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4361 * of file flags and birth (create) time.
4363 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4366 const SMB_STRUCT_STAT
*psbuf
)
4368 uint32 file_flags
= 0;
4369 uint32 flags_mask
= 0;
4371 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4373 /* Create (birth) time 64 bit */
4374 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4377 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4378 SIVAL(pdata
, 0, file_flags
); /* flags */
4379 SIVAL(pdata
, 4, flags_mask
); /* mask */
4385 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4386 const struct stream_struct
*streams
,
4388 unsigned int max_data_bytes
,
4389 unsigned int *data_size
)
4392 unsigned int ofs
= 0;
4394 if (max_data_bytes
< 32) {
4395 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4398 for (i
= 0; i
< num_streams
; i
++) {
4399 unsigned int next_offset
;
4401 smb_ucs2_t
*namebuf
;
4403 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4404 streams
[i
].name
, &namelen
) ||
4407 return NT_STATUS_INVALID_PARAMETER
;
4411 * name_buf is now null-terminated, we need to marshall as not
4418 * We cannot overflow ...
4420 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4421 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4423 TALLOC_FREE(namebuf
);
4424 return STATUS_BUFFER_OVERFLOW
;
4427 SIVAL(data
, ofs
+4, namelen
);
4428 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4429 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4430 memcpy(data
+ofs
+24, namebuf
, namelen
);
4431 TALLOC_FREE(namebuf
);
4433 next_offset
= ofs
+ 24 + namelen
;
4435 if (i
== num_streams
-1) {
4436 SIVAL(data
, ofs
, 0);
4439 unsigned int align
= ndr_align_size(next_offset
, 8);
4441 if ((next_offset
+ align
) > max_data_bytes
) {
4442 DEBUG(10, ("refusing to overflow align "
4443 "reply at stream %u\n",
4445 TALLOC_FREE(namebuf
);
4446 return STATUS_BUFFER_OVERFLOW
;
4449 memset(data
+next_offset
, 0, align
);
4450 next_offset
+= align
;
4452 SIVAL(data
, ofs
, next_offset
- ofs
);
4459 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4463 return NT_STATUS_OK
;
4466 /****************************************************************************
4467 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4468 ****************************************************************************/
4470 static void call_trans2qpipeinfo(connection_struct
*conn
,
4471 struct smb_request
*req
,
4472 unsigned int tran_call
,
4473 char **pparams
, int total_params
,
4474 char **ppdata
, int total_data
,
4475 unsigned int max_data_bytes
)
4477 char *params
= *pparams
;
4478 char *pdata
= *ppdata
;
4479 unsigned int data_size
= 0;
4480 unsigned int param_size
= 2;
4485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4489 if (total_params
< 4) {
4490 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4494 fsp
= file_fsp(req
, SVAL(params
,0));
4495 if (!fsp_is_np(fsp
)) {
4496 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4500 info_level
= SVAL(params
,2);
4502 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4503 if (*pparams
== NULL
) {
4504 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4509 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4510 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4513 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4514 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4515 if (*ppdata
== NULL
) {
4516 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4521 switch (info_level
) {
4522 case SMB_FILE_STANDARD_INFORMATION
:
4524 SOFF_T(pdata
,0,4096LL);
4531 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4535 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4541 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4542 TALLOC_CTX
*mem_ctx
,
4543 uint16_t info_level
,
4545 struct smb_filename
*smb_fname
,
4546 bool delete_pending
,
4547 struct timespec write_time_ts
,
4548 struct ea_list
*ea_list
,
4549 int lock_data_count
,
4552 unsigned int max_data_bytes
,
4553 size_t *fixed_portion
,
4555 unsigned int *pdata_size
)
4557 char *pdata
= *ppdata
;
4558 char *dstart
, *dend
;
4559 unsigned int data_size
;
4560 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4561 time_t create_time
, mtime
, atime
, c_time
;
4562 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4569 uint64_t file_size
= 0;
4571 uint64_t allocation_size
= 0;
4572 uint64_t file_index
= 0;
4573 uint32_t access_mask
= 0;
4576 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4577 return NT_STATUS_INVALID_LEVEL
;
4580 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4581 smb_fname_str_dbg(smb_fname
),
4583 info_level
, max_data_bytes
));
4585 mode
= dos_mode(conn
, smb_fname
);
4586 nlink
= psbuf
->st_ex_nlink
;
4588 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4592 if ((nlink
> 0) && delete_pending
) {
4596 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4597 return NT_STATUS_INVALID_PARAMETER
;
4600 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4601 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4602 if (*ppdata
== NULL
) {
4603 return NT_STATUS_NO_MEMORY
;
4607 dend
= dstart
+ data_size
- 1;
4609 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4610 update_stat_ex_mtime(psbuf
, write_time_ts
);
4613 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4614 mtime_ts
= psbuf
->st_ex_mtime
;
4615 atime_ts
= psbuf
->st_ex_atime
;
4616 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4618 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4619 dos_filetime_timespec(&create_time_ts
);
4620 dos_filetime_timespec(&mtime_ts
);
4621 dos_filetime_timespec(&atime_ts
);
4622 dos_filetime_timespec(&ctime_ts
);
4625 create_time
= convert_timespec_to_time_t(create_time_ts
);
4626 mtime
= convert_timespec_to_time_t(mtime_ts
);
4627 atime
= convert_timespec_to_time_t(atime_ts
);
4628 c_time
= convert_timespec_to_time_t(ctime_ts
);
4630 p
= strrchr_m(smb_fname
->base_name
,'/');
4632 base_name
= smb_fname
->base_name
;
4636 /* NT expects the name to be in an exact form of the *full*
4637 filename. See the trans2 torture test */
4638 if (ISDOT(base_name
)) {
4639 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4641 return NT_STATUS_NO_MEMORY
;
4644 dos_fname
= talloc_asprintf(mem_ctx
,
4646 smb_fname
->base_name
);
4648 return NT_STATUS_NO_MEMORY
;
4650 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4651 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4652 smb_fname
->stream_name
);
4654 return NT_STATUS_NO_MEMORY
;
4658 string_replace(dos_fname
, '/', '\\');
4661 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4664 /* Do we have this path open ? */
4666 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4667 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4668 if (fsp1
&& fsp1
->initial_allocation_size
) {
4669 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4673 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4674 file_size
= get_file_size_stat(psbuf
);
4678 pos
= fsp
->fh
->position_information
;
4682 access_mask
= fsp
->access_mask
;
4684 /* GENERIC_EXECUTE mapping from Windows */
4685 access_mask
= 0x12019F;
4688 /* This should be an index number - looks like
4691 I think this causes us to fail the IFSKIT
4692 BasicFileInformationTest. -tpot */
4693 file_index
= get_FileIndex(conn
, psbuf
);
4697 switch (info_level
) {
4698 case SMB_INFO_STANDARD
:
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4701 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4702 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4703 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4704 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4705 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4706 SSVAL(pdata
,l1_attrFile
,mode
);
4709 case SMB_INFO_QUERY_EA_SIZE
:
4711 unsigned int ea_size
=
4712 estimate_ea_size(conn
, fsp
,
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4716 srv_put_dos_date2(pdata
,0,create_time
);
4717 srv_put_dos_date2(pdata
,4,atime
);
4718 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4719 SIVAL(pdata
,12,(uint32
)file_size
);
4720 SIVAL(pdata
,16,(uint32
)allocation_size
);
4721 SSVAL(pdata
,20,mode
);
4722 SIVAL(pdata
,22,ea_size
);
4726 case SMB_INFO_IS_NAME_VALID
:
4727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4729 /* os/2 needs this ? really ?*/
4730 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4732 /* This is only reached for qpathinfo */
4736 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4738 size_t total_ea_len
= 0;
4739 struct ea_list
*ea_file_list
= NULL
;
4740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4743 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4745 &total_ea_len
, &ea_file_list
);
4746 if (!NT_STATUS_IS_OK(status
)) {
4750 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4752 if (!ea_list
|| (total_ea_len
> data_size
)) {
4754 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4758 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4762 case SMB_INFO_QUERY_ALL_EAS
:
4764 /* We have data_size bytes to put EA's into. */
4765 size_t total_ea_len
= 0;
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4768 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4770 &total_ea_len
, &ea_list
);
4771 if (!NT_STATUS_IS_OK(status
)) {
4775 if (!ea_list
|| (total_ea_len
> data_size
)) {
4777 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4781 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4785 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4787 /* This is FileFullEaInformation - 0xF which maps to
4788 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4790 /* We have data_size bytes to put EA's into. */
4791 size_t total_ea_len
= 0;
4792 struct ea_list
*ea_file_list
= NULL
;
4794 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4796 /*TODO: add filtering and index handling */
4799 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4801 &total_ea_len
, &ea_file_list
);
4802 if (!NT_STATUS_IS_OK(status
)) {
4805 if (!ea_file_list
) {
4806 return NT_STATUS_NO_EAS_ON_FILE
;
4809 status
= fill_ea_chained_buffer(mem_ctx
,
4813 conn
, ea_file_list
);
4814 if (!NT_STATUS_IS_OK(status
)) {
4820 case SMB_FILE_BASIC_INFORMATION
:
4821 case SMB_QUERY_FILE_BASIC_INFO
:
4823 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4824 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4825 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4827 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4831 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4832 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4833 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4834 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4835 SIVAL(pdata
,32,mode
);
4837 DEBUG(5,("SMB_QFBI - "));
4838 DEBUG(5,("create: %s ", ctime(&create_time
)));
4839 DEBUG(5,("access: %s ", ctime(&atime
)));
4840 DEBUG(5,("write: %s ", ctime(&mtime
)));
4841 DEBUG(5,("change: %s ", ctime(&c_time
)));
4842 DEBUG(5,("mode: %x\n", mode
));
4843 *fixed_portion
= data_size
;
4846 case SMB_FILE_STANDARD_INFORMATION
:
4847 case SMB_QUERY_FILE_STANDARD_INFO
:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4851 SOFF_T(pdata
,0,allocation_size
);
4852 SOFF_T(pdata
,8,file_size
);
4853 SIVAL(pdata
,16,nlink
);
4854 SCVAL(pdata
,20,delete_pending
?1:0);
4855 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4856 SSVAL(pdata
,22,0); /* Padding. */
4857 *fixed_portion
= 24;
4860 case SMB_FILE_EA_INFORMATION
:
4861 case SMB_QUERY_FILE_EA_INFO
:
4863 unsigned int ea_size
=
4864 estimate_ea_size(conn
, fsp
, smb_fname
);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4868 SIVAL(pdata
,0,ea_size
);
4872 /* Get the 8.3 name - used if NT SMB was negotiated. */
4873 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4874 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4876 char mangled_name
[13];
4877 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4878 if (!name_to_8_3(base_name
,mangled_name
,
4879 True
,conn
->params
)) {
4880 return NT_STATUS_NO_MEMORY
;
4882 status
= srvstr_push(dstart
, flags2
,
4883 pdata
+4, mangled_name
,
4884 PTR_DIFF(dend
, pdata
+4),
4886 if (!NT_STATUS_IS_OK(status
)) {
4889 data_size
= 4 + len
;
4895 case SMB_QUERY_FILE_NAME_INFO
:
4898 this must be *exactly* right for ACLs on mapped drives to work
4900 status
= srvstr_push(dstart
, flags2
,
4902 PTR_DIFF(dend
, pdata
+4),
4904 if (!NT_STATUS_IS_OK(status
)) {
4907 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4908 data_size
= 4 + len
;
4913 case SMB_FILE_ALLOCATION_INFORMATION
:
4914 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4915 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4917 SOFF_T(pdata
,0,allocation_size
);
4920 case SMB_FILE_END_OF_FILE_INFORMATION
:
4921 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4922 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4924 SOFF_T(pdata
,0,file_size
);
4927 case SMB_QUERY_FILE_ALL_INFO
:
4928 case SMB_FILE_ALL_INFORMATION
:
4930 unsigned int ea_size
=
4931 estimate_ea_size(conn
, fsp
, smb_fname
);
4932 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4933 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4934 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4935 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4936 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4937 SIVAL(pdata
,32,mode
);
4938 SIVAL(pdata
,36,0); /* padding. */
4940 SOFF_T(pdata
,0,allocation_size
);
4941 SOFF_T(pdata
,8,file_size
);
4942 SIVAL(pdata
,16,nlink
);
4943 SCVAL(pdata
,20,delete_pending
);
4944 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4947 SIVAL(pdata
,0,ea_size
);
4948 pdata
+= 4; /* EA info */
4949 status
= srvstr_push(dstart
, flags2
,
4951 PTR_DIFF(dend
, pdata
+4),
4953 if (!NT_STATUS_IS_OK(status
)) {
4958 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4959 *fixed_portion
= 10;
4963 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4965 unsigned int ea_size
=
4966 estimate_ea_size(conn
, fsp
, smb_fname
);
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4968 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4969 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4970 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4971 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4972 SIVAL(pdata
, 0x20, mode
);
4973 SIVAL(pdata
, 0x24, 0); /* padding. */
4974 SBVAL(pdata
, 0x28, allocation_size
);
4975 SBVAL(pdata
, 0x30, file_size
);
4976 SIVAL(pdata
, 0x38, nlink
);
4977 SCVAL(pdata
, 0x3C, delete_pending
);
4978 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4979 SSVAL(pdata
, 0x3E, 0); /* padding */
4980 SBVAL(pdata
, 0x40, file_index
);
4981 SIVAL(pdata
, 0x48, ea_size
);
4982 SIVAL(pdata
, 0x4C, access_mask
);
4983 SBVAL(pdata
, 0x50, pos
);
4984 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4985 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4989 status
= srvstr_push(dstart
, flags2
,
4991 PTR_DIFF(dend
, pdata
+4),
4993 if (!NT_STATUS_IS_OK(status
)) {
4998 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4999 *fixed_portion
= 104;
5002 case SMB_FILE_INTERNAL_INFORMATION
:
5004 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5005 SBVAL(pdata
, 0, file_index
);
5010 case SMB_FILE_ACCESS_INFORMATION
:
5011 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5012 SIVAL(pdata
, 0, access_mask
);
5017 case SMB_FILE_NAME_INFORMATION
:
5018 /* Pathname with leading '\'. */
5021 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5022 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5023 SIVAL(pdata
,0,byte_len
);
5024 data_size
= 4 + byte_len
;
5028 case SMB_FILE_DISPOSITION_INFORMATION
:
5029 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5031 SCVAL(pdata
,0,delete_pending
);
5035 case SMB_FILE_POSITION_INFORMATION
:
5036 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5038 SOFF_T(pdata
,0,pos
);
5042 case SMB_FILE_MODE_INFORMATION
:
5043 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5044 SIVAL(pdata
,0,mode
);
5049 case SMB_FILE_ALIGNMENT_INFORMATION
:
5050 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5051 SIVAL(pdata
,0,0); /* No alignment needed. */
5057 * NT4 server just returns "invalid query" to this - if we try
5058 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5061 /* The first statement above is false - verified using Thursby
5062 * client against NT4 -- gcolley.
5064 case SMB_QUERY_FILE_STREAM_INFO
:
5065 case SMB_FILE_STREAM_INFORMATION
: {
5066 unsigned int num_streams
= 0;
5067 struct stream_struct
*streams
= NULL
;
5069 DEBUG(10,("smbd_do_qfilepathinfo: "
5070 "SMB_FILE_STREAM_INFORMATION\n"));
5072 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5073 return NT_STATUS_INVALID_PARAMETER
;
5076 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5077 talloc_tos(), &num_streams
, &streams
);
5079 if (!NT_STATUS_IS_OK(status
)) {
5080 DEBUG(10, ("could not get stream info: %s\n",
5081 nt_errstr(status
)));
5085 status
= marshall_stream_info(num_streams
, streams
,
5086 pdata
, max_data_bytes
,
5089 if (!NT_STATUS_IS_OK(status
)) {
5090 DEBUG(10, ("marshall_stream_info failed: %s\n",
5091 nt_errstr(status
)));
5092 TALLOC_FREE(streams
);
5096 TALLOC_FREE(streams
);
5098 *fixed_portion
= 32;
5102 case SMB_QUERY_COMPRESSION_INFO
:
5103 case SMB_FILE_COMPRESSION_INFORMATION
:
5104 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5105 SOFF_T(pdata
,0,file_size
);
5106 SIVAL(pdata
,8,0); /* ??? */
5107 SIVAL(pdata
,12,0); /* ??? */
5109 *fixed_portion
= 16;
5112 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5113 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5114 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5115 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5116 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5117 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5118 SOFF_T(pdata
,32,allocation_size
);
5119 SOFF_T(pdata
,40,file_size
);
5120 SIVAL(pdata
,48,mode
);
5121 SIVAL(pdata
,52,0); /* ??? */
5123 *fixed_portion
= 56;
5126 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5127 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5128 SIVAL(pdata
,0,mode
);
5135 * CIFS UNIX Extensions.
5138 case SMB_QUERY_FILE_UNIX_BASIC
:
5140 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5141 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5143 DEBUG(4,("smbd_do_qfilepathinfo: "
5144 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5145 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5149 case SMB_QUERY_FILE_UNIX_INFO2
:
5151 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5152 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5156 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5158 for (i
=0; i
<100; i
++)
5159 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5165 case SMB_QUERY_FILE_UNIX_LINK
:
5168 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5171 return NT_STATUS_NO_MEMORY
;
5174 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5176 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5177 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5180 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5182 link_len
= SMB_VFS_READLINK(conn
,
5183 smb_fname
->base_name
,
5185 if (link_len
== -1) {
5186 return map_nt_error_from_unix(errno
);
5188 buffer
[link_len
] = 0;
5189 status
= srvstr_push(dstart
, flags2
,
5191 PTR_DIFF(dend
, pdata
),
5192 STR_TERMINATE
, &len
);
5193 if (!NT_STATUS_IS_OK(status
)) {
5197 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5202 #if defined(HAVE_POSIX_ACLS)
5203 case SMB_QUERY_POSIX_ACL
:
5205 SMB_ACL_T file_acl
= NULL
;
5206 SMB_ACL_T def_acl
= NULL
;
5207 uint16 num_file_acls
= 0;
5208 uint16 num_def_acls
= 0;
5210 if (fsp
&& fsp
->fh
->fd
!= -1) {
5211 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5215 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5216 smb_fname
->base_name
,
5217 SMB_ACL_TYPE_ACCESS
,
5221 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5222 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5223 "not implemented on "
5224 "filesystem containing %s\n",
5225 smb_fname
->base_name
));
5226 return NT_STATUS_NOT_IMPLEMENTED
;
5229 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5230 if (fsp
&& fsp
->is_directory
) {
5232 SMB_VFS_SYS_ACL_GET_FILE(
5234 fsp
->fsp_name
->base_name
,
5235 SMB_ACL_TYPE_DEFAULT
,
5239 SMB_VFS_SYS_ACL_GET_FILE(
5241 smb_fname
->base_name
,
5242 SMB_ACL_TYPE_DEFAULT
,
5245 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5248 num_file_acls
= count_acl_entries(conn
, file_acl
);
5249 num_def_acls
= count_acl_entries(conn
, def_acl
);
5251 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5252 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5254 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5255 SMB_POSIX_ACL_HEADER_SIZE
) ));
5257 TALLOC_FREE(file_acl
);
5260 TALLOC_FREE(def_acl
);
5262 return NT_STATUS_BUFFER_TOO_SMALL
;
5265 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5266 SSVAL(pdata
,2,num_file_acls
);
5267 SSVAL(pdata
,4,num_def_acls
);
5268 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5270 TALLOC_FREE(file_acl
);
5273 TALLOC_FREE(def_acl
);
5275 return NT_STATUS_INTERNAL_ERROR
;
5277 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5279 TALLOC_FREE(file_acl
);
5282 TALLOC_FREE(def_acl
);
5284 return NT_STATUS_INTERNAL_ERROR
;
5288 TALLOC_FREE(file_acl
);
5291 TALLOC_FREE(def_acl
);
5293 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5299 case SMB_QUERY_POSIX_LOCK
:
5304 enum brl_type lock_type
;
5306 /* We need an open file with a real fd for this. */
5307 if (!fsp
|| fsp
->fh
->fd
== -1) {
5308 return NT_STATUS_INVALID_LEVEL
;
5311 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5312 return NT_STATUS_INVALID_PARAMETER
;
5315 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5316 case POSIX_LOCK_TYPE_READ
:
5317 lock_type
= READ_LOCK
;
5319 case POSIX_LOCK_TYPE_WRITE
:
5320 lock_type
= WRITE_LOCK
;
5322 case POSIX_LOCK_TYPE_UNLOCK
:
5324 /* There's no point in asking for an unlock... */
5325 return NT_STATUS_INVALID_PARAMETER
;
5328 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5329 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5330 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5332 status
= query_lock(fsp
,
5339 if (ERROR_WAS_LOCK_DENIED(status
)) {
5340 /* Here we need to report who has it locked... */
5341 data_size
= POSIX_LOCK_DATA_SIZE
;
5343 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5344 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5345 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5346 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5347 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5349 } else if (NT_STATUS_IS_OK(status
)) {
5350 /* For success we just return a copy of what we sent
5351 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5352 data_size
= POSIX_LOCK_DATA_SIZE
;
5353 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5354 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5362 return NT_STATUS_INVALID_LEVEL
;
5365 *pdata_size
= data_size
;
5366 return NT_STATUS_OK
;
5369 /****************************************************************************
5370 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5371 file name or file id).
5372 ****************************************************************************/
5374 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5375 struct smb_request
*req
,
5376 unsigned int tran_call
,
5377 char **pparams
, int total_params
,
5378 char **ppdata
, int total_data
,
5379 unsigned int max_data_bytes
)
5381 char *params
= *pparams
;
5382 char *pdata
= *ppdata
;
5384 unsigned int data_size
= 0;
5385 unsigned int param_size
= 2;
5386 struct smb_filename
*smb_fname
= NULL
;
5387 bool delete_pending
= False
;
5388 struct timespec write_time_ts
;
5389 files_struct
*fsp
= NULL
;
5390 struct file_id fileid
;
5391 struct ea_list
*ea_list
= NULL
;
5392 int lock_data_count
= 0;
5393 char *lock_data
= NULL
;
5394 size_t fixed_portion
;
5395 NTSTATUS status
= NT_STATUS_OK
;
5398 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5402 ZERO_STRUCT(write_time_ts
);
5404 if (tran_call
== TRANSACT2_QFILEINFO
) {
5405 if (total_params
< 4) {
5406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5411 call_trans2qpipeinfo(conn
, req
, tran_call
,
5412 pparams
, total_params
,
5418 fsp
= file_fsp(req
, SVAL(params
,0));
5419 info_level
= SVAL(params
,2);
5421 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5423 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5424 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5428 /* Initial check for valid fsp ptr. */
5429 if (!check_fsp_open(conn
, req
, fsp
)) {
5433 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5434 if (smb_fname
== NULL
) {
5435 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5439 if(fsp
->fake_file_handle
) {
5441 * This is actually for the QUOTA_FAKE_FILE --metze
5444 /* We know this name is ok, it's already passed the checks. */
5446 } else if(fsp
->fh
->fd
== -1) {
5448 * This is actually a QFILEINFO on a directory
5449 * handle (returned from an NT SMB). NT5.0 seems
5450 * to do this call. JRA.
5453 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5454 /* Always do lstat for UNIX calls. */
5455 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5456 DEBUG(3,("call_trans2qfilepathinfo: "
5457 "SMB_VFS_LSTAT of %s failed "
5459 smb_fname_str_dbg(smb_fname
),
5462 map_nt_error_from_unix(errno
));
5465 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5466 DEBUG(3,("call_trans2qfilepathinfo: "
5467 "SMB_VFS_STAT of %s failed (%s)\n",
5468 smb_fname_str_dbg(smb_fname
),
5471 map_nt_error_from_unix(errno
));
5475 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5476 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5479 * Original code - this is an open file.
5481 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5482 DEBUG(3, ("fstat of %s failed (%s)\n",
5483 fsp_fnum_dbg(fsp
), strerror(errno
)));
5485 map_nt_error_from_unix(errno
));
5488 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5489 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5495 uint32_t ucf_flags
= 0;
5498 if (total_params
< 7) {
5499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5503 info_level
= SVAL(params
,0);
5505 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5507 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5508 if (!lp_unix_extensions()) {
5509 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5512 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5513 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5514 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5515 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5519 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5521 STR_TERMINATE
, &status
);
5522 if (!NT_STATUS_IS_OK(status
)) {
5523 reply_nterror(req
, status
);
5527 status
= filename_convert(req
,
5529 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5534 if (!NT_STATUS_IS_OK(status
)) {
5535 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5536 reply_botherror(req
,
5537 NT_STATUS_PATH_NOT_COVERED
,
5538 ERRSRV
, ERRbadpath
);
5541 reply_nterror(req
, status
);
5545 /* If this is a stream, check if there is a delete_pending. */
5546 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5547 && is_ntfs_stream_smb_fname(smb_fname
)) {
5548 struct smb_filename
*smb_fname_base
;
5550 /* Create an smb_filename with stream_name == NULL. */
5551 smb_fname_base
= synthetic_smb_fname(
5552 talloc_tos(), smb_fname
->base_name
,
5554 if (smb_fname_base
== NULL
) {
5555 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5559 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5560 /* Always do lstat for UNIX calls. */
5561 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5562 DEBUG(3,("call_trans2qfilepathinfo: "
5563 "SMB_VFS_LSTAT of %s failed "
5565 smb_fname_str_dbg(smb_fname_base
),
5567 TALLOC_FREE(smb_fname_base
);
5569 map_nt_error_from_unix(errno
));
5573 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5574 DEBUG(3,("call_trans2qfilepathinfo: "
5575 "fileinfo of %s failed "
5577 smb_fname_str_dbg(smb_fname_base
),
5579 TALLOC_FREE(smb_fname_base
);
5581 map_nt_error_from_unix(errno
));
5586 status
= file_name_hash(conn
,
5587 smb_fname_str_dbg(smb_fname_base
),
5589 if (!NT_STATUS_IS_OK(status
)) {
5590 TALLOC_FREE(smb_fname_base
);
5591 reply_nterror(req
, status
);
5595 fileid
= vfs_file_id_from_sbuf(conn
,
5596 &smb_fname_base
->st
);
5597 TALLOC_FREE(smb_fname_base
);
5598 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5599 if (delete_pending
) {
5600 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5605 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5606 /* Always do lstat for UNIX calls. */
5607 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5608 DEBUG(3,("call_trans2qfilepathinfo: "
5609 "SMB_VFS_LSTAT of %s failed (%s)\n",
5610 smb_fname_str_dbg(smb_fname
),
5613 map_nt_error_from_unix(errno
));
5618 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5619 DEBUG(3,("call_trans2qfilepathinfo: "
5620 "SMB_VFS_STAT of %s failed (%s)\n",
5621 smb_fname_str_dbg(smb_fname
),
5624 map_nt_error_from_unix(errno
));
5629 status
= file_name_hash(conn
,
5630 smb_fname_str_dbg(smb_fname
),
5632 if (!NT_STATUS_IS_OK(status
)) {
5633 reply_nterror(req
, status
);
5637 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5638 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5639 if (delete_pending
) {
5640 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5645 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5646 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5648 info_level
,tran_call
,total_data
));
5650 /* Pull out any data sent here before we realloc. */
5651 switch (info_level
) {
5652 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5654 /* Pull any EA list from the data portion. */
5657 if (total_data
< 4) {
5659 req
, NT_STATUS_INVALID_PARAMETER
);
5662 ea_size
= IVAL(pdata
,0);
5664 if (total_data
> 0 && ea_size
!= total_data
) {
5665 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5666 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5668 req
, NT_STATUS_INVALID_PARAMETER
);
5672 if (!lp_ea_support(SNUM(conn
))) {
5673 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5677 /* Pull out the list of names. */
5678 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5681 req
, NT_STATUS_INVALID_PARAMETER
);
5687 case SMB_QUERY_POSIX_LOCK
:
5689 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5690 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5694 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5696 req
, NT_STATUS_INVALID_PARAMETER
);
5700 /* Copy the lock range data. */
5701 lock_data
= (char *)talloc_memdup(
5702 req
, pdata
, total_data
);
5704 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5707 lock_data_count
= total_data
;
5713 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5714 if (*pparams
== NULL
) {
5715 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5722 * draft-leach-cifs-v1-spec-02.txt
5723 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5726 * The requested information is placed in the Data portion of the
5727 * transaction response. For the information levels greater than 0x100,
5728 * the transaction response has 1 parameter word which should be
5729 * ignored by the client.
5731 * However Windows only follows this rule for the IS_NAME_VALID call.
5733 switch (info_level
) {
5734 case SMB_INFO_IS_NAME_VALID
:
5739 if ((info_level
& 0xFF00) == 0xFF00) {
5741 * We use levels that start with 0xFF00
5742 * internally to represent SMB2 specific levels
5744 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5748 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5750 delete_pending
, write_time_ts
,
5752 lock_data_count
, lock_data
,
5753 req
->flags2
, max_data_bytes
,
5755 ppdata
, &data_size
);
5756 if (!NT_STATUS_IS_OK(status
)) {
5757 reply_nterror(req
, status
);
5760 if (fixed_portion
> max_data_bytes
) {
5761 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5765 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5771 /****************************************************************************
5772 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5774 ****************************************************************************/
5776 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5777 connection_struct
*conn
,
5778 struct smb_request
*req
,
5779 bool overwrite_if_exists
,
5780 const struct smb_filename
*smb_fname_old
,
5781 struct smb_filename
*smb_fname_new
)
5783 NTSTATUS status
= NT_STATUS_OK
;
5785 /* source must already exist. */
5786 if (!VALID_STAT(smb_fname_old
->st
)) {
5787 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5790 if (VALID_STAT(smb_fname_new
->st
)) {
5791 if (overwrite_if_exists
) {
5792 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5793 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5795 status
= unlink_internals(conn
,
5797 FILE_ATTRIBUTE_NORMAL
,
5800 if (!NT_STATUS_IS_OK(status
)) {
5804 /* Disallow if newname already exists. */
5805 return NT_STATUS_OBJECT_NAME_COLLISION
;
5809 /* No links from a directory. */
5810 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5811 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5814 /* Setting a hardlink to/from a stream isn't currently supported. */
5815 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5816 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5817 return NT_STATUS_INVALID_PARAMETER
;
5820 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5821 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5823 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5824 smb_fname_new
->base_name
) != 0) {
5825 status
= map_nt_error_from_unix(errno
);
5826 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5827 nt_errstr(status
), smb_fname_old
->base_name
,
5828 smb_fname_new
->base_name
));
5833 /****************************************************************************
5834 Deal with setting the time from any of the setfilepathinfo functions.
5835 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5836 calling this function.
5837 ****************************************************************************/
5839 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5841 const struct smb_filename
*smb_fname
,
5842 struct smb_file_time
*ft
,
5843 bool setting_write_time
)
5845 struct smb_filename smb_fname_base
;
5847 FILE_NOTIFY_CHANGE_LAST_ACCESS
5848 |FILE_NOTIFY_CHANGE_LAST_WRITE
5849 |FILE_NOTIFY_CHANGE_CREATION
;
5851 if (!VALID_STAT(smb_fname
->st
)) {
5852 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5855 /* get some defaults (no modifications) if any info is zero or -1. */
5856 if (null_timespec(ft
->create_time
)) {
5857 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5860 if (null_timespec(ft
->atime
)) {
5861 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5864 if (null_timespec(ft
->mtime
)) {
5865 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5868 if (!setting_write_time
) {
5869 /* ft->mtime comes from change time, not write time. */
5870 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5873 /* Ensure the resolution is the correct for
5874 * what we can store on this filesystem. */
5876 round_timespec(conn
->ts_res
, &ft
->create_time
);
5877 round_timespec(conn
->ts_res
, &ft
->ctime
);
5878 round_timespec(conn
->ts_res
, &ft
->atime
);
5879 round_timespec(conn
->ts_res
, &ft
->mtime
);
5881 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5882 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5883 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5884 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5885 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5886 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5887 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5888 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5890 if (setting_write_time
) {
5892 * This was a Windows setfileinfo on an open file.
5893 * NT does this a lot. We also need to
5894 * set the time here, as it can be read by
5895 * FindFirst/FindNext and with the patch for bug #2045
5896 * in smbd/fileio.c it ensures that this timestamp is
5897 * kept sticky even after a write. We save the request
5898 * away and will set it on file close and after a write. JRA.
5901 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5902 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5905 if (fsp
->base_fsp
) {
5906 set_sticky_write_time_fsp(fsp
->base_fsp
,
5909 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5912 set_sticky_write_time_path(
5913 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5918 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5920 /* Always call ntimes on the base, even if a stream was passed in. */
5921 smb_fname_base
= *smb_fname
;
5922 smb_fname_base
.stream_name
= NULL
;
5924 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5925 return map_nt_error_from_unix(errno
);
5928 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5929 smb_fname
->base_name
);
5930 return NT_STATUS_OK
;
5933 /****************************************************************************
5934 Deal with setting the dosmode from any of the setfilepathinfo functions.
5935 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5936 done before calling this function.
5937 ****************************************************************************/
5939 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5940 const struct smb_filename
*smb_fname
,
5943 struct smb_filename
*smb_fname_base
;
5946 if (!VALID_STAT(smb_fname
->st
)) {
5947 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5950 /* Always operate on the base_name, even if a stream was passed in. */
5951 smb_fname_base
= synthetic_smb_fname(
5952 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5953 if (smb_fname_base
== NULL
) {
5954 return NT_STATUS_NO_MEMORY
;
5958 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5959 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5961 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5965 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5967 /* check the mode isn't different, before changing it */
5968 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5969 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5970 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5971 (unsigned int)dosmode
));
5973 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5975 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5977 smb_fname_str_dbg(smb_fname_base
),
5979 status
= map_nt_error_from_unix(errno
);
5983 status
= NT_STATUS_OK
;
5985 TALLOC_FREE(smb_fname_base
);
5989 /****************************************************************************
5990 Deal with setting the size from any of the setfilepathinfo functions.
5991 ****************************************************************************/
5993 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5994 struct smb_request
*req
,
5996 const struct smb_filename
*smb_fname
,
5997 const SMB_STRUCT_STAT
*psbuf
,
5999 bool fail_after_createfile
)
6001 NTSTATUS status
= NT_STATUS_OK
;
6002 struct smb_filename
*smb_fname_tmp
= NULL
;
6003 files_struct
*new_fsp
= NULL
;
6005 if (!VALID_STAT(*psbuf
)) {
6006 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6009 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6011 if (size
== get_file_size_stat(psbuf
)) {
6012 return NT_STATUS_OK
;
6015 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6016 smb_fname_str_dbg(smb_fname
), (double)size
));
6018 if (fsp
&& fsp
->fh
->fd
!= -1) {
6019 /* Handle based call. */
6020 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6021 return NT_STATUS_ACCESS_DENIED
;
6024 if (vfs_set_filelen(fsp
, size
) == -1) {
6025 return map_nt_error_from_unix(errno
);
6027 trigger_write_time_update_immediate(fsp
);
6028 return NT_STATUS_OK
;
6031 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6032 if (smb_fname_tmp
== NULL
) {
6033 return NT_STATUS_NO_MEMORY
;
6036 smb_fname_tmp
->st
= *psbuf
;
6038 status
= SMB_VFS_CREATE_FILE(
6041 0, /* root_dir_fid */
6042 smb_fname_tmp
, /* fname */
6043 FILE_WRITE_DATA
, /* access_mask */
6044 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6046 FILE_OPEN
, /* create_disposition*/
6047 0, /* create_options */
6048 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6049 0, /* oplock_request */
6051 0, /* allocation_size */
6052 0, /* private_flags */
6055 &new_fsp
, /* result */
6057 NULL
, NULL
); /* create context */
6059 TALLOC_FREE(smb_fname_tmp
);
6061 if (!NT_STATUS_IS_OK(status
)) {
6062 /* NB. We check for open_was_deferred in the caller. */
6066 /* See RAW-SFILEINFO-END-OF-FILE */
6067 if (fail_after_createfile
) {
6068 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6069 return NT_STATUS_INVALID_LEVEL
;
6072 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6073 status
= map_nt_error_from_unix(errno
);
6074 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6078 trigger_write_time_update_immediate(new_fsp
);
6079 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6080 return NT_STATUS_OK
;
6083 /****************************************************************************
6084 Deal with SMB_INFO_SET_EA.
6085 ****************************************************************************/
6087 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6091 const struct smb_filename
*smb_fname
)
6093 struct ea_list
*ea_list
= NULL
;
6094 TALLOC_CTX
*ctx
= NULL
;
6095 NTSTATUS status
= NT_STATUS_OK
;
6097 if (total_data
< 10) {
6099 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6100 length. They seem to have no effect. Bug #3212. JRA */
6102 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6103 /* We're done. We only get EA info in this call. */
6104 return NT_STATUS_OK
;
6107 return NT_STATUS_INVALID_PARAMETER
;
6110 if (IVAL(pdata
,0) > total_data
) {
6111 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6112 IVAL(pdata
,0), (unsigned int)total_data
));
6113 return NT_STATUS_INVALID_PARAMETER
;
6117 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6119 return NT_STATUS_INVALID_PARAMETER
;
6122 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6127 /****************************************************************************
6128 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6129 ****************************************************************************/
6131 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6136 struct ea_list
*ea_list
= NULL
;
6140 return NT_STATUS_INVALID_HANDLE
;
6143 if (!lp_ea_support(SNUM(conn
))) {
6144 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6145 "EA's not supported.\n",
6146 (unsigned int)total_data
));
6147 return NT_STATUS_EAS_NOT_SUPPORTED
;
6150 if (total_data
< 10) {
6151 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6153 (unsigned int)total_data
));
6154 return NT_STATUS_INVALID_PARAMETER
;
6157 ea_list
= read_nttrans_ea_list(talloc_tos(),
6162 return NT_STATUS_INVALID_PARAMETER
;
6165 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6167 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6168 smb_fname_str_dbg(fsp
->fsp_name
),
6169 nt_errstr(status
) ));
6175 /****************************************************************************
6176 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6177 ****************************************************************************/
6179 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6183 struct smb_filename
*smb_fname
)
6185 NTSTATUS status
= NT_STATUS_OK
;
6186 bool delete_on_close
;
6189 if (total_data
< 1) {
6190 return NT_STATUS_INVALID_PARAMETER
;
6194 return NT_STATUS_INVALID_HANDLE
;
6197 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6198 dosmode
= dos_mode(conn
, smb_fname
);
6200 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6201 "delete_on_close = %u\n",
6202 smb_fname_str_dbg(smb_fname
),
6203 (unsigned int)dosmode
,
6204 (unsigned int)delete_on_close
));
6206 if (delete_on_close
) {
6207 status
= can_set_delete_on_close(fsp
, dosmode
);
6208 if (!NT_STATUS_IS_OK(status
)) {
6213 /* The set is across all open files on this dev/inode pair. */
6214 if (!set_delete_on_close(fsp
, delete_on_close
,
6215 conn
->session_info
->security_token
,
6216 conn
->session_info
->unix_token
)) {
6217 return NT_STATUS_ACCESS_DENIED
;
6219 return NT_STATUS_OK
;
6222 /****************************************************************************
6223 Deal with SMB_FILE_POSITION_INFORMATION.
6224 ****************************************************************************/
6226 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6231 uint64_t position_information
;
6233 if (total_data
< 8) {
6234 return NT_STATUS_INVALID_PARAMETER
;
6238 /* Ignore on pathname based set. */
6239 return NT_STATUS_OK
;
6242 position_information
= (uint64_t)IVAL(pdata
,0);
6243 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6245 DEBUG(10,("smb_file_position_information: Set file position "
6246 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6247 (double)position_information
));
6248 fsp
->fh
->position_information
= position_information
;
6249 return NT_STATUS_OK
;
6252 /****************************************************************************
6253 Deal with SMB_FILE_MODE_INFORMATION.
6254 ****************************************************************************/
6256 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6262 if (total_data
< 4) {
6263 return NT_STATUS_INVALID_PARAMETER
;
6265 mode
= IVAL(pdata
,0);
6266 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6267 return NT_STATUS_INVALID_PARAMETER
;
6269 return NT_STATUS_OK
;
6272 /****************************************************************************
6273 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6274 ****************************************************************************/
6276 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6277 struct smb_request
*req
,
6280 const struct smb_filename
*smb_fname
)
6282 char *link_target
= NULL
;
6283 const char *newname
= smb_fname
->base_name
;
6284 TALLOC_CTX
*ctx
= talloc_tos();
6286 /* Set a symbolic link. */
6287 /* Don't allow this if follow links is false. */
6289 if (total_data
== 0) {
6290 return NT_STATUS_INVALID_PARAMETER
;
6293 if (!lp_follow_symlinks(SNUM(conn
))) {
6294 return NT_STATUS_ACCESS_DENIED
;
6297 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6298 total_data
, STR_TERMINATE
);
6301 return NT_STATUS_INVALID_PARAMETER
;
6304 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6305 newname
, link_target
));
6307 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6308 return map_nt_error_from_unix(errno
);
6311 return NT_STATUS_OK
;
6314 /****************************************************************************
6315 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6316 ****************************************************************************/
6318 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6319 struct smb_request
*req
,
6320 const char *pdata
, int total_data
,
6321 struct smb_filename
*smb_fname_new
)
6323 char *oldname
= NULL
;
6324 struct smb_filename
*smb_fname_old
= NULL
;
6325 TALLOC_CTX
*ctx
= talloc_tos();
6326 NTSTATUS status
= NT_STATUS_OK
;
6328 /* Set a hard link. */
6329 if (total_data
== 0) {
6330 return NT_STATUS_INVALID_PARAMETER
;
6333 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6334 total_data
, STR_TERMINATE
, &status
);
6335 if (!NT_STATUS_IS_OK(status
)) {
6339 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6340 smb_fname_str_dbg(smb_fname_new
), oldname
));
6342 status
= filename_convert(ctx
,
6344 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6349 if (!NT_STATUS_IS_OK(status
)) {
6353 return hardlink_internals(ctx
, conn
, req
, false,
6354 smb_fname_old
, smb_fname_new
);
6357 /****************************************************************************
6358 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6359 ****************************************************************************/
6361 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6362 struct smb_request
*req
,
6366 struct smb_filename
*smb_fname_src
)
6370 char *newname
= NULL
;
6371 struct smb_filename
*smb_fname_dst
= NULL
;
6372 NTSTATUS status
= NT_STATUS_OK
;
6373 TALLOC_CTX
*ctx
= talloc_tos();
6376 return NT_STATUS_INVALID_HANDLE
;
6379 if (total_data
< 20) {
6380 return NT_STATUS_INVALID_PARAMETER
;
6383 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6384 len
= IVAL(pdata
,16);
6386 if (len
> (total_data
- 20) || (len
== 0)) {
6387 return NT_STATUS_INVALID_PARAMETER
;
6390 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6391 &pdata
[20], len
, STR_TERMINATE
,
6393 if (!NT_STATUS_IS_OK(status
)) {
6397 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6400 status
= filename_convert(ctx
,
6402 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6407 if (!NT_STATUS_IS_OK(status
)) {
6411 if (fsp
->base_fsp
) {
6412 /* newname must be a stream name. */
6413 if (newname
[0] != ':') {
6414 return NT_STATUS_NOT_SUPPORTED
;
6417 /* Create an smb_fname to call rename_internals_fsp() with. */
6418 smb_fname_dst
= synthetic_smb_fname(
6419 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6421 if (smb_fname_dst
== NULL
) {
6422 status
= NT_STATUS_NO_MEMORY
;
6427 * Set the original last component, since
6428 * rename_internals_fsp() requires it.
6430 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6432 if (smb_fname_dst
->original_lcomp
== NULL
) {
6433 status
= NT_STATUS_NO_MEMORY
;
6439 DEBUG(10,("smb2_file_rename_information: "
6440 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6441 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6442 smb_fname_str_dbg(smb_fname_dst
)));
6443 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6444 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6448 TALLOC_FREE(smb_fname_dst
);
6452 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6453 struct smb_request
*req
,
6457 struct smb_filename
*smb_fname_src
)
6461 char *newname
= NULL
;
6462 struct smb_filename
*smb_fname_dst
= NULL
;
6463 NTSTATUS status
= NT_STATUS_OK
;
6464 TALLOC_CTX
*ctx
= talloc_tos();
6467 return NT_STATUS_INVALID_HANDLE
;
6470 if (total_data
< 20) {
6471 return NT_STATUS_INVALID_PARAMETER
;
6474 overwrite
= (CVAL(pdata
,0) ? true : false);
6475 len
= IVAL(pdata
,16);
6477 if (len
> (total_data
- 20) || (len
== 0)) {
6478 return NT_STATUS_INVALID_PARAMETER
;
6481 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6482 &pdata
[20], len
, STR_TERMINATE
,
6484 if (!NT_STATUS_IS_OK(status
)) {
6488 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6491 status
= filename_convert(ctx
,
6493 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6498 if (!NT_STATUS_IS_OK(status
)) {
6502 if (fsp
->base_fsp
) {
6503 /* No stream names. */
6504 return NT_STATUS_NOT_SUPPORTED
;
6507 DEBUG(10,("smb_file_link_information: "
6508 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6509 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6510 smb_fname_str_dbg(smb_fname_dst
)));
6511 status
= hardlink_internals(ctx
,
6518 TALLOC_FREE(smb_fname_dst
);
6522 /****************************************************************************
6523 Deal with SMB_FILE_RENAME_INFORMATION.
6524 ****************************************************************************/
6526 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6527 struct smb_request
*req
,
6531 struct smb_filename
*smb_fname_src
)
6536 char *newname
= NULL
;
6537 struct smb_filename
*smb_fname_dst
= NULL
;
6538 bool dest_has_wcard
= False
;
6539 NTSTATUS status
= NT_STATUS_OK
;
6541 TALLOC_CTX
*ctx
= talloc_tos();
6543 if (total_data
< 13) {
6544 return NT_STATUS_INVALID_PARAMETER
;
6547 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6548 root_fid
= IVAL(pdata
,4);
6549 len
= IVAL(pdata
,8);
6551 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6552 return NT_STATUS_INVALID_PARAMETER
;
6555 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6558 if (!NT_STATUS_IS_OK(status
)) {
6562 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6565 status
= resolve_dfspath_wcard(ctx
, conn
,
6566 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6569 !conn
->sconn
->using_smb2
,
6572 if (!NT_STATUS_IS_OK(status
)) {
6576 /* Check the new name has no '/' characters. */
6577 if (strchr_m(newname
, '/')) {
6578 return NT_STATUS_NOT_SUPPORTED
;
6581 if (fsp
&& fsp
->base_fsp
) {
6582 /* newname must be a stream name. */
6583 if (newname
[0] != ':') {
6584 return NT_STATUS_NOT_SUPPORTED
;
6587 /* Create an smb_fname to call rename_internals_fsp() with. */
6588 smb_fname_dst
= synthetic_smb_fname(
6589 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6591 if (smb_fname_dst
== NULL
) {
6592 status
= NT_STATUS_NO_MEMORY
;
6597 * Set the original last component, since
6598 * rename_internals_fsp() requires it.
6600 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6602 if (smb_fname_dst
->original_lcomp
== NULL
) {
6603 status
= NT_STATUS_NO_MEMORY
;
6609 * Build up an smb_fname_dst based on the filename passed in.
6610 * We basically just strip off the last component, and put on
6611 * the newname instead.
6613 char *base_name
= NULL
;
6615 /* newname must *not* be a stream name. */
6616 if (newname
[0] == ':') {
6617 return NT_STATUS_NOT_SUPPORTED
;
6621 * Strip off the last component (filename) of the path passed
6624 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6626 return NT_STATUS_NO_MEMORY
;
6628 p
= strrchr_m(base_name
, '/');
6632 base_name
= talloc_strdup(ctx
, "");
6634 return NT_STATUS_NO_MEMORY
;
6637 /* Append the new name. */
6638 base_name
= talloc_asprintf_append(base_name
,
6642 return NT_STATUS_NO_MEMORY
;
6645 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6648 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6651 /* If an error we expect this to be
6652 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6654 if (!NT_STATUS_IS_OK(status
)) {
6655 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6659 /* Create an smb_fname to call rename_internals_fsp() */
6660 smb_fname_dst
= synthetic_smb_fname(
6661 ctx
, base_name
, NULL
, NULL
);
6662 if (smb_fname_dst
== NULL
) {
6663 status
= NT_STATUS_NO_MEMORY
;
6670 DEBUG(10,("smb_file_rename_information: "
6671 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6672 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6673 smb_fname_str_dbg(smb_fname_dst
)));
6674 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6677 DEBUG(10,("smb_file_rename_information: "
6678 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6679 smb_fname_str_dbg(smb_fname_src
),
6680 smb_fname_str_dbg(smb_fname_dst
)));
6681 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6682 smb_fname_dst
, 0, overwrite
, false,
6684 FILE_WRITE_ATTRIBUTES
);
6687 TALLOC_FREE(smb_fname_dst
);
6691 /****************************************************************************
6692 Deal with SMB_SET_POSIX_ACL.
6693 ****************************************************************************/
6695 #if defined(HAVE_POSIX_ACLS)
6696 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6700 const struct smb_filename
*smb_fname
)
6702 uint16 posix_acl_version
;
6703 uint16 num_file_acls
;
6704 uint16 num_def_acls
;
6705 bool valid_file_acls
= True
;
6706 bool valid_def_acls
= True
;
6708 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6709 return NT_STATUS_INVALID_PARAMETER
;
6711 posix_acl_version
= SVAL(pdata
,0);
6712 num_file_acls
= SVAL(pdata
,2);
6713 num_def_acls
= SVAL(pdata
,4);
6715 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6716 valid_file_acls
= False
;
6720 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6721 valid_def_acls
= False
;
6725 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6726 return NT_STATUS_INVALID_PARAMETER
;
6729 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6730 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6731 return NT_STATUS_INVALID_PARAMETER
;
6734 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6735 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6736 (unsigned int)num_file_acls
,
6737 (unsigned int)num_def_acls
));
6739 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6740 smb_fname
->base_name
, num_file_acls
,
6741 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6742 return map_nt_error_from_unix(errno
);
6745 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6746 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6747 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6748 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6749 return map_nt_error_from_unix(errno
);
6751 return NT_STATUS_OK
;
6755 /****************************************************************************
6756 Deal with SMB_SET_POSIX_LOCK.
6757 ****************************************************************************/
6759 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6760 struct smb_request
*req
,
6768 bool blocking_lock
= False
;
6769 enum brl_type lock_type
;
6771 NTSTATUS status
= NT_STATUS_OK
;
6773 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6774 return NT_STATUS_INVALID_HANDLE
;
6777 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6778 return NT_STATUS_INVALID_PARAMETER
;
6781 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6782 case POSIX_LOCK_TYPE_READ
:
6783 lock_type
= READ_LOCK
;
6785 case POSIX_LOCK_TYPE_WRITE
:
6786 /* Return the right POSIX-mappable error code for files opened read-only. */
6787 if (!fsp
->can_write
) {
6788 return NT_STATUS_INVALID_HANDLE
;
6790 lock_type
= WRITE_LOCK
;
6792 case POSIX_LOCK_TYPE_UNLOCK
:
6793 lock_type
= UNLOCK_LOCK
;
6796 return NT_STATUS_INVALID_PARAMETER
;
6799 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6800 blocking_lock
= False
;
6801 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6802 blocking_lock
= True
;
6804 return NT_STATUS_INVALID_PARAMETER
;
6807 if (!lp_blocking_locks(SNUM(conn
))) {
6808 blocking_lock
= False
;
6811 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6812 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6813 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6814 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6815 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6817 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6818 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6820 (unsigned int)lock_type
,
6821 (unsigned long long)smblctx
,
6825 if (lock_type
== UNLOCK_LOCK
) {
6826 status
= do_unlock(req
->sconn
->msg_ctx
,
6833 uint64_t block_smblctx
;
6835 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6846 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6848 * A blocking lock was requested. Package up
6849 * this smb into a queued request and push it
6850 * onto the blocking lock queue.
6852 if(push_blocking_lock_request(br_lck
,
6855 -1, /* infinite timeout. */
6863 TALLOC_FREE(br_lck
);
6867 TALLOC_FREE(br_lck
);
6873 /****************************************************************************
6874 Deal with SMB_SET_FILE_BASIC_INFO.
6875 ****************************************************************************/
6877 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6881 const struct smb_filename
*smb_fname
)
6883 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6884 struct smb_file_time ft
;
6886 NTSTATUS status
= NT_STATUS_OK
;
6890 if (total_data
< 36) {
6891 return NT_STATUS_INVALID_PARAMETER
;
6894 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6895 if (!NT_STATUS_IS_OK(status
)) {
6899 /* Set the attributes */
6900 dosmode
= IVAL(pdata
,32);
6901 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6902 if (!NT_STATUS_IS_OK(status
)) {
6907 ft
.create_time
= interpret_long_date(pdata
);
6910 ft
.atime
= interpret_long_date(pdata
+8);
6913 ft
.mtime
= interpret_long_date(pdata
+16);
6916 ft
.ctime
= interpret_long_date(pdata
+24);
6918 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6919 smb_fname_str_dbg(smb_fname
)));
6921 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6925 /****************************************************************************
6926 Deal with SMB_INFO_STANDARD.
6927 ****************************************************************************/
6929 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6933 const struct smb_filename
*smb_fname
)
6936 struct smb_file_time ft
;
6940 if (total_data
< 12) {
6941 return NT_STATUS_INVALID_PARAMETER
;
6945 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6947 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6949 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6951 DEBUG(10,("smb_set_info_standard: file %s\n",
6952 smb_fname_str_dbg(smb_fname
)));
6954 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6955 if (!NT_STATUS_IS_OK(status
)) {
6959 return smb_set_file_time(conn
,
6966 /****************************************************************************
6967 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6968 ****************************************************************************/
6970 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6971 struct smb_request
*req
,
6975 struct smb_filename
*smb_fname
)
6977 uint64_t allocation_size
= 0;
6978 NTSTATUS status
= NT_STATUS_OK
;
6979 files_struct
*new_fsp
= NULL
;
6981 if (!VALID_STAT(smb_fname
->st
)) {
6982 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6985 if (total_data
< 8) {
6986 return NT_STATUS_INVALID_PARAMETER
;
6989 allocation_size
= (uint64_t)IVAL(pdata
,0);
6990 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6991 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6992 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6993 (double)allocation_size
));
6995 if (allocation_size
) {
6996 allocation_size
= smb_roundup(conn
, allocation_size
);
6999 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7000 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7001 (double)allocation_size
));
7003 if (fsp
&& fsp
->fh
->fd
!= -1) {
7004 /* Open file handle. */
7005 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7006 return NT_STATUS_ACCESS_DENIED
;
7009 /* Only change if needed. */
7010 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7011 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7012 return map_nt_error_from_unix(errno
);
7015 /* But always update the time. */
7017 * This is equivalent to a write. Ensure it's seen immediately
7018 * if there are no pending writes.
7020 trigger_write_time_update_immediate(fsp
);
7021 return NT_STATUS_OK
;
7024 /* Pathname or stat or directory file. */
7025 status
= SMB_VFS_CREATE_FILE(
7028 0, /* root_dir_fid */
7029 smb_fname
, /* fname */
7030 FILE_WRITE_DATA
, /* access_mask */
7031 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7033 FILE_OPEN
, /* create_disposition*/
7034 0, /* create_options */
7035 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7036 0, /* oplock_request */
7038 0, /* allocation_size */
7039 0, /* private_flags */
7042 &new_fsp
, /* result */
7044 NULL
, NULL
); /* create context */
7046 if (!NT_STATUS_IS_OK(status
)) {
7047 /* NB. We check for open_was_deferred in the caller. */
7051 /* Only change if needed. */
7052 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7053 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7054 status
= map_nt_error_from_unix(errno
);
7055 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7060 /* Changing the allocation size should set the last mod time. */
7062 * This is equivalent to a write. Ensure it's seen immediately
7063 * if there are no pending writes.
7065 trigger_write_time_update_immediate(new_fsp
);
7066 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7067 return NT_STATUS_OK
;
7070 /****************************************************************************
7071 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7072 ****************************************************************************/
7074 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7075 struct smb_request
*req
,
7079 const struct smb_filename
*smb_fname
,
7080 bool fail_after_createfile
)
7084 if (total_data
< 8) {
7085 return NT_STATUS_INVALID_PARAMETER
;
7088 size
= IVAL(pdata
,0);
7089 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7090 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7091 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7094 return smb_set_file_size(conn
, req
,
7099 fail_after_createfile
);
7102 /****************************************************************************
7103 Allow a UNIX info mknod.
7104 ****************************************************************************/
7106 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7109 const struct smb_filename
*smb_fname
)
7111 uint32 file_type
= IVAL(pdata
,56);
7112 #if defined(HAVE_MAKEDEV)
7113 uint32 dev_major
= IVAL(pdata
,60);
7114 uint32 dev_minor
= IVAL(pdata
,68);
7116 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7117 uint32 raw_unixmode
= IVAL(pdata
,84);
7121 if (total_data
< 100) {
7122 return NT_STATUS_INVALID_PARAMETER
;
7125 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7126 PERM_NEW_FILE
, &unixmode
);
7127 if (!NT_STATUS_IS_OK(status
)) {
7131 #if defined(HAVE_MAKEDEV)
7132 dev
= makedev(dev_major
, dev_minor
);
7135 switch (file_type
) {
7136 #if defined(S_IFIFO)
7137 case UNIX_TYPE_FIFO
:
7138 unixmode
|= S_IFIFO
;
7141 #if defined(S_IFSOCK)
7142 case UNIX_TYPE_SOCKET
:
7143 unixmode
|= S_IFSOCK
;
7146 #if defined(S_IFCHR)
7147 case UNIX_TYPE_CHARDEV
:
7148 unixmode
|= S_IFCHR
;
7151 #if defined(S_IFBLK)
7152 case UNIX_TYPE_BLKDEV
:
7153 unixmode
|= S_IFBLK
;
7157 return NT_STATUS_INVALID_PARAMETER
;
7160 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7161 "%.0f mode 0%o for file %s\n", (double)dev
,
7162 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7164 /* Ok - do the mknod. */
7165 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7166 return map_nt_error_from_unix(errno
);
7169 /* If any of the other "set" calls fail we
7170 * don't want to end up with a half-constructed mknod.
7173 if (lp_inherit_permissions(SNUM(conn
))) {
7175 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7177 return NT_STATUS_NO_MEMORY
;
7179 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7181 TALLOC_FREE(parent
);
7184 return NT_STATUS_OK
;
7187 /****************************************************************************
7188 Deal with SMB_SET_FILE_UNIX_BASIC.
7189 ****************************************************************************/
7191 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7192 struct smb_request
*req
,
7196 const struct smb_filename
*smb_fname
)
7198 struct smb_file_time ft
;
7199 uint32 raw_unixmode
;
7202 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7203 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7204 NTSTATUS status
= NT_STATUS_OK
;
7205 bool delete_on_fail
= False
;
7206 enum perm_type ptype
;
7207 files_struct
*all_fsps
= NULL
;
7208 bool modify_mtime
= true;
7210 struct smb_filename
*smb_fname_tmp
= NULL
;
7211 SMB_STRUCT_STAT sbuf
;
7215 if (total_data
< 100) {
7216 return NT_STATUS_INVALID_PARAMETER
;
7219 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7220 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7221 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7222 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7225 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7226 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7227 set_owner
= (uid_t
)IVAL(pdata
,40);
7228 set_grp
= (gid_t
)IVAL(pdata
,48);
7229 raw_unixmode
= IVAL(pdata
,84);
7231 if (VALID_STAT(smb_fname
->st
)) {
7232 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7233 ptype
= PERM_EXISTING_DIR
;
7235 ptype
= PERM_EXISTING_FILE
;
7238 ptype
= PERM_NEW_FILE
;
7241 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7243 if (!NT_STATUS_IS_OK(status
)) {
7247 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7248 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7249 smb_fname_str_dbg(smb_fname
), (double)size
,
7250 (unsigned int)set_owner
, (unsigned int)set_grp
,
7251 (int)raw_unixmode
));
7253 sbuf
= smb_fname
->st
;
7255 if (!VALID_STAT(sbuf
)) {
7257 * The only valid use of this is to create character and block
7258 * devices, and named pipes. This is deprecated (IMHO) and
7259 * a new info level should be used for mknod. JRA.
7262 status
= smb_unix_mknod(conn
,
7266 if (!NT_STATUS_IS_OK(status
)) {
7270 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7271 if (smb_fname_tmp
== NULL
) {
7272 return NT_STATUS_NO_MEMORY
;
7275 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7276 status
= map_nt_error_from_unix(errno
);
7277 TALLOC_FREE(smb_fname_tmp
);
7278 SMB_VFS_UNLINK(conn
, smb_fname
);
7282 sbuf
= smb_fname_tmp
->st
;
7283 smb_fname
= smb_fname_tmp
;
7285 /* Ensure we don't try and change anything else. */
7286 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7287 size
= get_file_size_stat(&sbuf
);
7288 ft
.atime
= sbuf
.st_ex_atime
;
7289 ft
.mtime
= sbuf
.st_ex_mtime
;
7291 * We continue here as we might want to change the
7294 delete_on_fail
= True
;
7298 /* Horrible backwards compatibility hack as an old server bug
7299 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7303 size
= get_file_size_stat(&sbuf
);
7308 * Deal with the UNIX specific mode set.
7311 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7314 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7315 "setting mode 0%o for file %s\n",
7316 (unsigned int)unixmode
,
7317 smb_fname_str_dbg(smb_fname
)));
7318 if (fsp
&& fsp
->fh
->fd
!= -1) {
7319 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7321 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7324 return map_nt_error_from_unix(errno
);
7329 * Deal with the UNIX specific uid set.
7332 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7333 (sbuf
.st_ex_uid
!= set_owner
)) {
7336 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7337 "changing owner %u for path %s\n",
7338 (unsigned int)set_owner
,
7339 smb_fname_str_dbg(smb_fname
)));
7341 if (fsp
&& fsp
->fh
->fd
!= -1) {
7342 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7345 * UNIX extensions calls must always operate
7348 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7349 set_owner
, (gid_t
)-1);
7353 status
= map_nt_error_from_unix(errno
);
7354 if (delete_on_fail
) {
7355 SMB_VFS_UNLINK(conn
, smb_fname
);
7362 * Deal with the UNIX specific gid set.
7365 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7366 (sbuf
.st_ex_gid
!= set_grp
)) {
7369 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7370 "changing group %u for file %s\n",
7371 (unsigned int)set_owner
,
7372 smb_fname_str_dbg(smb_fname
)));
7373 if (fsp
&& fsp
->fh
->fd
!= -1) {
7374 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7377 * UNIX extensions calls must always operate
7380 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7384 status
= map_nt_error_from_unix(errno
);
7385 if (delete_on_fail
) {
7386 SMB_VFS_UNLINK(conn
, smb_fname
);
7392 /* Deal with any size changes. */
7394 status
= smb_set_file_size(conn
, req
,
7400 if (!NT_STATUS_IS_OK(status
)) {
7404 /* Deal with any time changes. */
7405 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7406 /* No change, don't cancel anything. */
7410 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7411 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7412 all_fsps
= file_find_di_next(all_fsps
)) {
7414 * We're setting the time explicitly for UNIX.
7415 * Cancel any pending changes over all handles.
7417 all_fsps
->update_write_time_on_close
= false;
7418 TALLOC_FREE(all_fsps
->update_write_time_event
);
7422 * Override the "setting_write_time"
7423 * parameter here as it almost does what
7424 * we need. Just remember if we modified
7425 * mtime and send the notify ourselves.
7427 if (null_timespec(ft
.mtime
)) {
7428 modify_mtime
= false;
7431 status
= smb_set_file_time(conn
,
7437 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7438 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7443 /****************************************************************************
7444 Deal with SMB_SET_FILE_UNIX_INFO2.
7445 ****************************************************************************/
7447 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7448 struct smb_request
*req
,
7452 const struct smb_filename
*smb_fname
)
7458 if (total_data
< 116) {
7459 return NT_STATUS_INVALID_PARAMETER
;
7462 /* Start by setting all the fields that are common between UNIX_BASIC
7465 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7467 if (!NT_STATUS_IS_OK(status
)) {
7471 smb_fflags
= IVAL(pdata
, 108);
7472 smb_fmask
= IVAL(pdata
, 112);
7474 /* NB: We should only attempt to alter the file flags if the client
7475 * sends a non-zero mask.
7477 if (smb_fmask
!= 0) {
7478 int stat_fflags
= 0;
7480 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7481 smb_fmask
, &stat_fflags
)) {
7482 /* Client asked to alter a flag we don't understand. */
7483 return NT_STATUS_INVALID_PARAMETER
;
7486 if (fsp
&& fsp
->fh
->fd
!= -1) {
7487 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7488 return NT_STATUS_NOT_SUPPORTED
;
7490 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7491 stat_fflags
) != 0) {
7492 return map_nt_error_from_unix(errno
);
7497 /* XXX: need to add support for changing the create_time here. You
7498 * can do this for paths on Darwin with setattrlist(2). The right way
7499 * to hook this up is probably by extending the VFS utimes interface.
7502 return NT_STATUS_OK
;
7505 /****************************************************************************
7506 Create a directory with POSIX semantics.
7507 ****************************************************************************/
7509 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7510 struct smb_request
*req
,
7513 struct smb_filename
*smb_fname
,
7514 int *pdata_return_size
)
7516 NTSTATUS status
= NT_STATUS_OK
;
7517 uint32 raw_unixmode
= 0;
7518 uint32 mod_unixmode
= 0;
7519 mode_t unixmode
= (mode_t
)0;
7520 files_struct
*fsp
= NULL
;
7521 uint16 info_level_return
= 0;
7523 char *pdata
= *ppdata
;
7525 if (total_data
< 18) {
7526 return NT_STATUS_INVALID_PARAMETER
;
7529 raw_unixmode
= IVAL(pdata
,8);
7530 /* Next 4 bytes are not yet defined. */
7532 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7533 PERM_NEW_DIR
, &unixmode
);
7534 if (!NT_STATUS_IS_OK(status
)) {
7538 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7540 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7541 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7543 status
= SMB_VFS_CREATE_FILE(
7546 0, /* root_dir_fid */
7547 smb_fname
, /* fname */
7548 FILE_READ_ATTRIBUTES
, /* access_mask */
7549 FILE_SHARE_NONE
, /* share_access */
7550 FILE_CREATE
, /* create_disposition*/
7551 FILE_DIRECTORY_FILE
, /* create_options */
7552 mod_unixmode
, /* file_attributes */
7553 0, /* oplock_request */
7555 0, /* allocation_size */
7556 0, /* private_flags */
7561 NULL
, NULL
); /* create context */
7563 if (NT_STATUS_IS_OK(status
)) {
7564 close_file(req
, fsp
, NORMAL_CLOSE
);
7567 info_level_return
= SVAL(pdata
,16);
7569 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7570 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7571 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7572 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7574 *pdata_return_size
= 12;
7577 /* Realloc the data size */
7578 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7579 if (*ppdata
== NULL
) {
7580 *pdata_return_size
= 0;
7581 return NT_STATUS_NO_MEMORY
;
7585 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7586 SSVAL(pdata
,2,0); /* No fnum. */
7587 SIVAL(pdata
,4,info
); /* Was directory created. */
7589 switch (info_level_return
) {
7590 case SMB_QUERY_FILE_UNIX_BASIC
:
7591 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7592 SSVAL(pdata
,10,0); /* Padding. */
7593 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7596 case SMB_QUERY_FILE_UNIX_INFO2
:
7597 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7598 SSVAL(pdata
,10,0); /* Padding. */
7599 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7603 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7604 SSVAL(pdata
,10,0); /* Padding. */
7611 /****************************************************************************
7612 Open/Create a file with POSIX semantics.
7613 ****************************************************************************/
7615 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7616 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7618 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7619 struct smb_request
*req
,
7622 struct smb_filename
*smb_fname
,
7623 int *pdata_return_size
)
7625 bool extended_oplock_granted
= False
;
7626 char *pdata
= *ppdata
;
7628 uint32 wire_open_mode
= 0;
7629 uint32 raw_unixmode
= 0;
7630 uint32 mod_unixmode
= 0;
7631 uint32 create_disp
= 0;
7632 uint32 access_mask
= 0;
7633 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7634 NTSTATUS status
= NT_STATUS_OK
;
7635 mode_t unixmode
= (mode_t
)0;
7636 files_struct
*fsp
= NULL
;
7637 int oplock_request
= 0;
7639 uint16 info_level_return
= 0;
7641 if (total_data
< 18) {
7642 return NT_STATUS_INVALID_PARAMETER
;
7645 flags
= IVAL(pdata
,0);
7646 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7647 if (oplock_request
) {
7648 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7651 wire_open_mode
= IVAL(pdata
,4);
7653 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7654 return smb_posix_mkdir(conn
, req
,
7661 switch (wire_open_mode
& SMB_ACCMODE
) {
7663 access_mask
= SMB_O_RDONLY_MAPPING
;
7666 access_mask
= SMB_O_WRONLY_MAPPING
;
7669 access_mask
= (SMB_O_RDONLY_MAPPING
|
7670 SMB_O_WRONLY_MAPPING
);
7673 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7674 (unsigned int)wire_open_mode
));
7675 return NT_STATUS_INVALID_PARAMETER
;
7678 wire_open_mode
&= ~SMB_ACCMODE
;
7680 /* First take care of O_CREAT|O_EXCL interactions. */
7681 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7682 case (SMB_O_CREAT
| SMB_O_EXCL
):
7683 /* File exists fail. File not exist create. */
7684 create_disp
= FILE_CREATE
;
7687 /* File exists open. File not exist create. */
7688 create_disp
= FILE_OPEN_IF
;
7691 /* O_EXCL on its own without O_CREAT is undefined.
7692 We deliberately ignore it as some versions of
7693 Linux CIFSFS can send a bare O_EXCL on the
7694 wire which other filesystems in the kernel
7695 ignore. See bug 9519 for details. */
7700 /* File exists open. File not exist fail. */
7701 create_disp
= FILE_OPEN
;
7704 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7705 (unsigned int)wire_open_mode
));
7706 return NT_STATUS_INVALID_PARAMETER
;
7709 /* Next factor in the effects of O_TRUNC. */
7710 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7712 if (wire_open_mode
& SMB_O_TRUNC
) {
7713 switch (create_disp
) {
7715 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7716 /* Leave create_disp alone as
7717 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7719 /* File exists fail. File not exist create. */
7722 /* SMB_O_CREAT | SMB_O_TRUNC */
7723 /* File exists overwrite. File not exist create. */
7724 create_disp
= FILE_OVERWRITE_IF
;
7728 /* File exists overwrite. File not exist fail. */
7729 create_disp
= FILE_OVERWRITE
;
7732 /* Cannot get here. */
7733 smb_panic("smb_posix_open: logic error");
7734 return NT_STATUS_INVALID_PARAMETER
;
7738 raw_unixmode
= IVAL(pdata
,8);
7739 /* Next 4 bytes are not yet defined. */
7741 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7742 (VALID_STAT(smb_fname
->st
) ?
7743 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7746 if (!NT_STATUS_IS_OK(status
)) {
7750 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7752 if (wire_open_mode
& SMB_O_SYNC
) {
7753 create_options
|= FILE_WRITE_THROUGH
;
7755 if (wire_open_mode
& SMB_O_APPEND
) {
7756 access_mask
|= FILE_APPEND_DATA
;
7758 if (wire_open_mode
& SMB_O_DIRECT
) {
7759 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7762 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7763 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7764 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7765 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7767 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7768 create_options
|= FILE_DIRECTORY_FILE
;
7771 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7772 smb_fname_str_dbg(smb_fname
),
7773 (unsigned int)wire_open_mode
,
7774 (unsigned int)unixmode
));
7776 status
= SMB_VFS_CREATE_FILE(
7779 0, /* root_dir_fid */
7780 smb_fname
, /* fname */
7781 access_mask
, /* access_mask */
7782 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7784 create_disp
, /* create_disposition*/
7785 create_options
, /* create_options */
7786 mod_unixmode
, /* file_attributes */
7787 oplock_request
, /* oplock_request */
7789 0, /* allocation_size */
7790 0, /* private_flags */
7795 NULL
, NULL
); /* create context */
7797 if (!NT_STATUS_IS_OK(status
)) {
7801 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7802 extended_oplock_granted
= True
;
7805 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7806 extended_oplock_granted
= True
;
7809 info_level_return
= SVAL(pdata
,16);
7811 /* Allocate the correct return size. */
7813 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7814 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7815 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7816 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7818 *pdata_return_size
= 12;
7821 /* Realloc the data size */
7822 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7823 if (*ppdata
== NULL
) {
7824 close_file(req
, fsp
, ERROR_CLOSE
);
7825 *pdata_return_size
= 0;
7826 return NT_STATUS_NO_MEMORY
;
7830 if (extended_oplock_granted
) {
7831 if (flags
& REQUEST_BATCH_OPLOCK
) {
7832 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7834 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7836 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7837 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7839 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7842 SSVAL(pdata
,2,fsp
->fnum
);
7843 SIVAL(pdata
,4,info
); /* Was file created etc. */
7845 switch (info_level_return
) {
7846 case SMB_QUERY_FILE_UNIX_BASIC
:
7847 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7848 SSVAL(pdata
,10,0); /* padding. */
7849 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7852 case SMB_QUERY_FILE_UNIX_INFO2
:
7853 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7854 SSVAL(pdata
,10,0); /* padding. */
7855 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7859 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7860 SSVAL(pdata
,10,0); /* padding. */
7863 return NT_STATUS_OK
;
7866 /****************************************************************************
7867 Delete a file with POSIX semantics.
7868 ****************************************************************************/
7870 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7871 struct smb_request
*req
,
7874 struct smb_filename
*smb_fname
)
7876 NTSTATUS status
= NT_STATUS_OK
;
7877 files_struct
*fsp
= NULL
;
7881 int create_options
= 0;
7883 struct share_mode_lock
*lck
= NULL
;
7885 if (total_data
< 2) {
7886 return NT_STATUS_INVALID_PARAMETER
;
7889 flags
= SVAL(pdata
,0);
7891 if (!VALID_STAT(smb_fname
->st
)) {
7892 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7895 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7896 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7897 return NT_STATUS_NOT_A_DIRECTORY
;
7900 DEBUG(10,("smb_posix_unlink: %s %s\n",
7901 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7902 smb_fname_str_dbg(smb_fname
)));
7904 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7905 create_options
|= FILE_DIRECTORY_FILE
;
7908 status
= SMB_VFS_CREATE_FILE(
7911 0, /* root_dir_fid */
7912 smb_fname
, /* fname */
7913 DELETE_ACCESS
, /* access_mask */
7914 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7916 FILE_OPEN
, /* create_disposition*/
7917 create_options
, /* create_options */
7918 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7919 0, /* oplock_request */
7921 0, /* allocation_size */
7922 0, /* private_flags */
7927 NULL
, NULL
); /* create context */
7929 if (!NT_STATUS_IS_OK(status
)) {
7934 * Don't lie to client. If we can't really delete due to
7935 * non-POSIX opens return SHARING_VIOLATION.
7938 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7940 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7941 "lock for file %s\n", fsp_str_dbg(fsp
)));
7942 close_file(req
, fsp
, NORMAL_CLOSE
);
7943 return NT_STATUS_INVALID_PARAMETER
;
7947 * See if others still have the file open. If this is the case, then
7948 * don't delete. If all opens are POSIX delete we can set the delete
7949 * on close disposition.
7951 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7952 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7953 if (is_valid_share_mode_entry(e
)) {
7954 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7957 if (share_mode_stale_pid(lck
->data
, i
)) {
7960 /* Fail with sharing violation. */
7962 close_file(req
, fsp
, NORMAL_CLOSE
);
7963 return NT_STATUS_SHARING_VIOLATION
;
7968 * Set the delete on close.
7970 status
= smb_set_file_disposition_info(conn
,
7978 if (!NT_STATUS_IS_OK(status
)) {
7979 close_file(req
, fsp
, NORMAL_CLOSE
);
7982 return close_file(req
, fsp
, NORMAL_CLOSE
);
7985 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7986 struct smb_request
*req
,
7987 TALLOC_CTX
*mem_ctx
,
7988 uint16_t info_level
,
7990 struct smb_filename
*smb_fname
,
7991 char **ppdata
, int total_data
,
7994 char *pdata
= *ppdata
;
7995 NTSTATUS status
= NT_STATUS_OK
;
7996 int data_return_size
= 0;
8000 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8001 return NT_STATUS_INVALID_LEVEL
;
8004 if (!CAN_WRITE(conn
)) {
8005 /* Allow POSIX opens. The open path will deny
8006 * any non-readonly opens. */
8007 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8008 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8012 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8013 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8015 info_level
, total_data
));
8017 switch (info_level
) {
8019 case SMB_INFO_STANDARD
:
8021 status
= smb_set_info_standard(conn
,
8029 case SMB_INFO_SET_EA
:
8031 status
= smb_info_set_ea(conn
,
8039 case SMB_SET_FILE_BASIC_INFO
:
8040 case SMB_FILE_BASIC_INFORMATION
:
8042 status
= smb_set_file_basic_info(conn
,
8050 case SMB_FILE_ALLOCATION_INFORMATION
:
8051 case SMB_SET_FILE_ALLOCATION_INFO
:
8053 status
= smb_set_file_allocation_info(conn
, req
,
8061 case SMB_FILE_END_OF_FILE_INFORMATION
:
8062 case SMB_SET_FILE_END_OF_FILE_INFO
:
8065 * XP/Win7 both fail after the createfile with
8066 * SMB_SET_FILE_END_OF_FILE_INFO but not
8067 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8068 * The level is known here, so pass it down
8072 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8074 status
= smb_set_file_end_of_file_info(conn
, req
,
8083 case SMB_FILE_DISPOSITION_INFORMATION
:
8084 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8087 /* JRA - We used to just ignore this on a path ?
8088 * Shouldn't this be invalid level on a pathname
8091 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8092 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8095 status
= smb_set_file_disposition_info(conn
,
8103 case SMB_FILE_POSITION_INFORMATION
:
8105 status
= smb_file_position_information(conn
,
8112 case SMB_FILE_FULL_EA_INFORMATION
:
8114 status
= smb_set_file_full_ea_info(conn
,
8121 /* From tridge Samba4 :
8122 * MODE_INFORMATION in setfileinfo (I have no
8123 * idea what "mode information" on a file is - it takes a value of 0,
8124 * 2, 4 or 6. What could it be?).
8127 case SMB_FILE_MODE_INFORMATION
:
8129 status
= smb_file_mode_information(conn
,
8136 * CIFS UNIX extensions.
8139 case SMB_SET_FILE_UNIX_BASIC
:
8141 status
= smb_set_file_unix_basic(conn
, req
,
8149 case SMB_SET_FILE_UNIX_INFO2
:
8151 status
= smb_set_file_unix_info2(conn
, req
,
8159 case SMB_SET_FILE_UNIX_LINK
:
8162 /* We must have a pathname for this. */
8163 return NT_STATUS_INVALID_LEVEL
;
8165 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8166 total_data
, smb_fname
);
8170 case SMB_SET_FILE_UNIX_HLINK
:
8173 /* We must have a pathname for this. */
8174 return NT_STATUS_INVALID_LEVEL
;
8176 status
= smb_set_file_unix_hlink(conn
, req
,
8182 case SMB_FILE_RENAME_INFORMATION
:
8184 status
= smb_file_rename_information(conn
, req
,
8190 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8192 /* SMB2 rename information. */
8193 status
= smb2_file_rename_information(conn
, req
,
8199 case SMB_FILE_LINK_INFORMATION
:
8201 status
= smb_file_link_information(conn
, req
,
8207 #if defined(HAVE_POSIX_ACLS)
8208 case SMB_SET_POSIX_ACL
:
8210 status
= smb_set_posix_acl(conn
,
8219 case SMB_SET_POSIX_LOCK
:
8222 return NT_STATUS_INVALID_LEVEL
;
8224 status
= smb_set_posix_lock(conn
, req
,
8225 pdata
, total_data
, fsp
);
8229 case SMB_POSIX_PATH_OPEN
:
8232 /* We must have a pathname for this. */
8233 return NT_STATUS_INVALID_LEVEL
;
8236 status
= smb_posix_open(conn
, req
,
8244 case SMB_POSIX_PATH_UNLINK
:
8247 /* We must have a pathname for this. */
8248 return NT_STATUS_INVALID_LEVEL
;
8251 status
= smb_posix_unlink(conn
, req
,
8259 return NT_STATUS_INVALID_LEVEL
;
8262 if (!NT_STATUS_IS_OK(status
)) {
8266 *ret_data_size
= data_return_size
;
8267 return NT_STATUS_OK
;
8270 /****************************************************************************
8271 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8272 ****************************************************************************/
8274 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8275 struct smb_request
*req
,
8276 unsigned int tran_call
,
8277 char **pparams
, int total_params
,
8278 char **ppdata
, int total_data
,
8279 unsigned int max_data_bytes
)
8281 char *params
= *pparams
;
8282 char *pdata
= *ppdata
;
8284 struct smb_filename
*smb_fname
= NULL
;
8285 files_struct
*fsp
= NULL
;
8286 NTSTATUS status
= NT_STATUS_OK
;
8287 int data_return_size
= 0;
8290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8294 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8295 if (total_params
< 4) {
8296 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8300 fsp
= file_fsp(req
, SVAL(params
,0));
8301 /* Basic check for non-null fsp. */
8302 if (!check_fsp_open(conn
, req
, fsp
)) {
8305 info_level
= SVAL(params
,2);
8307 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8308 if (smb_fname
== NULL
) {
8309 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8313 if(fsp
->fh
->fd
== -1) {
8315 * This is actually a SETFILEINFO on a directory
8316 * handle (returned from an NT SMB). NT5.0 seems
8317 * to do this call. JRA.
8319 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8320 /* Always do lstat for UNIX calls. */
8321 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8322 DEBUG(3,("call_trans2setfilepathinfo: "
8323 "SMB_VFS_LSTAT of %s failed "
8325 smb_fname_str_dbg(smb_fname
),
8327 reply_nterror(req
, map_nt_error_from_unix(errno
));
8331 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8332 DEBUG(3,("call_trans2setfilepathinfo: "
8333 "fileinfo of %s failed (%s)\n",
8334 smb_fname_str_dbg(smb_fname
),
8336 reply_nterror(req
, map_nt_error_from_unix(errno
));
8340 } else if (fsp
->print_file
) {
8342 * Doing a DELETE_ON_CLOSE should cancel a print job.
8344 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8345 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8347 DEBUG(3,("call_trans2setfilepathinfo: "
8348 "Cancelling print job (%s)\n",
8352 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8358 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8363 * Original code - this is an open file.
8365 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8366 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8367 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8369 reply_nterror(req
, map_nt_error_from_unix(errno
));
8375 uint32_t ucf_flags
= 0;
8378 if (total_params
< 7) {
8379 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8383 info_level
= SVAL(params
,0);
8384 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8385 total_params
- 6, STR_TERMINATE
,
8387 if (!NT_STATUS_IS_OK(status
)) {
8388 reply_nterror(req
, status
);
8392 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8393 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8394 info_level
== SMB_FILE_RENAME_INFORMATION
||
8395 info_level
== SMB_POSIX_PATH_UNLINK
) {
8396 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8399 status
= filename_convert(req
, conn
,
8400 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8405 if (!NT_STATUS_IS_OK(status
)) {
8406 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8407 reply_botherror(req
,
8408 NT_STATUS_PATH_NOT_COVERED
,
8409 ERRSRV
, ERRbadpath
);
8412 reply_nterror(req
, status
);
8416 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8418 * For CIFS UNIX extensions the target name may not exist.
8421 /* Always do lstat for UNIX calls. */
8422 SMB_VFS_LSTAT(conn
, smb_fname
);
8424 } else if (!VALID_STAT(smb_fname
->st
) &&
8425 SMB_VFS_STAT(conn
, smb_fname
)) {
8426 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8428 smb_fname_str_dbg(smb_fname
),
8430 reply_nterror(req
, map_nt_error_from_unix(errno
));
8435 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8436 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8438 info_level
,total_data
));
8440 /* Realloc the parameter size */
8441 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8442 if (*pparams
== NULL
) {
8443 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8450 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8456 if (!NT_STATUS_IS_OK(status
)) {
8457 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8458 /* We have re-scheduled this call. */
8461 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8462 /* We have re-scheduled this call. */
8465 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8466 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8467 ERRSRV
, ERRbadpath
);
8470 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8471 reply_openerror(req
, status
);
8476 * Invalid EA name needs to return 2 param bytes,
8477 * not a zero-length error packet.
8479 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8480 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8483 reply_nterror(req
, status
);
8488 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8494 /****************************************************************************
8495 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8496 ****************************************************************************/
8498 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8499 char **pparams
, int total_params
,
8500 char **ppdata
, int total_data
,
8501 unsigned int max_data_bytes
)
8503 struct smb_filename
*smb_dname
= NULL
;
8504 char *params
= *pparams
;
8505 char *pdata
= *ppdata
;
8506 char *directory
= NULL
;
8507 NTSTATUS status
= NT_STATUS_OK
;
8508 struct ea_list
*ea_list
= NULL
;
8509 TALLOC_CTX
*ctx
= talloc_tos();
8511 if (!CAN_WRITE(conn
)) {
8512 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8516 if (total_params
< 5) {
8517 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8521 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8522 total_params
- 4, STR_TERMINATE
,
8524 if (!NT_STATUS_IS_OK(status
)) {
8525 reply_nterror(req
, status
);
8529 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8531 status
= filename_convert(ctx
,
8533 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8539 if (!NT_STATUS_IS_OK(status
)) {
8540 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8541 reply_botherror(req
,
8542 NT_STATUS_PATH_NOT_COVERED
,
8543 ERRSRV
, ERRbadpath
);
8546 reply_nterror(req
, status
);
8551 * OS/2 workplace shell seems to send SET_EA requests of "null"
8552 * length (4 bytes containing IVAL 4).
8553 * They seem to have no effect. Bug #3212. JRA.
8556 if (total_data
&& (total_data
!= 4)) {
8557 /* Any data in this call is an EA list. */
8558 if (total_data
< 10) {
8559 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8563 if (IVAL(pdata
,0) > total_data
) {
8564 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8565 IVAL(pdata
,0), (unsigned int)total_data
));
8566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8570 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8573 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8577 if (!lp_ea_support(SNUM(conn
))) {
8578 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8582 /* If total_data == 4 Windows doesn't care what values
8583 * are placed in that field, it just ignores them.
8584 * The System i QNTC IBM SMB client puts bad values here,
8585 * so ignore them. */
8587 status
= create_directory(conn
, req
, smb_dname
);
8589 if (!NT_STATUS_IS_OK(status
)) {
8590 reply_nterror(req
, status
);
8594 /* Try and set any given EA. */
8596 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8597 if (!NT_STATUS_IS_OK(status
)) {
8598 reply_nterror(req
, status
);
8603 /* Realloc the parameter and data sizes */
8604 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8605 if(*pparams
== NULL
) {
8606 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8613 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8616 TALLOC_FREE(smb_dname
);
8620 /****************************************************************************
8621 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8622 We don't actually do this - we just send a null response.
8623 ****************************************************************************/
8625 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8626 struct smb_request
*req
,
8627 char **pparams
, int total_params
,
8628 char **ppdata
, int total_data
,
8629 unsigned int max_data_bytes
)
8631 char *params
= *pparams
;
8634 if (total_params
< 6) {
8635 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8639 info_level
= SVAL(params
,4);
8640 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8642 switch (info_level
) {
8647 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8651 /* Realloc the parameter and data sizes */
8652 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8653 if (*pparams
== NULL
) {
8654 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8659 SSVAL(params
,0,fnf_handle
);
8660 SSVAL(params
,2,0); /* No changes */
8661 SSVAL(params
,4,0); /* No EA errors */
8668 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8673 /****************************************************************************
8674 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8675 changes). Currently this does nothing.
8676 ****************************************************************************/
8678 static void call_trans2findnotifynext(connection_struct
*conn
,
8679 struct smb_request
*req
,
8680 char **pparams
, int total_params
,
8681 char **ppdata
, int total_data
,
8682 unsigned int max_data_bytes
)
8684 char *params
= *pparams
;
8686 DEBUG(3,("call_trans2findnotifynext\n"));
8688 /* Realloc the parameter and data sizes */
8689 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8690 if (*pparams
== NULL
) {
8691 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8696 SSVAL(params
,0,0); /* No changes */
8697 SSVAL(params
,2,0); /* No EA errors */
8699 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8704 /****************************************************************************
8705 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8706 ****************************************************************************/
8708 static void call_trans2getdfsreferral(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
;
8715 char *pathname
= NULL
;
8717 int max_referral_level
;
8718 NTSTATUS status
= NT_STATUS_OK
;
8719 TALLOC_CTX
*ctx
= talloc_tos();
8721 DEBUG(10,("call_trans2getdfsreferral\n"));
8723 if (total_params
< 3) {
8724 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8728 max_referral_level
= SVAL(params
,0);
8730 if(!lp_host_msdfs()) {
8731 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8735 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8736 total_params
- 2, STR_TERMINATE
);
8738 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8741 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8742 ppdata
,&status
)) < 0) {
8743 reply_nterror(req
, status
);
8747 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8748 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8749 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8754 #define LMCAT_SPL 0x53
8755 #define LMFUNC_GETJOBID 0x60
8757 /****************************************************************************
8758 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8759 ****************************************************************************/
8761 static void call_trans2ioctl(connection_struct
*conn
,
8762 struct smb_request
*req
,
8763 char **pparams
, int total_params
,
8764 char **ppdata
, int total_data
,
8765 unsigned int max_data_bytes
)
8767 char *pdata
= *ppdata
;
8768 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8772 /* check for an invalid fid before proceeding */
8775 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8779 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8780 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8781 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8782 if (*ppdata
== NULL
) {
8783 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8788 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8789 CAN ACCEPT THIS IN UNICODE. JRA. */
8792 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8794 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8795 lp_netbios_name(), 15,
8796 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8797 if (!NT_STATUS_IS_OK(status
)) {
8798 reply_nterror(req
, status
);
8801 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8802 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8803 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8804 if (!NT_STATUS_IS_OK(status
)) {
8805 reply_nterror(req
, status
);
8808 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8813 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8814 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8817 /****************************************************************************
8818 Reply to a SMBfindclose (stop trans2 directory search).
8819 ****************************************************************************/
8821 void reply_findclose(struct smb_request
*req
)
8824 struct smbd_server_connection
*sconn
= req
->sconn
;
8826 START_PROFILE(SMBfindclose
);
8829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8830 END_PROFILE(SMBfindclose
);
8834 dptr_num
= SVALS(req
->vwv
+0, 0);
8836 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8838 dptr_close(sconn
, &dptr_num
);
8840 reply_outbuf(req
, 0, 0);
8842 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8844 END_PROFILE(SMBfindclose
);
8848 /****************************************************************************
8849 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8850 ****************************************************************************/
8852 void reply_findnclose(struct smb_request
*req
)
8856 START_PROFILE(SMBfindnclose
);
8859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8860 END_PROFILE(SMBfindnclose
);
8864 dptr_num
= SVAL(req
->vwv
+0, 0);
8866 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8868 /* We never give out valid handles for a
8869 findnotifyfirst - so any dptr_num is ok here.
8872 reply_outbuf(req
, 0, 0);
8874 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8876 END_PROFILE(SMBfindnclose
);
8880 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8881 struct trans_state
*state
)
8883 if (get_Protocol() >= PROTOCOL_NT1
) {
8884 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8885 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8888 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8889 if (state
->call
!= TRANSACT2_QFSINFO
&&
8890 state
->call
!= TRANSACT2_SETFSINFO
) {
8891 DEBUG(0,("handle_trans2: encryption required "
8893 (unsigned int)state
->call
));
8894 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8899 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8901 /* Now we must call the relevant TRANS2 function */
8902 switch(state
->call
) {
8903 case TRANSACT2_OPEN
:
8905 START_PROFILE(Trans2_open
);
8906 call_trans2open(conn
, req
,
8907 &state
->param
, state
->total_param
,
8908 &state
->data
, state
->total_data
,
8909 state
->max_data_return
);
8910 END_PROFILE(Trans2_open
);
8914 case TRANSACT2_FINDFIRST
:
8916 START_PROFILE(Trans2_findfirst
);
8917 call_trans2findfirst(conn
, req
,
8918 &state
->param
, state
->total_param
,
8919 &state
->data
, state
->total_data
,
8920 state
->max_data_return
);
8921 END_PROFILE(Trans2_findfirst
);
8925 case TRANSACT2_FINDNEXT
:
8927 START_PROFILE(Trans2_findnext
);
8928 call_trans2findnext(conn
, req
,
8929 &state
->param
, state
->total_param
,
8930 &state
->data
, state
->total_data
,
8931 state
->max_data_return
);
8932 END_PROFILE(Trans2_findnext
);
8936 case TRANSACT2_QFSINFO
:
8938 START_PROFILE(Trans2_qfsinfo
);
8939 call_trans2qfsinfo(conn
, req
,
8940 &state
->param
, state
->total_param
,
8941 &state
->data
, state
->total_data
,
8942 state
->max_data_return
);
8943 END_PROFILE(Trans2_qfsinfo
);
8947 case TRANSACT2_SETFSINFO
:
8949 START_PROFILE(Trans2_setfsinfo
);
8950 call_trans2setfsinfo(conn
, req
,
8951 &state
->param
, state
->total_param
,
8952 &state
->data
, state
->total_data
,
8953 state
->max_data_return
);
8954 END_PROFILE(Trans2_setfsinfo
);
8958 case TRANSACT2_QPATHINFO
:
8959 case TRANSACT2_QFILEINFO
:
8961 START_PROFILE(Trans2_qpathinfo
);
8962 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8963 &state
->param
, state
->total_param
,
8964 &state
->data
, state
->total_data
,
8965 state
->max_data_return
);
8966 END_PROFILE(Trans2_qpathinfo
);
8970 case TRANSACT2_SETPATHINFO
:
8971 case TRANSACT2_SETFILEINFO
:
8973 START_PROFILE(Trans2_setpathinfo
);
8974 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8975 &state
->param
, state
->total_param
,
8976 &state
->data
, state
->total_data
,
8977 state
->max_data_return
);
8978 END_PROFILE(Trans2_setpathinfo
);
8982 case TRANSACT2_FINDNOTIFYFIRST
:
8984 START_PROFILE(Trans2_findnotifyfirst
);
8985 call_trans2findnotifyfirst(conn
, req
,
8986 &state
->param
, state
->total_param
,
8987 &state
->data
, state
->total_data
,
8988 state
->max_data_return
);
8989 END_PROFILE(Trans2_findnotifyfirst
);
8993 case TRANSACT2_FINDNOTIFYNEXT
:
8995 START_PROFILE(Trans2_findnotifynext
);
8996 call_trans2findnotifynext(conn
, req
,
8997 &state
->param
, state
->total_param
,
8998 &state
->data
, state
->total_data
,
8999 state
->max_data_return
);
9000 END_PROFILE(Trans2_findnotifynext
);
9004 case TRANSACT2_MKDIR
:
9006 START_PROFILE(Trans2_mkdir
);
9007 call_trans2mkdir(conn
, req
,
9008 &state
->param
, state
->total_param
,
9009 &state
->data
, state
->total_data
,
9010 state
->max_data_return
);
9011 END_PROFILE(Trans2_mkdir
);
9015 case TRANSACT2_GET_DFS_REFERRAL
:
9017 START_PROFILE(Trans2_get_dfs_referral
);
9018 call_trans2getdfsreferral(conn
, req
,
9019 &state
->param
, state
->total_param
,
9020 &state
->data
, state
->total_data
,
9021 state
->max_data_return
);
9022 END_PROFILE(Trans2_get_dfs_referral
);
9026 case TRANSACT2_IOCTL
:
9028 START_PROFILE(Trans2_ioctl
);
9029 call_trans2ioctl(conn
, req
,
9030 &state
->param
, state
->total_param
,
9031 &state
->data
, state
->total_data
,
9032 state
->max_data_return
);
9033 END_PROFILE(Trans2_ioctl
);
9038 /* Error in request */
9039 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9040 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9044 /****************************************************************************
9045 Reply to a SMBtrans2.
9046 ****************************************************************************/
9048 void reply_trans2(struct smb_request
*req
)
9050 connection_struct
*conn
= req
->conn
;
9055 unsigned int tran_call
;
9056 struct trans_state
*state
;
9059 START_PROFILE(SMBtrans2
);
9061 if (req
->wct
< 14) {
9062 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9063 END_PROFILE(SMBtrans2
);
9067 dsoff
= SVAL(req
->vwv
+12, 0);
9068 dscnt
= SVAL(req
->vwv
+11, 0);
9069 psoff
= SVAL(req
->vwv
+10, 0);
9070 pscnt
= SVAL(req
->vwv
+9, 0);
9071 tran_call
= SVAL(req
->vwv
+14, 0);
9073 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9074 if (!NT_STATUS_IS_OK(result
)) {
9075 DEBUG(2, ("Got invalid trans2 request: %s\n",
9076 nt_errstr(result
)));
9077 reply_nterror(req
, result
);
9078 END_PROFILE(SMBtrans2
);
9083 switch (tran_call
) {
9084 /* List the allowed trans2 calls on IPC$ */
9085 case TRANSACT2_OPEN
:
9086 case TRANSACT2_GET_DFS_REFERRAL
:
9087 case TRANSACT2_QFILEINFO
:
9088 case TRANSACT2_QFSINFO
:
9089 case TRANSACT2_SETFSINFO
:
9092 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9093 END_PROFILE(SMBtrans2
);
9098 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9099 DEBUG(0, ("talloc failed\n"));
9100 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9101 END_PROFILE(SMBtrans2
);
9105 state
->cmd
= SMBtrans2
;
9107 state
->mid
= req
->mid
;
9108 state
->vuid
= req
->vuid
;
9109 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9110 state
->setup
= NULL
;
9111 state
->total_param
= SVAL(req
->vwv
+0, 0);
9112 state
->param
= NULL
;
9113 state
->total_data
= SVAL(req
->vwv
+1, 0);
9115 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9116 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9117 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9118 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9119 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9121 state
->call
= tran_call
;
9123 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9124 is so as a sanity check */
9125 if (state
->setup_count
!= 1) {
9127 * Need to have rc=0 for ioctl to get job id for OS/2.
9128 * Network printing will fail if function is not successful.
9129 * Similar function in reply.c will be used if protocol
9130 * is LANMAN1.0 instead of LM1.2X002.
9131 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9132 * outbuf doesn't have to be set(only job id is used).
9134 if ( (state
->setup_count
== 4)
9135 && (tran_call
== TRANSACT2_IOCTL
)
9136 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9137 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9138 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9140 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9141 DEBUG(2,("Transaction is %d\n",tran_call
));
9143 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9144 END_PROFILE(SMBtrans2
);
9149 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9152 if (state
->total_data
) {
9154 if (trans_oob(state
->total_data
, 0, dscnt
)
9155 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9159 /* Can't use talloc here, the core routines do realloc on the
9160 * params and data. */
9161 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9162 if (state
->data
== NULL
) {
9163 DEBUG(0,("reply_trans2: data malloc fail for %u "
9164 "bytes !\n", (unsigned int)state
->total_data
));
9166 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9167 END_PROFILE(SMBtrans2
);
9171 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9174 if (state
->total_param
) {
9176 if (trans_oob(state
->total_param
, 0, pscnt
)
9177 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9181 /* Can't use talloc here, the core routines do realloc on the
9182 * params and data. */
9183 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9184 if (state
->param
== NULL
) {
9185 DEBUG(0,("reply_trans: param malloc fail for %u "
9186 "bytes !\n", (unsigned int)state
->total_param
));
9187 SAFE_FREE(state
->data
);
9189 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9190 END_PROFILE(SMBtrans2
);
9194 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9197 state
->received_data
= dscnt
;
9198 state
->received_param
= pscnt
;
9200 if ((state
->received_param
== state
->total_param
) &&
9201 (state
->received_data
== state
->total_data
)) {
9203 handle_trans2(conn
, req
, state
);
9205 SAFE_FREE(state
->data
);
9206 SAFE_FREE(state
->param
);
9208 END_PROFILE(SMBtrans2
);
9212 DLIST_ADD(conn
->pending_trans
, state
);
9214 /* We need to send an interim response then receive the rest
9215 of the parameter/data bytes */
9216 reply_outbuf(req
, 0, 0);
9217 show_msg((char *)req
->outbuf
);
9218 END_PROFILE(SMBtrans2
);
9223 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9224 SAFE_FREE(state
->data
);
9225 SAFE_FREE(state
->param
);
9227 END_PROFILE(SMBtrans2
);
9228 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9232 /****************************************************************************
9233 Reply to a SMBtranss2
9234 ****************************************************************************/
9236 void reply_transs2(struct smb_request
*req
)
9238 connection_struct
*conn
= req
->conn
;
9239 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9240 struct trans_state
*state
;
9242 START_PROFILE(SMBtranss2
);
9244 show_msg((const char *)req
->inbuf
);
9246 /* Windows clients expect all replies to
9247 a transact secondary (SMBtranss2 0x33)
9248 to have a command code of transact
9249 (SMBtrans2 0x32). See bug #8989
9250 and also [MS-CIFS] section 2.2.4.47.2
9253 req
->cmd
= SMBtrans2
;
9256 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9257 END_PROFILE(SMBtranss2
);
9261 for (state
= conn
->pending_trans
; state
!= NULL
;
9262 state
= state
->next
) {
9263 if (state
->mid
== req
->mid
) {
9268 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9269 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9270 END_PROFILE(SMBtranss2
);
9274 /* Revise state->total_param and state->total_data in case they have
9275 changed downwards */
9277 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9278 state
->total_param
= SVAL(req
->vwv
+0, 0);
9279 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9280 state
->total_data
= SVAL(req
->vwv
+1, 0);
9282 pcnt
= SVAL(req
->vwv
+2, 0);
9283 poff
= SVAL(req
->vwv
+3, 0);
9284 pdisp
= SVAL(req
->vwv
+4, 0);
9286 dcnt
= SVAL(req
->vwv
+5, 0);
9287 doff
= SVAL(req
->vwv
+6, 0);
9288 ddisp
= SVAL(req
->vwv
+7, 0);
9290 state
->received_param
+= pcnt
;
9291 state
->received_data
+= dcnt
;
9293 if ((state
->received_data
> state
->total_data
) ||
9294 (state
->received_param
> state
->total_param
))
9298 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9299 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9302 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9306 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9307 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9310 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9313 if ((state
->received_param
< state
->total_param
) ||
9314 (state
->received_data
< state
->total_data
)) {
9315 END_PROFILE(SMBtranss2
);
9319 handle_trans2(conn
, req
, state
);
9321 DLIST_REMOVE(conn
->pending_trans
, state
);
9322 SAFE_FREE(state
->data
);
9323 SAFE_FREE(state
->param
);
9326 END_PROFILE(SMBtranss2
);
9331 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9332 DLIST_REMOVE(conn
->pending_trans
, state
);
9333 SAFE_FREE(state
->data
);
9334 SAFE_FREE(state
->param
);
9336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9337 END_PROFILE(SMBtranss2
);