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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS
check_access(connection_struct
*conn
,
60 const struct smb_filename
*smb_fname
,
64 if (!(fsp
->access_mask
& access_mask
)) {
65 return NT_STATUS_ACCESS_DENIED
;
68 NTSTATUS status
= smbd_check_access_rights(conn
,
72 if (!NT_STATUS_IS_OK(status
)) {
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
86 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type
= get_remote_arch();
90 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
91 val
= SMB_ROUNDUP(val
,rval
);
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
105 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
106 return (uint64_t)psbuf
->st_ex_ino
;
108 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
109 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name
)
123 static const char * const prohibited_ea_names
[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME
,
125 SAMBA_XATTR_DOS_ATTRIB
,
133 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
134 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
137 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
149 files_struct
*fsp
, const char *fname
,
150 const char *ea_name
, struct ea_struct
*pea
)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size
= 256;
159 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
161 return NT_STATUS_NO_MEMORY
;
164 if (fsp
&& fsp
->fh
->fd
!= -1) {
165 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
167 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
170 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
176 return map_nt_error_from_unix(errno
);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
180 dump_data(10, (uint8
*)val
, sizeret
);
183 if (strnequal(ea_name
, "user.", 5)) {
184 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
186 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
188 if (pea
->name
== NULL
) {
190 return NT_STATUS_NO_MEMORY
;
192 pea
->value
.data
= (unsigned char *)val
;
193 pea
->value
.length
= (size_t)sizeret
;
197 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
198 files_struct
*fsp
, const char *fname
,
199 char ***pnames
, size_t *pnum_names
)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size
= 1024;
203 char *ea_namelist
= NULL
;
208 ssize_t sizeret
= -1;
210 if (!lp_ea_support(SNUM(conn
))) {
219 * TALLOC the result early to get the talloc hierarchy right.
222 names
= talloc_array(mem_ctx
, char *, 1);
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY
;
228 while (ea_namelist_size
<= 65536) {
230 ea_namelist
= talloc_realloc(
231 names
, ea_namelist
, char, ea_namelist_size
);
232 if (ea_namelist
== NULL
) {
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY
;
238 if (fsp
&& fsp
->fh
->fd
!= -1) {
239 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
242 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
246 if ((sizeret
== -1) && (errno
== ERANGE
)) {
247 ea_namelist_size
*= 2;
256 return map_nt_error_from_unix(errno
);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret
));
272 * Ensure the result is 0-terminated
275 if (ea_namelist
[sizeret
-1] != '\0') {
277 return NT_STATUS_INTERNAL_ERROR
;
285 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
289 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
291 DEBUG(0, ("talloc failed\n"));
293 return NT_STATUS_NO_MEMORY
;
299 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
300 names
[num_names
++] = p
;
308 *pnum_names
= num_names
;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
317 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
319 /* Get a list of all xattrs. Max namesize is 64k. */
322 struct ea_list
*ea_list_head
= NULL
;
327 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
330 if (!NT_STATUS_IS_OK(status
)) {
334 if (num_names
== 0) {
339 for (i
=0; i
<num_names
; i
++) {
340 struct ea_list
*listp
;
343 if (strnequal(names
[i
], "system.", 7)
344 || samba_private_attr_name(names
[i
]))
347 listp
= talloc(mem_ctx
, struct ea_list
);
349 return NT_STATUS_NO_MEMORY
;
352 status
= get_ea_value(mem_ctx
, conn
, fsp
,
356 if (!NT_STATUS_IS_OK(status
)) {
360 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
363 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
365 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
366 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
367 (unsigned int)listp
->ea
.value
.length
));
369 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
373 /* Add on 4 for total length. */
374 if (*pea_total_len
) {
378 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
379 (unsigned int)*pea_total_len
));
381 *ea_list
= ea_list_head
;
385 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
386 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
391 if (!lp_ea_support(SNUM(conn
))) {
395 if (is_ntfs_stream_smb_fname(smb_fname
)) {
396 return NT_STATUS_INVALID_PARAMETER
;
399 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
402 /****************************************************************************
403 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
405 ****************************************************************************/
407 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
408 connection_struct
*conn
, struct ea_list
*ea_list
)
410 unsigned int ret_data_size
= 4;
413 SMB_ASSERT(total_data_size
>= 4);
415 if (!lp_ea_support(SNUM(conn
))) {
420 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
423 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
424 dos_namelen
= strlen(dos_ea_name
);
425 if (dos_namelen
> 255 || dos_namelen
== 0) {
428 if (ea_list
->ea
.value
.length
> 65535) {
431 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
435 /* We know we have room. */
436 SCVAL(p
,0,ea_list
->ea
.flags
);
437 SCVAL(p
,1,dos_namelen
);
438 SSVAL(p
,2,ea_list
->ea
.value
.length
);
439 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
440 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
442 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
443 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
446 ret_data_size
= PTR_DIFF(p
, pdata
);
447 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
448 SIVAL(pdata
,0,ret_data_size
);
449 return ret_data_size
;
452 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
454 unsigned int total_data_size
,
455 unsigned int *ret_data_size
,
456 connection_struct
*conn
,
457 struct ea_list
*ea_list
)
459 uint8_t *p
= (uint8_t *)pdata
;
460 uint8_t *last_start
= NULL
;
464 if (!lp_ea_support(SNUM(conn
))) {
465 return NT_STATUS_NO_EAS_ON_FILE
;
468 for (; ea_list
; ea_list
= ea_list
->next
) {
474 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
478 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
479 dos_namelen
= strlen(dos_ea_name
);
480 if (dos_namelen
> 255 || dos_namelen
== 0) {
481 return NT_STATUS_INTERNAL_ERROR
;
483 if (ea_list
->ea
.value
.length
> 65535) {
484 return NT_STATUS_INTERNAL_ERROR
;
487 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
490 size_t pad
= 4 - (this_size
% 4);
494 if (this_size
> total_data_size
) {
495 return NT_STATUS_INFO_LENGTH_MISMATCH
;
498 /* We know we have room. */
499 SIVAL(p
, 0x00, 0); /* next offset */
500 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
501 SCVAL(p
, 0x05, dos_namelen
);
502 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
503 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
504 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
506 total_data_size
-= this_size
;
510 *ret_data_size
= PTR_DIFF(p
, pdata
);
511 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
515 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
517 size_t total_ea_len
= 0;
519 struct ea_list
*ea_list
;
521 if (!lp_ea_support(SNUM(conn
))) {
524 mem_ctx
= talloc_stackframe();
526 /* If this is a stream fsp, then we need to instead find the
527 * estimated ea len from the main file, not the stream
528 * (streams cannot have EAs), but the estimate isn't just 0 in
530 if (is_ntfs_stream_smb_fname(smb_fname
)) {
533 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
534 TALLOC_FREE(mem_ctx
);
538 /****************************************************************************
539 Ensure the EA name is case insensitive by matching any existing EA name.
540 ****************************************************************************/
542 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
545 TALLOC_CTX
*mem_ctx
= talloc_tos();
546 struct ea_list
*ea_list
;
547 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
548 if (!NT_STATUS_IS_OK(status
)) {
552 for (; ea_list
; ea_list
= ea_list
->next
) {
553 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
554 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
555 &unix_ea_name
[5], ea_list
->ea
.name
));
556 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
562 /****************************************************************************
563 Set or delete an extended attribute.
564 ****************************************************************************/
566 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
567 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
572 if (!lp_ea_support(SNUM(conn
))) {
573 return NT_STATUS_EAS_NOT_SUPPORTED
;
576 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
577 if (!NT_STATUS_IS_OK(status
)) {
581 /* Setting EAs on streams isn't supported. */
582 if (is_ntfs_stream_smb_fname(smb_fname
)) {
583 return NT_STATUS_INVALID_PARAMETER
;
586 fname
= smb_fname
->base_name
;
588 for (;ea_list
; ea_list
= ea_list
->next
) {
590 fstring unix_ea_name
;
592 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
593 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
595 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
597 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
599 if (samba_private_attr_name(unix_ea_name
)) {
600 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
601 return NT_STATUS_ACCESS_DENIED
;
604 if (ea_list
->ea
.value
.length
== 0) {
605 /* Remove the attribute. */
606 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
607 DEBUG(10,("set_ea: deleting ea name %s on "
608 "file %s by file descriptor.\n",
609 unix_ea_name
, fsp_str_dbg(fsp
)));
610 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
612 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
613 unix_ea_name
, fname
));
614 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
617 /* Removing a non existent attribute always succeeds. */
618 if (ret
== -1 && errno
== ENOATTR
) {
619 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
625 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
626 DEBUG(10,("set_ea: setting ea name %s on file "
627 "%s by file descriptor.\n",
628 unix_ea_name
, fsp_str_dbg(fsp
)));
629 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
630 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
632 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
633 unix_ea_name
, fname
));
634 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
635 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
641 if (errno
== ENOTSUP
) {
642 return NT_STATUS_EAS_NOT_SUPPORTED
;
645 return map_nt_error_from_unix(errno
);
651 /****************************************************************************
652 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
653 ****************************************************************************/
655 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
657 struct ea_list
*ea_list_head
= NULL
;
658 size_t converted_size
, offset
= 0;
660 while (offset
+ 2 < data_size
) {
661 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
662 unsigned int namelen
= CVAL(pdata
,offset
);
664 offset
++; /* Go past the namelen byte. */
666 /* integer wrap paranioa. */
667 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
668 (offset
> data_size
) || (namelen
> data_size
) ||
669 (offset
+ namelen
>= data_size
)) {
672 /* Ensure the name is null terminated. */
673 if (pdata
[offset
+ namelen
] != '\0') {
676 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
678 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
679 "failed: %s", strerror(errno
)));
685 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
686 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
687 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
693 /****************************************************************************
694 Read one EA list entry from the buffer.
695 ****************************************************************************/
697 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
699 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
701 unsigned int namelen
;
702 size_t converted_size
;
712 eal
->ea
.flags
= CVAL(pdata
,0);
713 namelen
= CVAL(pdata
,1);
714 val_len
= SVAL(pdata
,2);
716 if (4 + namelen
+ 1 + val_len
> data_size
) {
720 /* Ensure the name is null terminated. */
721 if (pdata
[namelen
+ 4] != '\0') {
724 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
725 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
732 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
733 if (!eal
->ea
.value
.data
) {
737 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
739 /* Ensure we're null terminated just in case we print the value. */
740 eal
->ea
.value
.data
[val_len
] = '\0';
741 /* But don't count the null. */
742 eal
->ea
.value
.length
--;
745 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
748 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
749 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
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
,
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send
= datasize
;
854 int params_to_send
= paramsize
;
856 const char *pp
= params
;
857 const char *pd
= pdata
;
858 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
859 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset
= 0;
861 bool overflow
= False
;
862 struct smbd_server_connection
*sconn
= req
->sconn
;
863 int max_send
= sconn
->smb1
.sessions
.max_send
;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
870 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes
, datasize
));
873 datasize
= data_to_send
= max_data_bytes
;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send
== 0 && data_to_send
== 0) {
880 reply_outbuf(req
, 10, 0);
881 show_msg((char *)req
->outbuf
);
882 if (!srv_send_smb(sconn
,
885 IS_CONN_ENCRYPTED(conn
),
887 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
889 TALLOC_FREE(req
->outbuf
);
893 /* When sending params and data ensure that both are nicely aligned */
894 /* Only do this alignment when there is also data to send - else
895 can cause NT redirector problems. */
897 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
898 data_alignment_offset
= 4 - (params_to_send
% 4);
900 /* Space is bufsize minus Netbios over TCP header minus SMB header */
901 /* The alignment_offset is to align the param bytes on an even byte
902 boundary. NT 4.0 Beta needs this to work correctly. */
904 useable_space
= max_send
- (smb_size
907 + data_alignment_offset
);
909 if (useable_space
< 0) {
910 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
911 "= %d!!!", useable_space
));
912 exit_server_cleanly("send_trans2_replies: Not enough space");
915 while (params_to_send
|| data_to_send
) {
916 /* Calculate whether we will totally or partially fill this packet */
918 total_sent_thistime
= params_to_send
+ data_to_send
;
920 /* We can never send more than useable_space */
922 * Note that 'useable_space' does not include the alignment offsets,
923 * but we must include the alignment offsets in the calculation of
924 * the length of the data we send over the wire, as the alignment offsets
925 * are sent here. Fix from Marc_Jacobsen@hp.com.
928 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
930 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
931 + data_alignment_offset
);
933 /* Set total params and data to be sent */
934 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
935 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
937 /* Calculate how many parameters and data we can fit into
938 * this packet. Parameters get precedence
941 params_sent_thistime
= MIN(params_to_send
,useable_space
);
942 data_sent_thistime
= useable_space
- params_sent_thistime
;
943 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
945 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
947 /* smb_proff is the offset from the start of the SMB header to the
948 parameter bytes, however the first 4 bytes of outbuf are
949 the Netbios over TCP header. Thus use smb_base() to subtract
950 them from the calculation */
952 SSVAL(req
->outbuf
,smb_proff
,
953 ((smb_buf(req
->outbuf
)+alignment_offset
)
954 - smb_base(req
->outbuf
)));
956 if(params_sent_thistime
== 0)
957 SSVAL(req
->outbuf
,smb_prdisp
,0);
959 /* Absolute displacement of param bytes sent in this packet */
960 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
962 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
963 if(data_sent_thistime
== 0) {
964 SSVAL(req
->outbuf
,smb_droff
,0);
965 SSVAL(req
->outbuf
,smb_drdisp
, 0);
967 /* The offset of the data bytes is the offset of the
968 parameter bytes plus the number of parameters being sent this time */
969 SSVAL(req
->outbuf
, smb_droff
,
970 ((smb_buf(req
->outbuf
)+alignment_offset
)
971 - smb_base(req
->outbuf
))
972 + params_sent_thistime
+ data_alignment_offset
);
973 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
976 /* Initialize the padding for alignment */
978 if (alignment_offset
!= 0) {
979 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
982 /* Copy the param bytes into the packet */
984 if(params_sent_thistime
) {
985 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
986 params_sent_thistime
);
989 /* Copy in the data bytes */
990 if(data_sent_thistime
) {
991 if (data_alignment_offset
!= 0) {
992 memset((smb_buf(req
->outbuf
)+alignment_offset
+
993 params_sent_thistime
), 0,
994 data_alignment_offset
);
996 memcpy(smb_buf(req
->outbuf
)+alignment_offset
997 +params_sent_thistime
+data_alignment_offset
,
998 pd
,data_sent_thistime
);
1001 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1002 params_sent_thistime
, data_sent_thistime
, useable_space
));
1003 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1004 params_to_send
, data_to_send
, paramsize
, datasize
));
1007 error_packet_set((char *)req
->outbuf
,
1008 ERRDOS
,ERRbufferoverflow
,
1009 STATUS_BUFFER_OVERFLOW
,
1013 /* Send the packet */
1014 show_msg((char *)req
->outbuf
);
1015 if (!srv_send_smb(sconn
,
1016 (char *)req
->outbuf
,
1017 true, req
->seqnum
+1,
1018 IS_CONN_ENCRYPTED(conn
),
1020 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1022 TALLOC_FREE(req
->outbuf
);
1024 pp
+= params_sent_thistime
;
1025 pd
+= data_sent_thistime
;
1027 params_to_send
-= params_sent_thistime
;
1028 data_to_send
-= data_sent_thistime
;
1031 if(params_to_send
< 0 || data_to_send
< 0) {
1032 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1033 params_to_send
, data_to_send
));
1041 /****************************************************************************
1042 Reply to a TRANSACT2_OPEN.
1043 ****************************************************************************/
1045 static void call_trans2open(connection_struct
*conn
,
1046 struct smb_request
*req
,
1047 char **pparams
, int total_params
,
1048 char **ppdata
, int total_data
,
1049 unsigned int max_data_bytes
)
1051 struct smb_filename
*smb_fname
= NULL
;
1052 char *params
= *pparams
;
1053 char *pdata
= *ppdata
;
1056 bool oplock_request
;
1058 bool return_additional_info
;
1067 int fattr
=0,mtime
=0;
1068 SMB_INO_T inode
= 0;
1071 struct ea_list
*ea_list
= NULL
;
1076 uint32 create_disposition
;
1077 uint32 create_options
= 0;
1078 uint32_t private_flags
= 0;
1079 TALLOC_CTX
*ctx
= talloc_tos();
1082 * Ensure we have enough parameters to perform the operation.
1085 if (total_params
< 29) {
1086 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1090 flags
= SVAL(params
, 0);
1091 deny_mode
= SVAL(params
, 2);
1092 open_attr
= SVAL(params
,6);
1093 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1094 if (oplock_request
) {
1095 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1099 return_additional_info
= BITSETW(params
,0);
1100 open_sattr
= SVAL(params
, 4);
1101 open_time
= make_unix_date3(params
+8);
1103 open_ofun
= SVAL(params
,12);
1104 open_size
= IVAL(params
,14);
1105 pname
= ¶ms
[28];
1108 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1112 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1113 total_params
- 28, STR_TERMINATE
,
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 reply_nterror(req
, status
);
1120 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1121 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1122 (unsigned int)open_ofun
, open_size
));
1124 status
= filename_convert(ctx
,
1126 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1133 reply_botherror(req
,
1134 NT_STATUS_PATH_NOT_COVERED
,
1135 ERRSRV
, ERRbadpath
);
1138 reply_nterror(req
, status
);
1142 if (open_ofun
== 0) {
1143 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1147 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1149 &access_mask
, &share_mode
,
1150 &create_disposition
,
1153 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1157 /* Any data in this call is an EA list. */
1158 if (total_data
&& (total_data
!= 4)) {
1159 if (total_data
< 10) {
1160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1164 if (IVAL(pdata
,0) > total_data
) {
1165 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1166 IVAL(pdata
,0), (unsigned int)total_data
));
1167 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1171 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1178 if (!lp_ea_support(SNUM(conn
))) {
1179 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1184 status
= SMB_VFS_CREATE_FILE(
1187 0, /* root_dir_fid */
1188 smb_fname
, /* fname */
1189 access_mask
, /* access_mask */
1190 share_mode
, /* share_access */
1191 create_disposition
, /* create_disposition*/
1192 create_options
, /* create_options */
1193 open_attr
, /* file_attributes */
1194 oplock_request
, /* oplock_request */
1195 open_size
, /* allocation_size */
1198 ea_list
, /* ea_list */
1200 &smb_action
); /* psbuf */
1202 if (!NT_STATUS_IS_OK(status
)) {
1203 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1204 /* We have re-scheduled this call. */
1207 reply_openerror(req
, status
);
1211 size
= get_file_size_stat(&smb_fname
->st
);
1212 fattr
= dos_mode(conn
, smb_fname
);
1213 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1214 inode
= smb_fname
->st
.st_ex_ino
;
1215 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1216 close_file(req
, fsp
, ERROR_CLOSE
);
1217 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1221 /* Realloc the size of parameters and data we will return */
1222 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1223 if(*pparams
== NULL
) {
1224 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1229 SSVAL(params
,0,fsp
->fnum
);
1230 SSVAL(params
,2,fattr
);
1231 srv_put_dos_date2(params
,4, mtime
);
1232 SIVAL(params
,8, (uint32
)size
);
1233 SSVAL(params
,12,deny_mode
);
1234 SSVAL(params
,14,0); /* open_type - file or directory. */
1235 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1237 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1238 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1241 SSVAL(params
,18,smb_action
);
1244 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1246 SIVAL(params
,20,inode
);
1247 SSVAL(params
,24,0); /* Padding. */
1249 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1251 SIVAL(params
, 26, ea_size
);
1253 SIVAL(params
, 26, 0);
1256 /* Send the required number of replies */
1257 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1259 TALLOC_FREE(smb_fname
);
1262 /*********************************************************
1263 Routine to check if a given string matches exactly.
1264 as a special case a mask of "." does NOT match. That
1265 is required for correct wildcard semantics
1266 Case can be significant or not.
1267 **********************************************************/
1269 static bool exact_match(bool has_wild
,
1270 bool case_sensitive
,
1274 if (mask
[0] == '.' && mask
[1] == 0) {
1282 if (case_sensitive
) {
1283 return strcmp(str
,mask
)==0;
1285 return strcasecmp_m(str
,mask
) == 0;
1289 /****************************************************************************
1290 Return the filetype for UNIX extensions.
1291 ****************************************************************************/
1293 static uint32
unix_filetype(mode_t mode
)
1296 return UNIX_TYPE_FILE
;
1297 else if(S_ISDIR(mode
))
1298 return UNIX_TYPE_DIR
;
1300 else if(S_ISLNK(mode
))
1301 return UNIX_TYPE_SYMLINK
;
1304 else if(S_ISCHR(mode
))
1305 return UNIX_TYPE_CHARDEV
;
1308 else if(S_ISBLK(mode
))
1309 return UNIX_TYPE_BLKDEV
;
1312 else if(S_ISFIFO(mode
))
1313 return UNIX_TYPE_FIFO
;
1316 else if(S_ISSOCK(mode
))
1317 return UNIX_TYPE_SOCKET
;
1320 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1321 return UNIX_TYPE_UNKNOWN
;
1324 /****************************************************************************
1325 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1326 ****************************************************************************/
1328 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1330 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1331 const SMB_STRUCT_STAT
*psbuf
,
1333 enum perm_type ptype
,
1338 if (perms
== SMB_MODE_NO_CHANGE
) {
1339 if (!VALID_STAT(*psbuf
)) {
1340 return NT_STATUS_INVALID_PARAMETER
;
1342 *ret_perms
= psbuf
->st_ex_mode
;
1343 return NT_STATUS_OK
;
1347 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1348 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1349 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1350 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1351 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1352 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1353 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1354 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1355 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1357 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1360 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1363 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1368 /* Apply mode mask */
1369 ret
&= lp_create_mask(SNUM(conn
));
1370 /* Add in force bits */
1371 ret
|= lp_force_create_mode(SNUM(conn
));
1374 ret
&= lp_dir_mask(SNUM(conn
));
1375 /* Add in force bits */
1376 ret
|= lp_force_dir_mode(SNUM(conn
));
1378 case PERM_EXISTING_FILE
:
1379 /* Apply mode mask */
1380 ret
&= lp_security_mask(SNUM(conn
));
1381 /* Add in force bits */
1382 ret
|= lp_force_security_mode(SNUM(conn
));
1384 case PERM_EXISTING_DIR
:
1385 /* Apply mode mask */
1386 ret
&= lp_dir_security_mask(SNUM(conn
));
1387 /* Add in force bits */
1388 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1393 return NT_STATUS_OK
;
1396 /****************************************************************************
1397 Needed to show the msdfs symlinks as directories. Modifies psbuf
1398 to be a directory if it's a msdfs link.
1399 ****************************************************************************/
1401 static bool check_msdfs_link(connection_struct
*conn
,
1402 const char *pathname
,
1403 SMB_STRUCT_STAT
*psbuf
)
1405 int saved_errno
= errno
;
1406 if(lp_host_msdfs() &&
1407 lp_msdfs_root(SNUM(conn
)) &&
1408 is_msdfs_link(conn
, pathname
, psbuf
)) {
1410 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1413 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1414 errno
= saved_errno
;
1417 errno
= saved_errno
;
1422 /****************************************************************************
1423 Get a level dependent lanman2 dir entry.
1424 ****************************************************************************/
1426 struct smbd_dirptr_lanman2_state
{
1427 connection_struct
*conn
;
1428 uint32_t info_level
;
1429 bool check_mangled_names
;
1431 bool got_exact_match
;
1434 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1440 struct smbd_dirptr_lanman2_state
*state
=
1441 (struct smbd_dirptr_lanman2_state
*)private_data
;
1443 char mangled_name
[13]; /* mangled 8.3 name. */
1447 /* Mangle fname if it's an illegal name. */
1448 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1449 ok
= name_to_8_3(dname
, mangled_name
,
1450 true, state
->conn
->params
);
1454 fname
= mangled_name
;
1459 got_match
= exact_match(state
->has_wild
,
1460 state
->conn
->case_sensitive
,
1462 state
->got_exact_match
= got_match
;
1464 got_match
= mask_match(fname
, mask
,
1465 state
->conn
->case_sensitive
);
1468 if(!got_match
&& state
->check_mangled_names
&&
1469 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1471 * It turns out that NT matches wildcards against
1472 * both long *and* short names. This may explain some
1473 * of the wildcard wierdness from old DOS clients
1474 * that some people have been seeing.... JRA.
1476 /* Force the mangling into 8.3. */
1477 ok
= name_to_8_3(fname
, mangled_name
,
1478 false, state
->conn
->params
);
1483 got_match
= exact_match(state
->has_wild
,
1484 state
->conn
->case_sensitive
,
1485 mangled_name
, mask
);
1486 state
->got_exact_match
= got_match
;
1488 got_match
= mask_match(mangled_name
, mask
,
1489 state
->conn
->case_sensitive
);
1497 *_fname
= talloc_strdup(ctx
, fname
);
1498 if (*_fname
== NULL
) {
1505 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1507 struct smb_filename
*smb_fname
,
1510 struct smbd_dirptr_lanman2_state
*state
=
1511 (struct smbd_dirptr_lanman2_state
*)private_data
;
1512 bool ms_dfs_link
= false;
1515 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1516 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1517 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1518 "Couldn't lstat [%s] (%s)\n",
1519 smb_fname_str_dbg(smb_fname
),
1523 } else if (!VALID_STAT(smb_fname
->st
) &&
1524 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1525 /* Needed to show the msdfs symlinks as
1528 ms_dfs_link
= check_msdfs_link(state
->conn
,
1529 smb_fname
->base_name
,
1532 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1533 "Couldn't stat [%s] (%s)\n",
1534 smb_fname_str_dbg(smb_fname
),
1541 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1543 mode
= dos_mode(state
->conn
, smb_fname
);
1550 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1551 connection_struct
*conn
,
1553 uint32_t info_level
,
1554 struct ea_list
*name_list
,
1555 bool check_mangled_names
,
1556 bool requires_resume_key
,
1559 const struct smb_filename
*smb_fname
,
1560 int space_remaining
,
1567 uint64_t *last_entry_off
)
1569 char *p
, *q
, *pdata
= *ppdata
;
1571 uint64_t file_size
= 0;
1572 uint64_t allocation_size
= 0;
1573 uint64_t file_index
= 0;
1575 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1576 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1578 char *last_entry_ptr
;
1583 *out_of_space
= false;
1585 ZERO_STRUCT(mdate_ts
);
1586 ZERO_STRUCT(adate_ts
);
1587 ZERO_STRUCT(create_date_ts
);
1588 ZERO_STRUCT(cdate_ts
);
1590 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1591 file_size
= get_file_size_stat(&smb_fname
->st
);
1593 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1595 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1597 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1598 adate_ts
= smb_fname
->st
.st_ex_atime
;
1599 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1600 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1602 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1603 dos_filetime_timespec(&create_date_ts
);
1604 dos_filetime_timespec(&mdate_ts
);
1605 dos_filetime_timespec(&adate_ts
);
1606 dos_filetime_timespec(&cdate_ts
);
1609 create_date
= convert_timespec_to_time_t(create_date_ts
);
1610 mdate
= convert_timespec_to_time_t(mdate_ts
);
1611 adate
= convert_timespec_to_time_t(adate_ts
);
1613 /* align the record */
1614 SMB_ASSERT(align
>= 1);
1616 off
= (int)PTR_DIFF(pdata
, base_data
);
1617 pad
= (off
+ (align
-1)) & ~(align
-1);
1620 if (pad
&& pad
> space_remaining
) {
1621 *out_of_space
= true;
1622 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1623 "for padding (wanted %u, had %d)\n",
1626 return false; /* Not finished - just out of space */
1630 /* initialize padding to 0 */
1632 memset(pdata
, 0, pad
);
1634 space_remaining
-= pad
;
1636 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1646 switch (info_level
) {
1647 case SMB_FIND_INFO_STANDARD
:
1648 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1649 if(requires_resume_key
) {
1653 srv_put_dos_date2(p
,0,create_date
);
1654 srv_put_dos_date2(p
,4,adate
);
1655 srv_put_dos_date2(p
,8,mdate
);
1656 SIVAL(p
,12,(uint32
)file_size
);
1657 SIVAL(p
,16,(uint32
)allocation_size
);
1661 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1662 p
+= ucs2_align(base_data
, p
, 0);
1664 len
= srvstr_push(base_data
, flags2
, p
,
1665 fname
, PTR_DIFF(end_data
, p
),
1667 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1669 SCVAL(nameptr
, -1, len
- 2);
1671 SCVAL(nameptr
, -1, 0);
1675 SCVAL(nameptr
, -1, len
- 1);
1677 SCVAL(nameptr
, -1, 0);
1683 case SMB_FIND_EA_SIZE
:
1684 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1685 if (requires_resume_key
) {
1689 srv_put_dos_date2(p
,0,create_date
);
1690 srv_put_dos_date2(p
,4,adate
);
1691 srv_put_dos_date2(p
,8,mdate
);
1692 SIVAL(p
,12,(uint32
)file_size
);
1693 SIVAL(p
,16,(uint32
)allocation_size
);
1696 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1698 SIVAL(p
,22,ea_size
); /* Extended attributes */
1702 len
= srvstr_push(base_data
, flags2
,
1703 p
, fname
, PTR_DIFF(end_data
, p
),
1704 STR_TERMINATE
| STR_NOALIGN
);
1705 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1718 SCVAL(nameptr
,0,len
);
1720 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1723 case SMB_FIND_EA_LIST
:
1725 struct ea_list
*file_list
= NULL
;
1729 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1733 if (requires_resume_key
) {
1737 srv_put_dos_date2(p
,0,create_date
);
1738 srv_put_dos_date2(p
,4,adate
);
1739 srv_put_dos_date2(p
,8,mdate
);
1740 SIVAL(p
,12,(uint32
)file_size
);
1741 SIVAL(p
,16,(uint32
)allocation_size
);
1743 p
+= 22; /* p now points to the EA area. */
1745 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1747 &ea_len
, &file_list
);
1748 if (!NT_STATUS_IS_OK(status
)) {
1751 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1753 /* We need to determine if this entry will fit in the space available. */
1754 /* Max string size is 255 bytes. */
1755 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1756 *out_of_space
= true;
1757 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1758 "(wanted %u, had %d)\n",
1759 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1761 return False
; /* Not finished - just out of space */
1764 /* Push the ea_data followed by the name. */
1765 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1767 len
= srvstr_push(base_data
, flags2
,
1768 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1769 STR_TERMINATE
| STR_NOALIGN
);
1770 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1783 SCVAL(nameptr
,0,len
);
1785 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1789 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1790 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1791 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1793 SIVAL(p
,0,reskey
); p
+= 4;
1794 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1795 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1796 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1797 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1798 SOFF_T(p
,0,file_size
); p
+= 8;
1799 SOFF_T(p
,0,allocation_size
); p
+= 8;
1800 SIVAL(p
,0,mode
); p
+= 4;
1801 q
= p
; p
+= 4; /* q is placeholder for name length. */
1803 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1805 SIVAL(p
,0,ea_size
); /* Extended attributes */
1808 /* Clear the short name buffer. This is
1809 * IMPORTANT as not doing so will trigger
1810 * a Win2k client bug. JRA.
1812 if (!was_8_3
&& check_mangled_names
) {
1813 char mangled_name
[13]; /* mangled 8.3 name. */
1814 if (!name_to_8_3(fname
,mangled_name
,True
,
1816 /* Error - mangle failed ! */
1817 memset(mangled_name
,'\0',12);
1819 mangled_name
[12] = 0;
1820 len
= srvstr_push(base_data
, flags2
,
1821 p
+2, mangled_name
, 24,
1822 STR_UPPER
|STR_UNICODE
);
1824 memset(p
+ 2 + len
,'\0',24 - len
);
1831 len
= srvstr_push(base_data
, flags2
, p
,
1832 fname
, PTR_DIFF(end_data
, p
),
1833 STR_TERMINATE_ASCII
);
1837 len
= PTR_DIFF(p
, pdata
);
1838 pad
= (len
+ (align
-1)) & ~(align
-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1846 * set padding to zero
1849 memset(p
, 0, pad
- len
);
1856 case SMB_FIND_FILE_DIRECTORY_INFO
:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1859 SIVAL(p
,0,reskey
); p
+= 4;
1860 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1862 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1863 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1864 SOFF_T(p
,0,file_size
); p
+= 8;
1865 SOFF_T(p
,0,allocation_size
); p
+= 8;
1866 SIVAL(p
,0,mode
); p
+= 4;
1867 len
= srvstr_push(base_data
, flags2
,
1868 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1869 STR_TERMINATE_ASCII
);
1873 len
= PTR_DIFF(p
, pdata
);
1874 pad
= (len
+ (align
-1)) & ~(align
-1);
1876 * offset to the next entry, the caller
1877 * will overwrite it for the last entry
1878 * that's why we always include the padding
1882 * set padding to zero
1885 memset(p
, 0, pad
- len
);
1892 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1893 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1895 SIVAL(p
,0,reskey
); p
+= 4;
1896 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1897 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1898 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1899 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1900 SOFF_T(p
,0,file_size
); p
+= 8;
1901 SOFF_T(p
,0,allocation_size
); p
+= 8;
1902 SIVAL(p
,0,mode
); p
+= 4;
1903 q
= p
; p
+= 4; /* q is placeholder for name length. */
1905 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1907 SIVAL(p
,0,ea_size
); /* Extended attributes */
1910 len
= srvstr_push(base_data
, flags2
, p
,
1911 fname
, PTR_DIFF(end_data
, p
),
1912 STR_TERMINATE_ASCII
);
1916 len
= PTR_DIFF(p
, pdata
);
1917 pad
= (len
+ (align
-1)) & ~(align
-1);
1919 * offset to the next entry, the caller
1920 * will overwrite it for the last entry
1921 * that's why we always include the padding
1925 * set padding to zero
1928 memset(p
, 0, pad
- len
);
1935 case SMB_FIND_FILE_NAMES_INFO
:
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1938 SIVAL(p
,0,reskey
); p
+= 4;
1940 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1941 acl on a dir (tridge) */
1942 len
= srvstr_push(base_data
, flags2
, p
,
1943 fname
, PTR_DIFF(end_data
, p
),
1944 STR_TERMINATE_ASCII
);
1948 len
= PTR_DIFF(p
, pdata
);
1949 pad
= (len
+ (align
-1)) & ~(align
-1);
1951 * offset to the next entry, the caller
1952 * will overwrite it for the last entry
1953 * that's why we always include the padding
1957 * set padding to zero
1960 memset(p
, 0, pad
- len
);
1967 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1968 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1970 SIVAL(p
,0,reskey
); p
+= 4;
1971 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1972 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1973 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1974 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1975 SOFF_T(p
,0,file_size
); p
+= 8;
1976 SOFF_T(p
,0,allocation_size
); p
+= 8;
1977 SIVAL(p
,0,mode
); p
+= 4;
1978 q
= p
; p
+= 4; /* q is placeholder for name length. */
1980 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1982 SIVAL(p
,0,ea_size
); /* Extended attributes */
1985 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1986 SBVAL(p
,0,file_index
); p
+= 8;
1987 len
= srvstr_push(base_data
, flags2
, p
,
1988 fname
, PTR_DIFF(end_data
, p
),
1989 STR_TERMINATE_ASCII
);
1993 len
= PTR_DIFF(p
, pdata
);
1994 pad
= (len
+ (align
-1)) & ~(align
-1);
1996 * offset to the next entry, the caller
1997 * will overwrite it for the last entry
1998 * that's why we always include the padding
2002 * set padding to zero
2005 memset(p
, 0, pad
- len
);
2012 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2013 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2014 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2016 SIVAL(p
,0,reskey
); p
+= 4;
2017 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2018 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2019 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2020 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2021 SOFF_T(p
,0,file_size
); p
+= 8;
2022 SOFF_T(p
,0,allocation_size
); p
+= 8;
2023 SIVAL(p
,0,mode
); p
+= 4;
2024 q
= p
; p
+= 4; /* q is placeholder for name length */
2026 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2028 SIVAL(p
,0,ea_size
); /* Extended attributes */
2031 /* Clear the short name buffer. This is
2032 * IMPORTANT as not doing so will trigger
2033 * a Win2k client bug. JRA.
2035 if (!was_8_3
&& check_mangled_names
) {
2036 char mangled_name
[13]; /* mangled 8.3 name. */
2037 if (!name_to_8_3(fname
,mangled_name
,True
,
2039 /* Error - mangle failed ! */
2040 memset(mangled_name
,'\0',12);
2042 mangled_name
[12] = 0;
2043 len
= srvstr_push(base_data
, flags2
,
2044 p
+2, mangled_name
, 24,
2045 STR_UPPER
|STR_UNICODE
);
2048 memset(p
+ 2 + len
,'\0',24 - len
);
2055 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2056 SBVAL(p
,0,file_index
); p
+= 8;
2057 len
= srvstr_push(base_data
, flags2
, p
,
2058 fname
, PTR_DIFF(end_data
, p
),
2059 STR_TERMINATE_ASCII
);
2063 len
= PTR_DIFF(p
, pdata
);
2064 pad
= (len
+ (align
-1)) & ~(align
-1);
2066 * offset to the next entry, the caller
2067 * will overwrite it for the last entry
2068 * that's why we always include the padding
2072 * set padding to zero
2075 memset(p
, 0, pad
- len
);
2082 /* CIFS UNIX Extension. */
2084 case SMB_FIND_FILE_UNIX
:
2085 case SMB_FIND_FILE_UNIX_INFO2
:
2087 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2089 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2091 if (info_level
== SMB_FIND_FILE_UNIX
) {
2092 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2093 p
= store_file_unix_basic(conn
, p
,
2094 NULL
, &smb_fname
->st
);
2095 len
= srvstr_push(base_data
, flags2
, p
,
2096 fname
, PTR_DIFF(end_data
, p
),
2099 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2100 p
= store_file_unix_basic_info2(conn
, p
,
2101 NULL
, &smb_fname
->st
);
2104 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2105 PTR_DIFF(end_data
, p
), 0);
2106 SIVAL(nameptr
, 0, len
);
2111 len
= PTR_DIFF(p
, pdata
);
2112 pad
= (len
+ (align
-1)) & ~(align
-1);
2114 * offset to the next entry, the caller
2115 * will overwrite it for the last entry
2116 * that's why we always include the padding
2120 * set padding to zero
2123 memset(p
, 0, pad
- len
);
2128 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2136 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2137 *out_of_space
= true;
2138 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2139 "(wanted %u, had %d)\n",
2140 (unsigned int)PTR_DIFF(p
,pdata
),
2142 return false; /* Not finished - just out of space */
2145 /* Setup the last entry pointer, as an offset from base_data */
2146 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2147 /* Advance the data pointer to the next slot */
2153 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2154 connection_struct
*conn
,
2155 struct dptr_struct
*dirptr
,
2157 const char *path_mask
,
2160 int requires_resume_key
,
2168 int space_remaining
,
2170 bool *got_exact_match
,
2171 int *_last_entry_off
,
2172 struct ea_list
*name_list
)
2175 const char *mask
= NULL
;
2176 long prev_dirpos
= 0;
2179 struct smb_filename
*smb_fname
= NULL
;
2180 struct smbd_dirptr_lanman2_state state
;
2182 uint64_t last_entry_off
= 0;
2186 state
.info_level
= info_level
;
2187 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2188 state
.has_wild
= dptr_has_wild(dirptr
);
2189 state
.got_exact_match
= false;
2191 *out_of_space
= false;
2192 *got_exact_match
= false;
2194 p
= strrchr_m(path_mask
,'/');
2205 ok
= smbd_dirptr_get_entry(ctx
,
2211 smbd_dirptr_lanman2_match_fn
,
2212 smbd_dirptr_lanman2_mode_fn
,
2222 *got_exact_match
= state
.got_exact_match
;
2224 ok
= smbd_marshall_dir_entry(ctx
,
2229 state
.check_mangled_names
,
2230 requires_resume_key
,
2243 TALLOC_FREE(smb_fname
);
2244 if (*out_of_space
) {
2245 dptr_SeekDir(dirptr
, prev_dirpos
);
2252 *_last_entry_off
= last_entry_off
;
2256 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2257 connection_struct
*conn
,
2258 struct dptr_struct
*dirptr
,
2260 const char *path_mask
,
2263 bool requires_resume_key
,
2269 int space_remaining
,
2271 bool *got_exact_match
,
2272 int *last_entry_off
,
2273 struct ea_list
*name_list
)
2276 const bool do_pad
= true;
2278 if (info_level
>= 1 && info_level
<= 3) {
2279 /* No alignment on earlier info levels. */
2283 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2284 path_mask
, dirtype
, info_level
,
2285 requires_resume_key
, dont_descend
, ask_sharemode
,
2287 ppdata
, base_data
, end_data
,
2289 out_of_space
, got_exact_match
,
2290 last_entry_off
, name_list
);
2293 /****************************************************************************
2294 Reply to a TRANS2_FINDFIRST.
2295 ****************************************************************************/
2297 static void call_trans2findfirst(connection_struct
*conn
,
2298 struct smb_request
*req
,
2299 char **pparams
, int total_params
,
2300 char **ppdata
, int total_data
,
2301 unsigned int max_data_bytes
)
2303 /* We must be careful here that we don't return more than the
2304 allowed number of data bytes. If this means returning fewer than
2305 maxentries then so be it. We assume that the redirector has
2306 enough room for the fixed number of parameter bytes it has
2308 struct smb_filename
*smb_dname
= NULL
;
2309 char *params
= *pparams
;
2310 char *pdata
= *ppdata
;
2314 uint16 findfirst_flags
;
2315 bool close_after_first
;
2317 bool requires_resume_key
;
2319 char *directory
= NULL
;
2322 int last_entry_off
=0;
2326 bool finished
= False
;
2327 bool dont_descend
= False
;
2328 bool out_of_space
= False
;
2329 int space_remaining
;
2330 bool mask_contains_wcard
= False
;
2331 struct ea_list
*ea_list
= NULL
;
2332 NTSTATUS ntstatus
= NT_STATUS_OK
;
2333 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2334 TALLOC_CTX
*ctx
= talloc_tos();
2335 struct dptr_struct
*dirptr
= NULL
;
2336 struct smbd_server_connection
*sconn
= req
->sconn
;
2337 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2338 bool backup_priv
= false;
2340 if (total_params
< 13) {
2341 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2345 dirtype
= SVAL(params
,0);
2346 maxentries
= SVAL(params
,2);
2347 findfirst_flags
= SVAL(params
,4);
2348 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2349 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2350 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2351 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2352 security_token_has_privilege(get_current_nttok(conn
),
2355 info_level
= SVAL(params
,6);
2357 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2358 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2359 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2361 info_level
, max_data_bytes
));
2364 /* W2K3 seems to treat zero as 1. */
2368 switch (info_level
) {
2369 case SMB_FIND_INFO_STANDARD
:
2370 case SMB_FIND_EA_SIZE
:
2371 case SMB_FIND_EA_LIST
:
2372 case SMB_FIND_FILE_DIRECTORY_INFO
:
2373 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2374 case SMB_FIND_FILE_NAMES_INFO
:
2375 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2376 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2377 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2379 case SMB_FIND_FILE_UNIX
:
2380 case SMB_FIND_FILE_UNIX_INFO2
:
2381 /* Always use filesystem for UNIX mtime query. */
2382 ask_sharemode
= false;
2383 if (!lp_unix_extensions()) {
2384 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2387 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2390 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2394 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2395 params
+12, total_params
- 12,
2396 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2397 if (!NT_STATUS_IS_OK(ntstatus
)) {
2398 reply_nterror(req
, ntstatus
);
2404 ntstatus
= filename_convert_with_privilege(ctx
,
2409 &mask_contains_wcard
,
2412 ntstatus
= filename_convert(ctx
, conn
,
2413 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2416 &mask_contains_wcard
,
2420 if (!NT_STATUS_IS_OK(ntstatus
)) {
2421 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2422 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2423 ERRSRV
, ERRbadpath
);
2426 reply_nterror(req
, ntstatus
);
2430 mask
= smb_dname
->original_lcomp
;
2432 directory
= smb_dname
->base_name
;
2434 p
= strrchr_m(directory
,'/');
2436 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2437 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2438 mask
= talloc_strdup(ctx
,"*");
2440 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2443 mask_contains_wcard
= True
;
2449 if (p
== NULL
|| p
== directory
) {
2450 /* Ensure we don't have a directory name of "". */
2451 directory
= talloc_strdup(talloc_tos(), ".");
2453 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2458 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2460 if (info_level
== SMB_FIND_EA_LIST
) {
2463 if (total_data
< 4) {
2464 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2468 ea_size
= IVAL(pdata
,0);
2469 if (ea_size
!= total_data
) {
2470 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2471 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2472 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2476 if (!lp_ea_support(SNUM(conn
))) {
2477 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2481 /* Pull out the list of names. */
2482 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2484 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2489 *ppdata
= (char *)SMB_REALLOC(
2490 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2491 if(*ppdata
== NULL
) {
2492 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2496 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2498 /* Realloc the params space */
2499 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2500 if (*pparams
== NULL
) {
2501 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2506 /* Save the wildcard match and attribs we are using on this directory -
2507 needed as lanman2 assumes these are being saved between calls */
2509 ntstatus
= dptr_create(conn
,
2517 mask_contains_wcard
,
2521 if (!NT_STATUS_IS_OK(ntstatus
)) {
2522 reply_nterror(req
, ntstatus
);
2527 /* Remember this in case we have
2528 to do a findnext. */
2529 dptr_set_priv(dirptr
);
2532 dptr_num
= dptr_dnum(dirptr
);
2533 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2535 /* Initialize per TRANS2_FIND_FIRST operation data */
2536 dptr_init_search_op(dirptr
);
2538 /* We don't need to check for VOL here as this is returned by
2539 a different TRANS2 call. */
2541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2542 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2543 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2544 dont_descend
= True
;
2547 space_remaining
= max_data_bytes
;
2548 out_of_space
= False
;
2550 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2551 bool got_exact_match
= False
;
2553 /* this is a heuristic to avoid seeking the dirptr except when
2554 absolutely necessary. It allows for a filename of about 40 chars */
2555 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2556 out_of_space
= True
;
2559 finished
= !get_lanman2_dir_entry(ctx
,
2563 mask
,dirtype
,info_level
,
2564 requires_resume_key
,dont_descend
,
2567 space_remaining
, &out_of_space
,
2569 &last_entry_off
, ea_list
);
2572 if (finished
&& out_of_space
)
2575 if (!finished
&& !out_of_space
)
2579 * As an optimisation if we know we aren't looking
2580 * for a wildcard name (ie. the name matches the wildcard exactly)
2581 * then we can finish on any (first) match.
2582 * This speeds up large directory searches. JRA.
2588 /* Ensure space_remaining never goes -ve. */
2589 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2590 space_remaining
= 0;
2591 out_of_space
= true;
2593 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2597 /* Check if we can close the dirptr */
2598 if(close_after_first
|| (finished
&& close_if_end
)) {
2599 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2600 dptr_close(sconn
, &dptr_num
);
2604 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2605 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2606 * the protocol level is less than NT1. Tested with smbclient. JRA.
2607 * This should fix the OS/2 client bug #2335.
2610 if(numentries
== 0) {
2611 dptr_close(sconn
, &dptr_num
);
2612 if (get_Protocol() < PROTOCOL_NT1
) {
2613 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2616 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2617 ERRDOS
, ERRbadfile
);
2622 /* At this point pdata points to numentries directory entries. */
2624 /* Set up the return parameter block */
2625 SSVAL(params
,0,dptr_num
);
2626 SSVAL(params
,2,numentries
);
2627 SSVAL(params
,4,finished
);
2628 SSVAL(params
,6,0); /* Never an EA error */
2629 SSVAL(params
,8,last_entry_off
);
2631 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2634 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2635 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2637 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2641 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2642 smb_fn_name(req
->cmd
),
2643 mask
, directory
, dirtype
, numentries
) );
2646 * Force a name mangle here to ensure that the
2647 * mask as an 8.3 name is top of the mangled cache.
2648 * The reasons for this are subtle. Don't remove
2649 * this code unless you know what you are doing
2650 * (see PR#13758). JRA.
2653 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2654 char mangled_name
[13];
2655 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2663 TALLOC_FREE(smb_dname
);
2667 /****************************************************************************
2668 Reply to a TRANS2_FINDNEXT.
2669 ****************************************************************************/
2671 static void call_trans2findnext(connection_struct
*conn
,
2672 struct smb_request
*req
,
2673 char **pparams
, int total_params
,
2674 char **ppdata
, int total_data
,
2675 unsigned int max_data_bytes
)
2677 /* We must be careful here that we don't return more than the
2678 allowed number of data bytes. If this means returning fewer than
2679 maxentries then so be it. We assume that the redirector has
2680 enough room for the fixed number of parameter bytes it has
2682 char *params
= *pparams
;
2683 char *pdata
= *ppdata
;
2689 uint16 findnext_flags
;
2690 bool close_after_request
;
2692 bool requires_resume_key
;
2694 bool mask_contains_wcard
= False
;
2695 char *resume_name
= NULL
;
2696 const char *mask
= NULL
;
2697 const char *directory
= NULL
;
2701 int i
, last_entry_off
=0;
2702 bool finished
= False
;
2703 bool dont_descend
= False
;
2704 bool out_of_space
= False
;
2705 int space_remaining
;
2706 struct ea_list
*ea_list
= NULL
;
2707 NTSTATUS ntstatus
= NT_STATUS_OK
;
2708 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2709 TALLOC_CTX
*ctx
= talloc_tos();
2710 struct dptr_struct
*dirptr
;
2711 struct smbd_server_connection
*sconn
= req
->sconn
;
2712 bool backup_priv
= false;
2714 if (total_params
< 13) {
2715 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2719 dptr_num
= SVAL(params
,0);
2720 maxentries
= SVAL(params
,2);
2721 info_level
= SVAL(params
,4);
2722 resume_key
= IVAL(params
,6);
2723 findnext_flags
= SVAL(params
,10);
2724 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2725 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2726 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2727 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2729 if (!continue_bit
) {
2730 /* We only need resume_name if continue_bit is zero. */
2731 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2733 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2734 &mask_contains_wcard
);
2735 if (!NT_STATUS_IS_OK(ntstatus
)) {
2736 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2737 complain (it thinks we're asking for the directory above the shared
2738 path or an invalid name). Catch this as the resume name is only compared, never used in
2739 a file access. JRA. */
2740 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2741 &resume_name
, params
+12,
2745 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2746 reply_nterror(req
, ntstatus
);
2752 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2753 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2754 resume_key = %d resume name = %s continue=%d level = %d\n",
2755 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2756 requires_resume_key
, resume_key
,
2757 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2760 /* W2K3 seems to treat zero as 1. */
2764 switch (info_level
) {
2765 case SMB_FIND_INFO_STANDARD
:
2766 case SMB_FIND_EA_SIZE
:
2767 case SMB_FIND_EA_LIST
:
2768 case SMB_FIND_FILE_DIRECTORY_INFO
:
2769 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2770 case SMB_FIND_FILE_NAMES_INFO
:
2771 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2772 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2773 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2775 case SMB_FIND_FILE_UNIX
:
2776 case SMB_FIND_FILE_UNIX_INFO2
:
2777 /* Always use filesystem for UNIX mtime query. */
2778 ask_sharemode
= false;
2779 if (!lp_unix_extensions()) {
2780 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2785 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2789 if (info_level
== SMB_FIND_EA_LIST
) {
2792 if (total_data
< 4) {
2793 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2797 ea_size
= IVAL(pdata
,0);
2798 if (ea_size
!= total_data
) {
2799 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2800 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2801 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2805 if (!lp_ea_support(SNUM(conn
))) {
2806 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2810 /* Pull out the list of names. */
2811 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2813 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2818 *ppdata
= (char *)SMB_REALLOC(
2819 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2820 if(*ppdata
== NULL
) {
2821 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2826 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2828 /* Realloc the params space */
2829 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2830 if(*pparams
== NULL
) {
2831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2837 /* Check that the dptr is valid */
2838 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2839 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2843 directory
= dptr_path(sconn
, dptr_num
);
2845 /* Get the wildcard mask from the dptr */
2846 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2847 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2848 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2852 /* Get the attr mask from the dptr */
2853 dirtype
= dptr_attr(sconn
, dptr_num
);
2855 backup_priv
= dptr_get_priv(dirptr
);
2857 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2858 "backup_priv = %d\n",
2859 dptr_num
, mask
, dirtype
,
2861 dptr_TellDir(dirptr
),
2864 /* Initialize per TRANS2_FIND_NEXT operation data */
2865 dptr_init_search_op(dirptr
);
2867 /* We don't need to check for VOL here as this is returned by
2868 a different TRANS2 call. */
2870 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2871 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2872 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2873 dont_descend
= True
;
2876 space_remaining
= max_data_bytes
;
2877 out_of_space
= False
;
2884 * Seek to the correct position. We no longer use the resume key but
2885 * depend on the last file name instead.
2888 if(!continue_bit
&& resume_name
&& *resume_name
) {
2891 long current_pos
= 0;
2893 * Remember, name_to_8_3 is called by
2894 * get_lanman2_dir_entry(), so the resume name
2895 * could be mangled. Ensure we check the unmangled name.
2898 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2899 char *new_resume_name
= NULL
;
2900 mangle_lookup_name_from_8_3(ctx
,
2904 if (new_resume_name
) {
2905 resume_name
= new_resume_name
;
2910 * Fix for NT redirector problem triggered by resume key indexes
2911 * changing between directory scans. We now return a resume key of 0
2912 * and instead look for the filename to continue from (also given
2913 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2914 * findfirst/findnext (as is usual) then the directory pointer
2915 * should already be at the correct place.
2918 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2919 } /* end if resume_name && !continue_bit */
2921 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2922 bool got_exact_match
= False
;
2924 /* this is a heuristic to avoid seeking the dirptr except when
2925 absolutely necessary. It allows for a filename of about 40 chars */
2926 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2927 out_of_space
= True
;
2930 finished
= !get_lanman2_dir_entry(ctx
,
2934 mask
,dirtype
,info_level
,
2935 requires_resume_key
,dont_descend
,
2938 space_remaining
, &out_of_space
,
2940 &last_entry_off
, ea_list
);
2943 if (finished
&& out_of_space
)
2946 if (!finished
&& !out_of_space
)
2950 * As an optimisation if we know we aren't looking
2951 * for a wildcard name (ie. the name matches the wildcard exactly)
2952 * then we can finish on any (first) match.
2953 * This speeds up large directory searches. JRA.
2959 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2962 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2963 smb_fn_name(req
->cmd
),
2964 mask
, directory
, dirtype
, numentries
) );
2966 /* Check if we can close the dirptr */
2967 if(close_after_request
|| (finished
&& close_if_end
)) {
2968 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2969 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2976 /* Set up the return parameter block */
2977 SSVAL(params
,0,numentries
);
2978 SSVAL(params
,2,finished
);
2979 SSVAL(params
,4,0); /* Never an EA error */
2980 SSVAL(params
,6,last_entry_off
);
2982 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2988 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2990 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2994 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2996 SMB_ASSERT(extended_info
!= NULL
);
2998 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2999 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3000 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3001 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3002 #ifdef SAMBA_VERSION_REVISION
3003 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3005 extended_info
->samba_subversion
= 0;
3006 #ifdef SAMBA_VERSION_RC_RELEASE
3007 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3009 #ifdef SAMBA_VERSION_PRE_RELEASE
3010 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3013 #ifdef SAMBA_VERSION_VENDOR_PATCH
3014 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3016 extended_info
->samba_gitcommitdate
= 0;
3017 #ifdef SAMBA_VERSION_COMMIT_TIME
3018 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3021 memset(extended_info
->samba_version_string
, 0,
3022 sizeof(extended_info
->samba_version_string
));
3024 snprintf (extended_info
->samba_version_string
,
3025 sizeof(extended_info
->samba_version_string
),
3026 "%s", samba_version_string());
3029 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3030 TALLOC_CTX
*mem_ctx
,
3031 uint16_t info_level
,
3033 unsigned int max_data_bytes
,
3037 char *pdata
, *end_data
;
3038 int data_len
= 0, len
;
3039 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3040 int snum
= SNUM(conn
);
3041 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3042 uint32 additional_flags
= 0;
3043 struct smb_filename smb_fname_dot
;
3047 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3048 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3049 "info level (0x%x) on IPC$.\n",
3050 (unsigned int)info_level
));
3051 return NT_STATUS_ACCESS_DENIED
;
3055 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3057 ZERO_STRUCT(smb_fname_dot
);
3058 smb_fname_dot
.base_name
= discard_const_p(char, ".");
3060 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
3061 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3062 return map_nt_error_from_unix(errno
);
3065 st
= smb_fname_dot
.st
;
3067 *ppdata
= (char *)SMB_REALLOC(
3068 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3069 if (*ppdata
== NULL
) {
3070 return NT_STATUS_NO_MEMORY
;
3074 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3075 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3077 switch (info_level
) {
3078 case SMB_INFO_ALLOCATION
:
3080 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3082 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno
);
3086 block_size
= lp_block_size(snum
);
3087 if (bsize
< block_size
) {
3088 uint64_t factor
= block_size
/bsize
;
3093 if (bsize
> block_size
) {
3094 uint64_t factor
= bsize
/block_size
;
3099 bytes_per_sector
= 512;
3100 sectors_per_unit
= bsize
/bytes_per_sector
;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3104 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3106 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3107 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3108 SIVAL(pdata
,l1_cUnit
,dsize
);
3109 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3110 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3114 case SMB_INFO_VOLUME
:
3115 /* Return volume name */
3117 * Add volume serial number - hash of a combination of
3118 * the called hostname and the service name.
3120 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3122 * Win2k3 and previous mess this up by sending a name length
3123 * one byte short. I believe only older clients (OS/2 Win9x) use
3124 * this call so try fixing this by adding a terminating null to
3125 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3129 pdata
+l2_vol_szVolLabel
, vname
,
3130 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3131 STR_NOALIGN
|STR_TERMINATE
);
3132 SCVAL(pdata
,l2_vol_cch
,len
);
3133 data_len
= l2_vol_szVolLabel
+ len
;
3134 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3135 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3139 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3140 case SMB_FS_ATTRIBUTE_INFORMATION
:
3142 additional_flags
= 0;
3143 #if defined(HAVE_SYS_QUOTAS)
3144 additional_flags
|= FILE_VOLUME_QUOTAS
;
3147 if(lp_nt_acl_support(SNUM(conn
))) {
3148 additional_flags
|= FILE_PERSISTENT_ACLS
;
3151 /* Capabilities are filled in at connection time through STATVFS call */
3152 additional_flags
|= conn
->fs_capabilities
;
3153 additional_flags
|= lp_parm_int(conn
->params
->service
,
3154 "share", "fake_fscaps",
3157 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3158 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3159 additional_flags
); /* FS ATTRIBUTES */
3161 SIVAL(pdata
,4,255); /* Max filename component length */
3162 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3163 and will think we can't do long filenames */
3164 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3165 PTR_DIFF(end_data
, pdata
+12),
3168 data_len
= 12 + len
;
3171 case SMB_QUERY_FS_LABEL_INFO
:
3172 case SMB_FS_LABEL_INFORMATION
:
3173 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3174 PTR_DIFF(end_data
, pdata
+4), 0);
3179 case SMB_QUERY_FS_VOLUME_INFO
:
3180 case SMB_FS_VOLUME_INFORMATION
:
3183 * Add volume serial number - hash of a combination of
3184 * the called hostname and the service name.
3186 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3187 (str_checksum(get_local_machine_name())<<16));
3189 /* Max label len is 32 characters. */
3190 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3191 PTR_DIFF(end_data
, pdata
+18),
3193 SIVAL(pdata
,12,len
);
3196 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3197 (int)strlen(vname
),vname
,
3198 lp_servicename(talloc_tos(), snum
)));
3201 case SMB_QUERY_FS_SIZE_INFO
:
3202 case SMB_FS_SIZE_INFORMATION
:
3204 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3206 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3207 return map_nt_error_from_unix(errno
);
3209 block_size
= lp_block_size(snum
);
3210 if (bsize
< block_size
) {
3211 uint64_t factor
= block_size
/bsize
;
3216 if (bsize
> block_size
) {
3217 uint64_t factor
= bsize
/block_size
;
3222 bytes_per_sector
= 512;
3223 sectors_per_unit
= bsize
/bytes_per_sector
;
3224 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3225 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3226 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3227 SBIG_UINT(pdata
,0,dsize
);
3228 SBIG_UINT(pdata
,8,dfree
);
3229 SIVAL(pdata
,16,sectors_per_unit
);
3230 SIVAL(pdata
,20,bytes_per_sector
);
3234 case SMB_FS_FULL_SIZE_INFORMATION
:
3236 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3238 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3239 return map_nt_error_from_unix(errno
);
3241 block_size
= lp_block_size(snum
);
3242 if (bsize
< block_size
) {
3243 uint64_t factor
= block_size
/bsize
;
3248 if (bsize
> block_size
) {
3249 uint64_t factor
= bsize
/block_size
;
3254 bytes_per_sector
= 512;
3255 sectors_per_unit
= bsize
/bytes_per_sector
;
3256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3257 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3258 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3259 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3260 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3261 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3262 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3263 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3267 case SMB_QUERY_FS_DEVICE_INFO
:
3268 case SMB_FS_DEVICE_INFORMATION
:
3270 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3272 if (!CAN_WRITE(conn
)) {
3273 characteristics
|= FILE_READ_ONLY_DEVICE
;
3276 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3277 SIVAL(pdata
,4,characteristics
);
3281 #ifdef HAVE_SYS_QUOTAS
3282 case SMB_FS_QUOTA_INFORMATION
:
3284 * what we have to send --metze:
3286 * Unknown1: 24 NULL bytes
3287 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3288 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3289 * Quota Flags: 2 byte :
3290 * Unknown3: 6 NULL bytes
3294 * details for Quota Flags:
3296 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3297 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3298 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3299 * 0x0001 Enable Quotas: enable quota for this fs
3303 /* we need to fake up a fsp here,
3304 * because its not send in this call
3307 SMB_NTQUOTA_STRUCT quotas
;
3310 ZERO_STRUCT(quotas
);
3313 fsp
.fnum
= FNUM_FIELD_INVALID
;
3316 if (get_current_uid(conn
) != 0) {
3317 DEBUG(0,("set_user_quota: access_denied "
3318 "service [%s] user [%s]\n",
3319 lp_servicename(talloc_tos(), SNUM(conn
)),
3320 conn
->session_info
->unix_info
->unix_name
));
3321 return NT_STATUS_ACCESS_DENIED
;
3324 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3325 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3326 return map_nt_error_from_unix(errno
);
3331 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3332 lp_servicename(talloc_tos(), SNUM(conn
))));
3334 /* Unknown1 24 NULL bytes*/
3335 SBIG_UINT(pdata
,0,(uint64_t)0);
3336 SBIG_UINT(pdata
,8,(uint64_t)0);
3337 SBIG_UINT(pdata
,16,(uint64_t)0);
3339 /* Default Soft Quota 8 bytes */
3340 SBIG_UINT(pdata
,24,quotas
.softlim
);
3342 /* Default Hard Quota 8 bytes */
3343 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3345 /* Quota flag 2 bytes */
3346 SSVAL(pdata
,40,quotas
.qflags
);
3348 /* Unknown3 6 NULL bytes */
3354 #endif /* HAVE_SYS_QUOTAS */
3355 case SMB_FS_OBJECTID_INFORMATION
:
3357 unsigned char objid
[16];
3358 struct smb_extended_info extended_info
;
3359 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3360 samba_extended_info_version (&extended_info
);
3361 SIVAL(pdata
,16,extended_info
.samba_magic
);
3362 SIVAL(pdata
,20,extended_info
.samba_version
);
3363 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3364 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3365 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3371 * Query the version and capabilities of the CIFS UNIX extensions
3375 case SMB_QUERY_CIFS_UNIX_INFO
:
3377 bool large_write
= lp_min_receive_file_size() &&
3378 !srv_is_signing_active(conn
->sconn
);
3379 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3380 int encrypt_caps
= 0;
3382 if (!lp_unix_extensions()) {
3383 return NT_STATUS_INVALID_LEVEL
;
3386 switch (conn
->encrypt_level
) {
3387 case SMB_SIGNING_OFF
:
3390 case SMB_SIGNING_IF_REQUIRED
:
3391 case SMB_SIGNING_DEFAULT
:
3392 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3394 case SMB_SIGNING_REQUIRED
:
3395 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3396 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3397 large_write
= false;
3403 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3404 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3406 /* We have POSIX ACLs, pathname, encryption,
3407 * large read/write, and locking capability. */
3409 SBIG_UINT(pdata
,4,((uint64_t)(
3410 CIFS_UNIX_POSIX_ACLS_CAP
|
3411 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3412 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3413 CIFS_UNIX_EXTATTR_CAP
|
3414 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3416 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3418 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3422 case SMB_QUERY_POSIX_FS_INFO
:
3425 vfs_statvfs_struct svfs
;
3427 if (!lp_unix_extensions()) {
3428 return NT_STATUS_INVALID_LEVEL
;
3431 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3435 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3436 SIVAL(pdata
,4,svfs
.BlockSize
);
3437 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3438 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3439 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3440 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3441 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3442 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3443 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3445 } else if (rc
== EOPNOTSUPP
) {
3446 return NT_STATUS_INVALID_LEVEL
;
3447 #endif /* EOPNOTSUPP */
3449 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3450 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3455 case SMB_QUERY_POSIX_WHOAMI
:
3461 if (!lp_unix_extensions()) {
3462 return NT_STATUS_INVALID_LEVEL
;
3465 if (max_data_bytes
< 40) {
3466 return NT_STATUS_BUFFER_TOO_SMALL
;
3469 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3470 flags
|= SMB_WHOAMI_GUEST
;
3473 /* NOTE: 8 bytes for UID/GID, irrespective of native
3474 * platform size. This matches
3475 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3477 data_len
= 4 /* flags */
3484 + 4 /* pad/reserved */
3485 + (conn
->session_info
->unix_token
->ngroups
* 8)
3487 + (conn
->session_info
->security_token
->num_sids
*
3491 SIVAL(pdata
, 0, flags
);
3492 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3494 (uint64_t)conn
->session_info
->unix_token
->uid
);
3495 SBIG_UINT(pdata
, 16,
3496 (uint64_t)conn
->session_info
->unix_token
->gid
);
3499 if (data_len
>= max_data_bytes
) {
3500 /* Potential overflow, skip the GIDs and SIDs. */
3502 SIVAL(pdata
, 24, 0); /* num_groups */
3503 SIVAL(pdata
, 28, 0); /* num_sids */
3504 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3505 SIVAL(pdata
, 36, 0); /* reserved */
3511 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3512 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3514 /* We walk the SID list twice, but this call is fairly
3515 * infrequent, and I don't expect that it's performance
3516 * sensitive -- jpeach
3518 for (i
= 0, sid_bytes
= 0;
3519 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3520 sid_bytes
+= ndr_size_dom_sid(
3521 &conn
->session_info
->security_token
->sids
[i
],
3525 /* SID list byte count */
3526 SIVAL(pdata
, 32, sid_bytes
);
3528 /* 4 bytes pad/reserved - must be zero */
3529 SIVAL(pdata
, 36, 0);
3533 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3534 SBIG_UINT(pdata
, data_len
,
3535 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3541 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3542 int sid_len
= ndr_size_dom_sid(
3543 &conn
->session_info
->security_token
->sids
[i
],
3546 sid_linearize(pdata
+ data_len
, sid_len
,
3547 &conn
->session_info
->security_token
->sids
[i
]);
3548 data_len
+= sid_len
;
3554 case SMB_MAC_QUERY_FS_INFO
:
3556 * Thursby MAC extension... ONLY on NTFS filesystems
3557 * once we do streams then we don't need this
3559 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3561 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3566 return NT_STATUS_INVALID_LEVEL
;
3569 *ret_data_len
= data_len
;
3570 return NT_STATUS_OK
;
3573 /****************************************************************************
3574 Reply to a TRANS2_QFSINFO (query filesystem info).
3575 ****************************************************************************/
3577 static void call_trans2qfsinfo(connection_struct
*conn
,
3578 struct smb_request
*req
,
3579 char **pparams
, int total_params
,
3580 char **ppdata
, int total_data
,
3581 unsigned int max_data_bytes
)
3583 char *params
= *pparams
;
3584 uint16_t info_level
;
3588 if (total_params
< 2) {
3589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3593 info_level
= SVAL(params
,0);
3595 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3596 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3597 DEBUG(0,("call_trans2qfsinfo: encryption required "
3598 "and info level 0x%x sent.\n",
3599 (unsigned int)info_level
));
3600 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3605 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3607 status
= smbd_do_qfsinfo(conn
, req
,
3612 if (!NT_STATUS_IS_OK(status
)) {
3613 reply_nterror(req
, status
);
3617 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3620 DEBUG( 4, ( "%s info_level = %d\n",
3621 smb_fn_name(req
->cmd
), info_level
) );
3626 /****************************************************************************
3627 Reply to a TRANS2_SETFSINFO (set filesystem info).
3628 ****************************************************************************/
3630 static void call_trans2setfsinfo(connection_struct
*conn
,
3631 struct smb_request
*req
,
3632 char **pparams
, int total_params
,
3633 char **ppdata
, int total_data
,
3634 unsigned int max_data_bytes
)
3636 struct smbd_server_connection
*sconn
= req
->sconn
;
3637 char *pdata
= *ppdata
;
3638 char *params
= *pparams
;
3641 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3642 lp_servicename(talloc_tos(), SNUM(conn
))));
3645 if (total_params
< 4) {
3646 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3648 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3652 info_level
= SVAL(params
,2);
3655 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3656 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3657 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3658 "info level (0x%x) on IPC$.\n",
3659 (unsigned int)info_level
));
3660 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3665 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3666 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3667 DEBUG(0,("call_trans2setfsinfo: encryption required "
3668 "and info level 0x%x sent.\n",
3669 (unsigned int)info_level
));
3670 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3675 switch(info_level
) {
3676 case SMB_SET_CIFS_UNIX_INFO
:
3677 if (!lp_unix_extensions()) {
3678 DEBUG(2,("call_trans2setfsinfo: "
3679 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3680 "unix extensions off\n"));
3682 NT_STATUS_INVALID_LEVEL
);
3686 /* There should be 12 bytes of capabilities set. */
3687 if (total_data
< 12) {
3690 NT_STATUS_INVALID_PARAMETER
);
3693 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3694 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3695 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3696 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3697 /* Just print these values for now. */
3698 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3699 "major = %u, minor = %u cap_low = 0x%x, "
3701 (unsigned int)sconn
->
3702 smb1
.unix_info
.client_major
,
3703 (unsigned int)sconn
->
3704 smb1
.unix_info
.client_minor
,
3705 (unsigned int)sconn
->
3706 smb1
.unix_info
.client_cap_low
,
3707 (unsigned int)sconn
->
3708 smb1
.unix_info
.client_cap_high
));
3710 /* Here is where we must switch to posix pathname processing... */
3711 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3712 lp_set_posix_pathnames();
3713 mangle_change_to_posix();
3716 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3717 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3718 /* Client that knows how to do posix locks,
3719 * but not posix open/mkdir operations. Set a
3720 * default type for read/write checks. */
3722 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3727 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3730 size_t param_len
= 0;
3731 size_t data_len
= total_data
;
3733 if (!lp_unix_extensions()) {
3736 NT_STATUS_INVALID_LEVEL
);
3740 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3743 NT_STATUS_NOT_SUPPORTED
);
3747 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3748 DEBUG( 2,("call_trans2setfsinfo: "
3749 "request transport encryption disabled"
3750 "with 'fork echo handler = yes'\n"));
3753 NT_STATUS_NOT_SUPPORTED
);
3757 DEBUG( 4,("call_trans2setfsinfo: "
3758 "request transport encryption.\n"));
3760 status
= srv_request_encryption_setup(conn
,
3761 (unsigned char **)ppdata
,
3763 (unsigned char **)pparams
,
3766 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3767 !NT_STATUS_IS_OK(status
)) {
3768 reply_nterror(req
, status
);
3772 send_trans2_replies(conn
, req
,
3779 if (NT_STATUS_IS_OK(status
)) {
3780 /* Server-side transport
3781 * encryption is now *on*. */
3782 status
= srv_encryption_start(conn
);
3783 if (!NT_STATUS_IS_OK(status
)) {
3784 char *reason
= talloc_asprintf(talloc_tos(),
3785 "Failure in setting "
3786 "up encrypted transport: %s",
3788 exit_server_cleanly(reason
);
3794 case SMB_FS_QUOTA_INFORMATION
:
3796 files_struct
*fsp
= NULL
;
3797 SMB_NTQUOTA_STRUCT quotas
;
3799 ZERO_STRUCT(quotas
);
3802 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3803 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3804 lp_servicename(talloc_tos(), SNUM(conn
)),
3805 conn
->session_info
->unix_info
->unix_name
));
3806 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3810 /* note: normaly there're 48 bytes,
3811 * but we didn't use the last 6 bytes for now
3814 fsp
= file_fsp(req
, SVAL(params
,0));
3816 if (!check_fsp_ntquota_handle(conn
, req
,
3818 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3820 req
, NT_STATUS_INVALID_HANDLE
);
3824 if (total_data
< 42) {
3825 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3829 NT_STATUS_INVALID_PARAMETER
);
3833 /* unknown_1 24 NULL bytes in pdata*/
3835 /* the soft quotas 8 bytes (uint64_t)*/
3836 quotas
.softlim
= BVAL(pdata
,24);
3838 /* the hard quotas 8 bytes (uint64_t)*/
3839 quotas
.hardlim
= BVAL(pdata
,32);
3841 /* quota_flags 2 bytes **/
3842 quotas
.qflags
= SVAL(pdata
,40);
3844 /* unknown_2 6 NULL bytes follow*/
3846 /* now set the quotas */
3847 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3848 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3849 reply_nterror(req
, map_nt_error_from_unix(errno
));
3856 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3858 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3864 * sending this reply works fine,
3865 * but I'm not sure it's the same
3866 * like windows do...
3869 reply_outbuf(req
, 10, 0);
3872 #if defined(HAVE_POSIX_ACLS)
3873 /****************************************************************************
3874 Utility function to count the number of entries in a POSIX acl.
3875 ****************************************************************************/
3877 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3879 unsigned int ace_count
= 0;
3880 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3881 SMB_ACL_ENTRY_T entry
;
3883 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3885 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3886 entry_id
= SMB_ACL_NEXT_ENTRY
;
3893 /****************************************************************************
3894 Utility function to marshall a POSIX acl into wire format.
3895 ****************************************************************************/
3897 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3899 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3900 SMB_ACL_ENTRY_T entry
;
3902 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3903 SMB_ACL_TAG_T tagtype
;
3904 SMB_ACL_PERMSET_T permset
;
3905 unsigned char perms
= 0;
3906 unsigned int own_grp
;
3909 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3910 entry_id
= SMB_ACL_NEXT_ENTRY
;
3913 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3914 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3918 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3919 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3923 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3924 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3925 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3927 SCVAL(pdata
,1,perms
);
3930 case SMB_ACL_USER_OBJ
:
3931 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3932 own_grp
= (unsigned int)pst
->st_ex_uid
;
3933 SIVAL(pdata
,2,own_grp
);
3938 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3940 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3943 own_grp
= (unsigned int)*puid
;
3944 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3945 SIVAL(pdata
,2,own_grp
);
3949 case SMB_ACL_GROUP_OBJ
:
3950 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3951 own_grp
= (unsigned int)pst
->st_ex_gid
;
3952 SIVAL(pdata
,2,own_grp
);
3957 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3959 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3962 own_grp
= (unsigned int)*pgid
;
3963 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3964 SIVAL(pdata
,2,own_grp
);
3969 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3970 SIVAL(pdata
,2,0xFFFFFFFF);
3971 SIVAL(pdata
,6,0xFFFFFFFF);
3974 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3975 SIVAL(pdata
,2,0xFFFFFFFF);
3976 SIVAL(pdata
,6,0xFFFFFFFF);
3979 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3982 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3989 /****************************************************************************
3990 Store the FILE_UNIX_BASIC info.
3991 ****************************************************************************/
3993 static char *store_file_unix_basic(connection_struct
*conn
,
3996 const SMB_STRUCT_STAT
*psbuf
)
3998 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4001 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4002 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4004 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4007 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4012 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4015 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4019 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4023 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4026 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4027 devno
= psbuf
->st_ex_rdev
;
4029 devno
= psbuf
->st_ex_dev
;
4032 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4036 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4040 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4043 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4047 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4054 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4055 * the chflags(2) (or equivalent) flags.
4057 * XXX: this really should be behind the VFS interface. To do this, we would
4058 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4059 * Each VFS module could then implement its own mapping as appropriate for the
4060 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4062 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4066 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4070 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4074 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4078 { UF_HIDDEN
, EXT_HIDDEN
},
4081 /* Do not remove. We need to guarantee that this array has at least one
4082 * entry to build on HP-UX.
4088 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4089 uint32
*smb_fflags
, uint32
*smb_fmask
)
4093 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4094 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4095 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4096 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4101 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4102 const uint32 smb_fflags
,
4103 const uint32 smb_fmask
,
4106 uint32 max_fmask
= 0;
4109 *stat_fflags
= psbuf
->st_ex_flags
;
4111 /* For each flags requested in smb_fmask, check the state of the
4112 * corresponding flag in smb_fflags and set or clear the matching
4116 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4117 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4118 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4119 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4120 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4122 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4127 /* If smb_fmask is asking to set any bits that are not supported by
4128 * our flag mappings, we should fail.
4130 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4138 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4139 * of file flags and birth (create) time.
4141 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4144 const SMB_STRUCT_STAT
*psbuf
)
4146 uint32 file_flags
= 0;
4147 uint32 flags_mask
= 0;
4149 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4151 /* Create (birth) time 64 bit */
4152 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4155 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4156 SIVAL(pdata
, 0, file_flags
); /* flags */
4157 SIVAL(pdata
, 4, flags_mask
); /* mask */
4163 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4164 const struct stream_struct
*streams
,
4166 unsigned int max_data_bytes
,
4167 unsigned int *data_size
)
4170 unsigned int ofs
= 0;
4172 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4173 unsigned int next_offset
;
4175 smb_ucs2_t
*namebuf
;
4177 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4178 streams
[i
].name
, &namelen
) ||
4181 return NT_STATUS_INVALID_PARAMETER
;
4185 * name_buf is now null-terminated, we need to marshall as not
4191 SIVAL(data
, ofs
+4, namelen
);
4192 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4193 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4194 memcpy(data
+ofs
+24, namebuf
, namelen
);
4195 TALLOC_FREE(namebuf
);
4197 next_offset
= ofs
+ 24 + namelen
;
4199 if (i
== num_streams
-1) {
4200 SIVAL(data
, ofs
, 0);
4203 unsigned int align
= ndr_align_size(next_offset
, 8);
4205 memset(data
+next_offset
, 0, align
);
4206 next_offset
+= align
;
4208 SIVAL(data
, ofs
, next_offset
- ofs
);
4217 return NT_STATUS_OK
;
4220 /****************************************************************************
4221 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4222 ****************************************************************************/
4224 static void call_trans2qpipeinfo(connection_struct
*conn
,
4225 struct smb_request
*req
,
4226 unsigned int tran_call
,
4227 char **pparams
, int total_params
,
4228 char **ppdata
, int total_data
,
4229 unsigned int max_data_bytes
)
4231 char *params
= *pparams
;
4232 char *pdata
= *ppdata
;
4233 unsigned int data_size
= 0;
4234 unsigned int param_size
= 2;
4239 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4243 if (total_params
< 4) {
4244 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4248 fsp
= file_fsp(req
, SVAL(params
,0));
4249 if (!fsp_is_np(fsp
)) {
4250 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4254 info_level
= SVAL(params
,2);
4256 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4257 if (*pparams
== NULL
) {
4258 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4263 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4264 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4265 if (*ppdata
== NULL
) {
4266 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4271 switch (info_level
) {
4272 case SMB_FILE_STANDARD_INFORMATION
:
4274 SOFF_T(pdata
,0,4096LL);
4281 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4285 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4291 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4292 TALLOC_CTX
*mem_ctx
,
4293 uint16_t info_level
,
4295 struct smb_filename
*smb_fname
,
4296 bool delete_pending
,
4297 struct timespec write_time_ts
,
4298 struct ea_list
*ea_list
,
4299 int lock_data_count
,
4302 unsigned int max_data_bytes
,
4304 unsigned int *pdata_size
)
4306 char *pdata
= *ppdata
;
4307 char *dstart
, *dend
;
4308 unsigned int data_size
;
4309 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4310 time_t create_time
, mtime
, atime
, c_time
;
4311 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4318 uint64_t file_size
= 0;
4320 uint64_t allocation_size
= 0;
4321 uint64_t file_index
= 0;
4322 uint32_t access_mask
= 0;
4324 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4325 return NT_STATUS_INVALID_LEVEL
;
4328 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4329 smb_fname_str_dbg(smb_fname
),
4331 info_level
, max_data_bytes
));
4333 mode
= dos_mode(conn
, smb_fname
);
4334 nlink
= psbuf
->st_ex_nlink
;
4336 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4340 if ((nlink
> 0) && delete_pending
) {
4344 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4345 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4346 if (*ppdata
== NULL
) {
4347 return NT_STATUS_NO_MEMORY
;
4351 dend
= dstart
+ data_size
- 1;
4353 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4354 update_stat_ex_mtime(psbuf
, write_time_ts
);
4357 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4358 mtime_ts
= psbuf
->st_ex_mtime
;
4359 atime_ts
= psbuf
->st_ex_atime
;
4360 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4362 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4363 dos_filetime_timespec(&create_time_ts
);
4364 dos_filetime_timespec(&mtime_ts
);
4365 dos_filetime_timespec(&atime_ts
);
4366 dos_filetime_timespec(&ctime_ts
);
4369 create_time
= convert_timespec_to_time_t(create_time_ts
);
4370 mtime
= convert_timespec_to_time_t(mtime_ts
);
4371 atime
= convert_timespec_to_time_t(atime_ts
);
4372 c_time
= convert_timespec_to_time_t(ctime_ts
);
4374 p
= strrchr_m(smb_fname
->base_name
,'/');
4376 base_name
= smb_fname
->base_name
;
4380 /* NT expects the name to be in an exact form of the *full*
4381 filename. See the trans2 torture test */
4382 if (ISDOT(base_name
)) {
4383 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4385 return NT_STATUS_NO_MEMORY
;
4388 dos_fname
= talloc_asprintf(mem_ctx
,
4390 smb_fname
->base_name
);
4392 return NT_STATUS_NO_MEMORY
;
4394 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4395 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4396 smb_fname
->stream_name
);
4398 return NT_STATUS_NO_MEMORY
;
4402 string_replace(dos_fname
, '/', '\\');
4405 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4408 /* Do we have this path open ? */
4410 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4411 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4412 if (fsp1
&& fsp1
->initial_allocation_size
) {
4413 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4417 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4418 file_size
= get_file_size_stat(psbuf
);
4422 pos
= fsp
->fh
->position_information
;
4426 access_mask
= fsp
->access_mask
;
4428 /* GENERIC_EXECUTE mapping from Windows */
4429 access_mask
= 0x12019F;
4432 /* This should be an index number - looks like
4435 I think this causes us to fail the IFSKIT
4436 BasicFileInformationTest. -tpot */
4437 file_index
= get_FileIndex(conn
, psbuf
);
4439 switch (info_level
) {
4440 case SMB_INFO_STANDARD
:
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4443 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4444 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4445 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4446 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4447 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4448 SSVAL(pdata
,l1_attrFile
,mode
);
4451 case SMB_INFO_QUERY_EA_SIZE
:
4453 unsigned int ea_size
=
4454 estimate_ea_size(conn
, fsp
,
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4458 srv_put_dos_date2(pdata
,0,create_time
);
4459 srv_put_dos_date2(pdata
,4,atime
);
4460 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4461 SIVAL(pdata
,12,(uint32
)file_size
);
4462 SIVAL(pdata
,16,(uint32
)allocation_size
);
4463 SSVAL(pdata
,20,mode
);
4464 SIVAL(pdata
,22,ea_size
);
4468 case SMB_INFO_IS_NAME_VALID
:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4471 /* os/2 needs this ? really ?*/
4472 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4474 /* This is only reached for qpathinfo */
4478 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4480 size_t total_ea_len
= 0;
4481 struct ea_list
*ea_file_list
= NULL
;
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4485 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4487 &total_ea_len
, &ea_file_list
);
4488 if (!NT_STATUS_IS_OK(status
)) {
4492 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4494 if (!ea_list
|| (total_ea_len
> data_size
)) {
4496 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4500 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4504 case SMB_INFO_QUERY_ALL_EAS
:
4506 /* We have data_size bytes to put EA's into. */
4507 size_t total_ea_len
= 0;
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4510 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4512 &total_ea_len
, &ea_list
);
4513 if (!NT_STATUS_IS_OK(status
)) {
4517 if (!ea_list
|| (total_ea_len
> data_size
)) {
4519 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4523 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4527 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4529 /* This is FileFullEaInformation - 0xF which maps to
4530 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4532 /* We have data_size bytes to put EA's into. */
4533 size_t total_ea_len
= 0;
4534 struct ea_list
*ea_file_list
= NULL
;
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4538 /*TODO: add filtering and index handling */
4541 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4543 &total_ea_len
, &ea_file_list
);
4544 if (!NT_STATUS_IS_OK(status
)) {
4547 if (!ea_file_list
) {
4548 return NT_STATUS_NO_EAS_ON_FILE
;
4551 status
= fill_ea_chained_buffer(mem_ctx
,
4555 conn
, ea_file_list
);
4556 if (!NT_STATUS_IS_OK(status
)) {
4562 case SMB_FILE_BASIC_INFORMATION
:
4563 case SMB_QUERY_FILE_BASIC_INFO
:
4565 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4567 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4573 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4574 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4575 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4576 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4577 SIVAL(pdata
,32,mode
);
4579 DEBUG(5,("SMB_QFBI - "));
4580 DEBUG(5,("create: %s ", ctime(&create_time
)));
4581 DEBUG(5,("access: %s ", ctime(&atime
)));
4582 DEBUG(5,("write: %s ", ctime(&mtime
)));
4583 DEBUG(5,("change: %s ", ctime(&c_time
)));
4584 DEBUG(5,("mode: %x\n", mode
));
4587 case SMB_FILE_STANDARD_INFORMATION
:
4588 case SMB_QUERY_FILE_STANDARD_INFO
:
4590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4592 SOFF_T(pdata
,0,allocation_size
);
4593 SOFF_T(pdata
,8,file_size
);
4594 SIVAL(pdata
,16,nlink
);
4595 SCVAL(pdata
,20,delete_pending
?1:0);
4596 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4597 SSVAL(pdata
,22,0); /* Padding. */
4600 case SMB_FILE_EA_INFORMATION
:
4601 case SMB_QUERY_FILE_EA_INFO
:
4603 unsigned int ea_size
=
4604 estimate_ea_size(conn
, fsp
, smb_fname
);
4605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4607 SIVAL(pdata
,0,ea_size
);
4611 /* Get the 8.3 name - used if NT SMB was negotiated. */
4612 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4613 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4616 char mangled_name
[13];
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4618 if (!name_to_8_3(base_name
,mangled_name
,
4619 True
,conn
->params
)) {
4620 return NT_STATUS_NO_MEMORY
;
4622 len
= srvstr_push(dstart
, flags2
,
4623 pdata
+4, mangled_name
,
4624 PTR_DIFF(dend
, pdata
+4),
4626 data_size
= 4 + len
;
4631 case SMB_QUERY_FILE_NAME_INFO
:
4635 this must be *exactly* right for ACLs on mapped drives to work
4637 len
= srvstr_push(dstart
, flags2
,
4639 PTR_DIFF(dend
, pdata
+4),
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4642 data_size
= 4 + len
;
4647 case SMB_FILE_ALLOCATION_INFORMATION
:
4648 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4651 SOFF_T(pdata
,0,allocation_size
);
4654 case SMB_FILE_END_OF_FILE_INFORMATION
:
4655 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4658 SOFF_T(pdata
,0,file_size
);
4661 case SMB_QUERY_FILE_ALL_INFO
:
4662 case SMB_FILE_ALL_INFORMATION
:
4665 unsigned int ea_size
=
4666 estimate_ea_size(conn
, fsp
, smb_fname
);
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4668 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4669 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4670 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4671 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4672 SIVAL(pdata
,32,mode
);
4673 SIVAL(pdata
,36,0); /* padding. */
4675 SOFF_T(pdata
,0,allocation_size
);
4676 SOFF_T(pdata
,8,file_size
);
4677 SIVAL(pdata
,16,nlink
);
4678 SCVAL(pdata
,20,delete_pending
);
4679 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4682 SIVAL(pdata
,0,ea_size
);
4683 pdata
+= 4; /* EA info */
4684 len
= srvstr_push(dstart
, flags2
,
4686 PTR_DIFF(dend
, pdata
+4),
4690 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4694 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4697 unsigned int ea_size
=
4698 estimate_ea_size(conn
, fsp
, smb_fname
);
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4700 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4701 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4702 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4703 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4704 SIVAL(pdata
, 0x20, mode
);
4705 SIVAL(pdata
, 0x24, 0); /* padding. */
4706 SBVAL(pdata
, 0x28, allocation_size
);
4707 SBVAL(pdata
, 0x30, file_size
);
4708 SIVAL(pdata
, 0x38, nlink
);
4709 SCVAL(pdata
, 0x3C, delete_pending
);
4710 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4711 SSVAL(pdata
, 0x3E, 0); /* padding */
4712 SBVAL(pdata
, 0x40, file_index
);
4713 SIVAL(pdata
, 0x48, ea_size
);
4714 SIVAL(pdata
, 0x4C, access_mask
);
4715 SBVAL(pdata
, 0x50, pos
);
4716 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4717 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4721 len
= srvstr_push(dstart
, flags2
,
4723 PTR_DIFF(dend
, pdata
+4),
4727 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4730 case SMB_FILE_INTERNAL_INFORMATION
:
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4733 SBVAL(pdata
, 0, file_index
);
4737 case SMB_FILE_ACCESS_INFORMATION
:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4739 SIVAL(pdata
, 0, access_mask
);
4743 case SMB_FILE_NAME_INFORMATION
:
4744 /* Pathname with leading '\'. */
4747 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4749 SIVAL(pdata
,0,byte_len
);
4750 data_size
= 4 + byte_len
;
4754 case SMB_FILE_DISPOSITION_INFORMATION
:
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4757 SCVAL(pdata
,0,delete_pending
);
4760 case SMB_FILE_POSITION_INFORMATION
:
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4763 SOFF_T(pdata
,0,pos
);
4766 case SMB_FILE_MODE_INFORMATION
:
4767 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4768 SIVAL(pdata
,0,mode
);
4772 case SMB_FILE_ALIGNMENT_INFORMATION
:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4774 SIVAL(pdata
,0,0); /* No alignment needed. */
4779 * NT4 server just returns "invalid query" to this - if we try
4780 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4783 /* The first statement above is false - verified using Thursby
4784 * client against NT4 -- gcolley.
4786 case SMB_QUERY_FILE_STREAM_INFO
:
4787 case SMB_FILE_STREAM_INFORMATION
: {
4788 unsigned int num_streams
= 0;
4789 struct stream_struct
*streams
= NULL
;
4791 DEBUG(10,("smbd_do_qfilepathinfo: "
4792 "SMB_FILE_STREAM_INFORMATION\n"));
4794 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4795 return NT_STATUS_INVALID_PARAMETER
;
4798 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4799 talloc_tos(), &num_streams
, &streams
);
4801 if (!NT_STATUS_IS_OK(status
)) {
4802 DEBUG(10, ("could not get stream info: %s\n",
4803 nt_errstr(status
)));
4807 status
= marshall_stream_info(num_streams
, streams
,
4808 pdata
, max_data_bytes
,
4811 if (!NT_STATUS_IS_OK(status
)) {
4812 DEBUG(10, ("marshall_stream_info failed: %s\n",
4813 nt_errstr(status
)));
4817 TALLOC_FREE(streams
);
4821 case SMB_QUERY_COMPRESSION_INFO
:
4822 case SMB_FILE_COMPRESSION_INFORMATION
:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4824 SOFF_T(pdata
,0,file_size
);
4825 SIVAL(pdata
,8,0); /* ??? */
4826 SIVAL(pdata
,12,0); /* ??? */
4830 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4832 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4833 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4834 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4835 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4836 SOFF_T(pdata
,32,allocation_size
);
4837 SOFF_T(pdata
,40,file_size
);
4838 SIVAL(pdata
,48,mode
);
4839 SIVAL(pdata
,52,0); /* ??? */
4843 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4845 SIVAL(pdata
,0,mode
);
4851 * CIFS UNIX Extensions.
4854 case SMB_QUERY_FILE_UNIX_BASIC
:
4856 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4857 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4859 DEBUG(4,("smbd_do_qfilepathinfo: "
4860 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4861 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4865 case SMB_QUERY_FILE_UNIX_INFO2
:
4867 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4868 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4872 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4874 for (i
=0; i
<100; i
++)
4875 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4881 case SMB_QUERY_FILE_UNIX_LINK
:
4884 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4887 return NT_STATUS_NO_MEMORY
;
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4892 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4893 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4896 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4898 len
= SMB_VFS_READLINK(conn
,
4899 smb_fname
->base_name
,
4902 return map_nt_error_from_unix(errno
);
4905 len
= srvstr_push(dstart
, flags2
,
4907 PTR_DIFF(dend
, pdata
),
4910 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4915 #if defined(HAVE_POSIX_ACLS)
4916 case SMB_QUERY_POSIX_ACL
:
4918 SMB_ACL_T file_acl
= NULL
;
4919 SMB_ACL_T def_acl
= NULL
;
4920 uint16 num_file_acls
= 0;
4921 uint16 num_def_acls
= 0;
4923 if (fsp
&& fsp
->fh
->fd
!= -1) {
4924 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4927 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4928 smb_fname
->base_name
,
4929 SMB_ACL_TYPE_ACCESS
);
4932 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4933 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4934 "not implemented on "
4935 "filesystem containing %s\n",
4936 smb_fname
->base_name
));
4937 return NT_STATUS_NOT_IMPLEMENTED
;
4940 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4941 if (fsp
&& fsp
->is_directory
) {
4943 SMB_VFS_SYS_ACL_GET_FILE(
4945 fsp
->fsp_name
->base_name
,
4946 SMB_ACL_TYPE_DEFAULT
);
4949 SMB_VFS_SYS_ACL_GET_FILE(
4951 smb_fname
->base_name
,
4952 SMB_ACL_TYPE_DEFAULT
);
4954 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4957 num_file_acls
= count_acl_entries(conn
, file_acl
);
4958 num_def_acls
= count_acl_entries(conn
, def_acl
);
4960 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4961 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4963 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4964 SMB_POSIX_ACL_HEADER_SIZE
) ));
4966 TALLOC_FREE(file_acl
);
4969 TALLOC_FREE(def_acl
);
4971 return NT_STATUS_BUFFER_TOO_SMALL
;
4974 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4975 SSVAL(pdata
,2,num_file_acls
);
4976 SSVAL(pdata
,4,num_def_acls
);
4977 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4979 TALLOC_FREE(file_acl
);
4982 TALLOC_FREE(def_acl
);
4984 return NT_STATUS_INTERNAL_ERROR
;
4986 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4988 TALLOC_FREE(file_acl
);
4991 TALLOC_FREE(def_acl
);
4993 return NT_STATUS_INTERNAL_ERROR
;
4997 TALLOC_FREE(file_acl
);
5000 TALLOC_FREE(def_acl
);
5002 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5008 case SMB_QUERY_POSIX_LOCK
:
5013 enum brl_type lock_type
;
5015 /* We need an open file with a real fd for this. */
5016 if (!fsp
|| fsp
->fh
->fd
== -1) {
5017 return NT_STATUS_INVALID_LEVEL
;
5020 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5021 return NT_STATUS_INVALID_PARAMETER
;
5024 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5025 case POSIX_LOCK_TYPE_READ
:
5026 lock_type
= READ_LOCK
;
5028 case POSIX_LOCK_TYPE_WRITE
:
5029 lock_type
= WRITE_LOCK
;
5031 case POSIX_LOCK_TYPE_UNLOCK
:
5033 /* There's no point in asking for an unlock... */
5034 return NT_STATUS_INVALID_PARAMETER
;
5037 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5038 #if defined(HAVE_LONGLONG)
5039 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5040 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5041 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5042 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5043 #else /* HAVE_LONGLONG */
5044 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5045 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5046 #endif /* HAVE_LONGLONG */
5048 status
= query_lock(fsp
,
5055 if (ERROR_WAS_LOCK_DENIED(status
)) {
5056 /* Here we need to report who has it locked... */
5057 data_size
= POSIX_LOCK_DATA_SIZE
;
5059 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5060 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5061 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5062 #if defined(HAVE_LONGLONG)
5063 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5064 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5065 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5066 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5067 #else /* HAVE_LONGLONG */
5068 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5069 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5070 #endif /* HAVE_LONGLONG */
5072 } else if (NT_STATUS_IS_OK(status
)) {
5073 /* For success we just return a copy of what we sent
5074 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5075 data_size
= POSIX_LOCK_DATA_SIZE
;
5076 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5077 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5085 return NT_STATUS_INVALID_LEVEL
;
5088 *pdata_size
= data_size
;
5089 return NT_STATUS_OK
;
5092 /****************************************************************************
5093 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5094 file name or file id).
5095 ****************************************************************************/
5097 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5098 struct smb_request
*req
,
5099 unsigned int tran_call
,
5100 char **pparams
, int total_params
,
5101 char **ppdata
, int total_data
,
5102 unsigned int max_data_bytes
)
5104 char *params
= *pparams
;
5105 char *pdata
= *ppdata
;
5107 unsigned int data_size
= 0;
5108 unsigned int param_size
= 2;
5109 struct smb_filename
*smb_fname
= NULL
;
5110 bool delete_pending
= False
;
5111 struct timespec write_time_ts
;
5112 files_struct
*fsp
= NULL
;
5113 struct file_id fileid
;
5114 struct ea_list
*ea_list
= NULL
;
5115 int lock_data_count
= 0;
5116 char *lock_data
= NULL
;
5117 NTSTATUS status
= NT_STATUS_OK
;
5120 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5124 ZERO_STRUCT(write_time_ts
);
5126 if (tran_call
== TRANSACT2_QFILEINFO
) {
5127 if (total_params
< 4) {
5128 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5133 call_trans2qpipeinfo(conn
, req
, tran_call
,
5134 pparams
, total_params
,
5140 fsp
= file_fsp(req
, SVAL(params
,0));
5141 info_level
= SVAL(params
,2);
5143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5145 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5146 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5150 /* Initial check for valid fsp ptr. */
5151 if (!check_fsp_open(conn
, req
, fsp
)) {
5155 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5157 if (!NT_STATUS_IS_OK(status
)) {
5158 reply_nterror(req
, status
);
5162 if(fsp
->fake_file_handle
) {
5164 * This is actually for the QUOTA_FAKE_FILE --metze
5167 /* We know this name is ok, it's already passed the checks. */
5169 } else if(fsp
->fh
->fd
== -1) {
5171 * This is actually a QFILEINFO on a directory
5172 * handle (returned from an NT SMB). NT5.0 seems
5173 * to do this call. JRA.
5176 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5177 /* Always do lstat for UNIX calls. */
5178 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5179 DEBUG(3,("call_trans2qfilepathinfo: "
5180 "SMB_VFS_LSTAT of %s failed "
5182 smb_fname_str_dbg(smb_fname
),
5185 map_nt_error_from_unix(errno
));
5188 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_STAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname
),
5194 map_nt_error_from_unix(errno
));
5198 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5199 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5202 * Original code - this is an open file.
5204 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5205 DEBUG(3, ("fstat of %s failed (%s)\n",
5206 fsp_fnum_dbg(fsp
), strerror(errno
)));
5208 map_nt_error_from_unix(errno
));
5211 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5212 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5218 uint32_t ucf_flags
= 0;
5221 if (total_params
< 7) {
5222 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5226 info_level
= SVAL(params
,0);
5228 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5230 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5231 if (!lp_unix_extensions()) {
5232 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5235 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5236 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5237 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5238 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5242 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5244 STR_TERMINATE
, &status
);
5245 if (!NT_STATUS_IS_OK(status
)) {
5246 reply_nterror(req
, status
);
5250 status
= filename_convert(req
,
5252 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5257 if (!NT_STATUS_IS_OK(status
)) {
5258 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5259 reply_botherror(req
,
5260 NT_STATUS_PATH_NOT_COVERED
,
5261 ERRSRV
, ERRbadpath
);
5264 reply_nterror(req
, status
);
5268 /* If this is a stream, check if there is a delete_pending. */
5269 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5270 && is_ntfs_stream_smb_fname(smb_fname
)) {
5271 struct smb_filename
*smb_fname_base
= NULL
;
5273 /* Create an smb_filename with stream_name == NULL. */
5275 create_synthetic_smb_fname(talloc_tos(),
5276 smb_fname
->base_name
,
5279 if (!NT_STATUS_IS_OK(status
)) {
5280 reply_nterror(req
, status
);
5284 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5285 /* Always do lstat for UNIX calls. */
5286 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5287 DEBUG(3,("call_trans2qfilepathinfo: "
5288 "SMB_VFS_LSTAT of %s failed "
5290 smb_fname_str_dbg(smb_fname_base
),
5292 TALLOC_FREE(smb_fname_base
);
5294 map_nt_error_from_unix(errno
));
5298 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "fileinfo of %s failed "
5302 smb_fname_str_dbg(smb_fname_base
),
5304 TALLOC_FREE(smb_fname_base
);
5306 map_nt_error_from_unix(errno
));
5311 status
= file_name_hash(conn
,
5312 smb_fname_str_dbg(smb_fname_base
),
5314 if (!NT_STATUS_IS_OK(status
)) {
5315 TALLOC_FREE(smb_fname_base
);
5316 reply_nterror(req
, status
);
5320 fileid
= vfs_file_id_from_sbuf(conn
,
5321 &smb_fname_base
->st
);
5322 TALLOC_FREE(smb_fname_base
);
5323 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5324 if (delete_pending
) {
5325 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5330 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5331 /* Always do lstat for UNIX calls. */
5332 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5333 DEBUG(3,("call_trans2qfilepathinfo: "
5334 "SMB_VFS_LSTAT of %s failed (%s)\n",
5335 smb_fname_str_dbg(smb_fname
),
5338 map_nt_error_from_unix(errno
));
5343 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5344 DEBUG(3,("call_trans2qfilepathinfo: "
5345 "SMB_VFS_STAT of %s failed (%s)\n",
5346 smb_fname_str_dbg(smb_fname
),
5349 map_nt_error_from_unix(errno
));
5354 status
= file_name_hash(conn
,
5355 smb_fname_str_dbg(smb_fname
),
5357 if (!NT_STATUS_IS_OK(status
)) {
5358 reply_nterror(req
, status
);
5362 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5363 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5364 if (delete_pending
) {
5365 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5370 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5371 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5373 info_level
,tran_call
,total_data
));
5375 /* Pull out any data sent here before we realloc. */
5376 switch (info_level
) {
5377 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5379 /* Pull any EA list from the data portion. */
5382 if (total_data
< 4) {
5384 req
, NT_STATUS_INVALID_PARAMETER
);
5387 ea_size
= IVAL(pdata
,0);
5389 if (total_data
> 0 && ea_size
!= total_data
) {
5390 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5391 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5393 req
, NT_STATUS_INVALID_PARAMETER
);
5397 if (!lp_ea_support(SNUM(conn
))) {
5398 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5402 /* Pull out the list of names. */
5403 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5406 req
, NT_STATUS_INVALID_PARAMETER
);
5412 case SMB_QUERY_POSIX_LOCK
:
5414 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5415 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5419 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5421 req
, NT_STATUS_INVALID_PARAMETER
);
5425 /* Copy the lock range data. */
5426 lock_data
= (char *)talloc_memdup(
5427 req
, pdata
, total_data
);
5429 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5432 lock_data_count
= total_data
;
5438 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5439 if (*pparams
== NULL
) {
5440 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5447 * draft-leach-cifs-v1-spec-02.txt
5448 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5451 * The requested information is placed in the Data portion of the
5452 * transaction response. For the information levels greater than 0x100,
5453 * the transaction response has 1 parameter word which should be
5454 * ignored by the client.
5456 * However Windows only follows this rule for the IS_NAME_VALID call.
5458 switch (info_level
) {
5459 case SMB_INFO_IS_NAME_VALID
:
5464 if ((info_level
& 0xFF00) == 0xFF00) {
5466 * We use levels that start with 0xFF00
5467 * internally to represent SMB2 specific levels
5469 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5473 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5475 delete_pending
, write_time_ts
,
5477 lock_data_count
, lock_data
,
5478 req
->flags2
, max_data_bytes
,
5479 ppdata
, &data_size
);
5480 if (!NT_STATUS_IS_OK(status
)) {
5481 reply_nterror(req
, status
);
5485 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5491 /****************************************************************************
5492 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5494 ****************************************************************************/
5496 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5497 connection_struct
*conn
,
5498 struct smb_request
*req
,
5499 bool overwrite_if_exists
,
5500 const struct smb_filename
*smb_fname_old
,
5501 struct smb_filename
*smb_fname_new
)
5503 NTSTATUS status
= NT_STATUS_OK
;
5505 /* source must already exist. */
5506 if (!VALID_STAT(smb_fname_old
->st
)) {
5507 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5510 if (VALID_STAT(smb_fname_new
->st
)) {
5511 if (overwrite_if_exists
) {
5512 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5513 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5515 status
= unlink_internals(conn
,
5517 FILE_ATTRIBUTE_NORMAL
,
5520 if (!NT_STATUS_IS_OK(status
)) {
5524 /* Disallow if newname already exists. */
5525 return NT_STATUS_OBJECT_NAME_COLLISION
;
5529 /* No links from a directory. */
5530 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5531 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5534 /* Setting a hardlink to/from a stream isn't currently supported. */
5535 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5536 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5537 return NT_STATUS_INVALID_PARAMETER
;
5540 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5541 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5543 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5544 smb_fname_new
->base_name
) != 0) {
5545 status
= map_nt_error_from_unix(errno
);
5546 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5547 nt_errstr(status
), smb_fname_old
->base_name
,
5548 smb_fname_new
->base_name
));
5553 /****************************************************************************
5554 Deal with setting the time from any of the setfilepathinfo functions.
5555 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5556 calling this function.
5557 ****************************************************************************/
5559 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5561 const struct smb_filename
*smb_fname
,
5562 struct smb_file_time
*ft
,
5563 bool setting_write_time
)
5565 struct smb_filename smb_fname_base
;
5567 FILE_NOTIFY_CHANGE_LAST_ACCESS
5568 |FILE_NOTIFY_CHANGE_LAST_WRITE
5569 |FILE_NOTIFY_CHANGE_CREATION
;
5571 if (!VALID_STAT(smb_fname
->st
)) {
5572 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5575 /* get some defaults (no modifications) if any info is zero or -1. */
5576 if (null_timespec(ft
->create_time
)) {
5577 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5580 if (null_timespec(ft
->atime
)) {
5581 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5584 if (null_timespec(ft
->mtime
)) {
5585 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5588 if (!setting_write_time
) {
5589 /* ft->mtime comes from change time, not write time. */
5590 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5593 /* Ensure the resolution is the correct for
5594 * what we can store on this filesystem. */
5596 round_timespec(conn
->ts_res
, &ft
->create_time
);
5597 round_timespec(conn
->ts_res
, &ft
->ctime
);
5598 round_timespec(conn
->ts_res
, &ft
->atime
);
5599 round_timespec(conn
->ts_res
, &ft
->mtime
);
5601 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5602 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5603 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5604 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5605 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5606 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5607 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5608 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5610 if (setting_write_time
) {
5612 * This was a Windows setfileinfo on an open file.
5613 * NT does this a lot. We also need to
5614 * set the time here, as it can be read by
5615 * FindFirst/FindNext and with the patch for bug #2045
5616 * in smbd/fileio.c it ensures that this timestamp is
5617 * kept sticky even after a write. We save the request
5618 * away and will set it on file close and after a write. JRA.
5621 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5622 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5625 if (fsp
->base_fsp
) {
5626 set_sticky_write_time_fsp(fsp
->base_fsp
,
5629 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5632 set_sticky_write_time_path(
5633 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5638 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5640 /* Always call ntimes on the base, even if a stream was passed in. */
5641 smb_fname_base
= *smb_fname
;
5642 smb_fname_base
.stream_name
= NULL
;
5644 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5645 return map_nt_error_from_unix(errno
);
5648 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5649 smb_fname
->base_name
);
5650 return NT_STATUS_OK
;
5653 /****************************************************************************
5654 Deal with setting the dosmode from any of the setfilepathinfo functions.
5655 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5656 done before calling this function.
5657 ****************************************************************************/
5659 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5660 const struct smb_filename
*smb_fname
,
5663 struct smb_filename
*smb_fname_base
= NULL
;
5666 if (!VALID_STAT(smb_fname
->st
)) {
5667 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5670 /* Always operate on the base_name, even if a stream was passed in. */
5671 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5672 NULL
, &smb_fname
->st
,
5674 if (!NT_STATUS_IS_OK(status
)) {
5679 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5680 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5682 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5686 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5688 /* check the mode isn't different, before changing it */
5689 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5690 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5691 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5692 (unsigned int)dosmode
));
5694 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5696 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5698 smb_fname_str_dbg(smb_fname_base
),
5700 status
= map_nt_error_from_unix(errno
);
5704 status
= NT_STATUS_OK
;
5706 TALLOC_FREE(smb_fname_base
);
5710 /****************************************************************************
5711 Deal with setting the size from any of the setfilepathinfo functions.
5712 ****************************************************************************/
5714 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5715 struct smb_request
*req
,
5717 const struct smb_filename
*smb_fname
,
5718 const SMB_STRUCT_STAT
*psbuf
,
5720 bool fail_after_createfile
)
5722 NTSTATUS status
= NT_STATUS_OK
;
5723 struct smb_filename
*smb_fname_tmp
= NULL
;
5724 files_struct
*new_fsp
= NULL
;
5726 if (!VALID_STAT(*psbuf
)) {
5727 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5730 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5732 if (size
== get_file_size_stat(psbuf
)) {
5733 return NT_STATUS_OK
;
5736 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5737 smb_fname_str_dbg(smb_fname
), (double)size
));
5739 if (fsp
&& fsp
->fh
->fd
!= -1) {
5740 /* Handle based call. */
5741 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5742 return NT_STATUS_ACCESS_DENIED
;
5745 if (vfs_set_filelen(fsp
, size
) == -1) {
5746 return map_nt_error_from_unix(errno
);
5748 trigger_write_time_update_immediate(fsp
);
5749 return NT_STATUS_OK
;
5752 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5753 if (!NT_STATUS_IS_OK(status
)) {
5757 smb_fname_tmp
->st
= *psbuf
;
5759 status
= SMB_VFS_CREATE_FILE(
5762 0, /* root_dir_fid */
5763 smb_fname_tmp
, /* fname */
5764 FILE_WRITE_DATA
, /* access_mask */
5765 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5767 FILE_OPEN
, /* create_disposition*/
5768 0, /* create_options */
5769 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5770 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5771 0, /* allocation_size */
5772 0, /* private_flags */
5775 &new_fsp
, /* result */
5778 TALLOC_FREE(smb_fname_tmp
);
5780 if (!NT_STATUS_IS_OK(status
)) {
5781 /* NB. We check for open_was_deferred in the caller. */
5785 /* See RAW-SFILEINFO-END-OF-FILE */
5786 if (fail_after_createfile
) {
5787 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5788 return NT_STATUS_INVALID_LEVEL
;
5791 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5792 status
= map_nt_error_from_unix(errno
);
5793 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5797 trigger_write_time_update_immediate(new_fsp
);
5798 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5799 return NT_STATUS_OK
;
5802 /****************************************************************************
5803 Deal with SMB_INFO_SET_EA.
5804 ****************************************************************************/
5806 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5810 const struct smb_filename
*smb_fname
)
5812 struct ea_list
*ea_list
= NULL
;
5813 TALLOC_CTX
*ctx
= NULL
;
5814 NTSTATUS status
= NT_STATUS_OK
;
5816 if (total_data
< 10) {
5818 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5819 length. They seem to have no effect. Bug #3212. JRA */
5821 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5822 /* We're done. We only get EA info in this call. */
5823 return NT_STATUS_OK
;
5826 return NT_STATUS_INVALID_PARAMETER
;
5829 if (IVAL(pdata
,0) > total_data
) {
5830 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5831 IVAL(pdata
,0), (unsigned int)total_data
));
5832 return NT_STATUS_INVALID_PARAMETER
;
5836 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5838 return NT_STATUS_INVALID_PARAMETER
;
5841 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5846 /****************************************************************************
5847 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5848 ****************************************************************************/
5850 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5855 struct ea_list
*ea_list
= NULL
;
5859 return NT_STATUS_INVALID_HANDLE
;
5862 if (!lp_ea_support(SNUM(conn
))) {
5863 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5864 "EA's not supported.\n",
5865 (unsigned int)total_data
));
5866 return NT_STATUS_EAS_NOT_SUPPORTED
;
5869 if (total_data
< 10) {
5870 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5872 (unsigned int)total_data
));
5873 return NT_STATUS_INVALID_PARAMETER
;
5876 ea_list
= read_nttrans_ea_list(talloc_tos(),
5881 return NT_STATUS_INVALID_PARAMETER
;
5884 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5886 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5887 smb_fname_str_dbg(fsp
->fsp_name
),
5888 nt_errstr(status
) ));
5894 /****************************************************************************
5895 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5896 ****************************************************************************/
5898 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5902 struct smb_filename
*smb_fname
)
5904 NTSTATUS status
= NT_STATUS_OK
;
5905 bool delete_on_close
;
5908 if (total_data
< 1) {
5909 return NT_STATUS_INVALID_PARAMETER
;
5913 return NT_STATUS_INVALID_HANDLE
;
5916 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5917 dosmode
= dos_mode(conn
, smb_fname
);
5919 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5920 "delete_on_close = %u\n",
5921 smb_fname_str_dbg(smb_fname
),
5922 (unsigned int)dosmode
,
5923 (unsigned int)delete_on_close
));
5925 if (delete_on_close
) {
5926 status
= can_set_delete_on_close(fsp
, dosmode
);
5927 if (!NT_STATUS_IS_OK(status
)) {
5932 /* The set is across all open files on this dev/inode pair. */
5933 if (!set_delete_on_close(fsp
, delete_on_close
,
5934 conn
->session_info
->security_token
,
5935 conn
->session_info
->unix_token
)) {
5936 return NT_STATUS_ACCESS_DENIED
;
5938 return NT_STATUS_OK
;
5941 /****************************************************************************
5942 Deal with SMB_FILE_POSITION_INFORMATION.
5943 ****************************************************************************/
5945 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5950 uint64_t position_information
;
5952 if (total_data
< 8) {
5953 return NT_STATUS_INVALID_PARAMETER
;
5957 /* Ignore on pathname based set. */
5958 return NT_STATUS_OK
;
5961 position_information
= (uint64_t)IVAL(pdata
,0);
5962 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5964 DEBUG(10,("smb_file_position_information: Set file position "
5965 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5966 (double)position_information
));
5967 fsp
->fh
->position_information
= position_information
;
5968 return NT_STATUS_OK
;
5971 /****************************************************************************
5972 Deal with SMB_FILE_MODE_INFORMATION.
5973 ****************************************************************************/
5975 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5981 if (total_data
< 4) {
5982 return NT_STATUS_INVALID_PARAMETER
;
5984 mode
= IVAL(pdata
,0);
5985 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5986 return NT_STATUS_INVALID_PARAMETER
;
5988 return NT_STATUS_OK
;
5991 /****************************************************************************
5992 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5993 ****************************************************************************/
5995 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5996 struct smb_request
*req
,
5999 const struct smb_filename
*smb_fname
)
6001 char *link_target
= NULL
;
6002 const char *newname
= smb_fname
->base_name
;
6003 TALLOC_CTX
*ctx
= talloc_tos();
6005 /* Set a symbolic link. */
6006 /* Don't allow this if follow links is false. */
6008 if (total_data
== 0) {
6009 return NT_STATUS_INVALID_PARAMETER
;
6012 if (!lp_symlinks(SNUM(conn
))) {
6013 return NT_STATUS_ACCESS_DENIED
;
6016 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6017 total_data
, STR_TERMINATE
);
6020 return NT_STATUS_INVALID_PARAMETER
;
6023 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6024 newname
, link_target
));
6026 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6027 return map_nt_error_from_unix(errno
);
6030 return NT_STATUS_OK
;
6033 /****************************************************************************
6034 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6035 ****************************************************************************/
6037 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6038 struct smb_request
*req
,
6039 const char *pdata
, int total_data
,
6040 struct smb_filename
*smb_fname_new
)
6042 char *oldname
= NULL
;
6043 struct smb_filename
*smb_fname_old
= NULL
;
6044 TALLOC_CTX
*ctx
= talloc_tos();
6045 NTSTATUS status
= NT_STATUS_OK
;
6047 /* Set a hard link. */
6048 if (total_data
== 0) {
6049 return NT_STATUS_INVALID_PARAMETER
;
6052 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6053 total_data
, STR_TERMINATE
, &status
);
6054 if (!NT_STATUS_IS_OK(status
)) {
6058 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6059 smb_fname_str_dbg(smb_fname_new
), oldname
));
6061 status
= filename_convert(ctx
,
6063 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6068 if (!NT_STATUS_IS_OK(status
)) {
6072 return hardlink_internals(ctx
, conn
, req
, false,
6073 smb_fname_old
, smb_fname_new
);
6076 /****************************************************************************
6077 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6078 ****************************************************************************/
6080 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6081 struct smb_request
*req
,
6085 struct smb_filename
*smb_fname_src
)
6089 char *newname
= NULL
;
6090 struct smb_filename
*smb_fname_dst
= NULL
;
6091 NTSTATUS status
= NT_STATUS_OK
;
6092 TALLOC_CTX
*ctx
= talloc_tos();
6095 return NT_STATUS_INVALID_HANDLE
;
6098 if (total_data
< 20) {
6099 return NT_STATUS_INVALID_PARAMETER
;
6102 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6103 len
= IVAL(pdata
,16);
6105 if (len
> (total_data
- 20) || (len
== 0)) {
6106 return NT_STATUS_INVALID_PARAMETER
;
6109 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6110 &pdata
[20], len
, STR_TERMINATE
,
6112 if (!NT_STATUS_IS_OK(status
)) {
6116 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6119 status
= filename_convert(ctx
,
6121 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6126 if (!NT_STATUS_IS_OK(status
)) {
6130 if (fsp
->base_fsp
) {
6131 /* newname must be a stream name. */
6132 if (newname
[0] != ':') {
6133 return NT_STATUS_NOT_SUPPORTED
;
6136 /* Create an smb_fname to call rename_internals_fsp() with. */
6137 status
= create_synthetic_smb_fname(talloc_tos(),
6138 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6140 if (!NT_STATUS_IS_OK(status
)) {
6145 * Set the original last component, since
6146 * rename_internals_fsp() requires it.
6148 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6150 if (smb_fname_dst
->original_lcomp
== NULL
) {
6151 status
= NT_STATUS_NO_MEMORY
;
6157 DEBUG(10,("smb2_file_rename_information: "
6158 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6159 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6160 smb_fname_str_dbg(smb_fname_dst
)));
6161 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6162 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6166 TALLOC_FREE(smb_fname_dst
);
6170 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6171 struct smb_request
*req
,
6175 struct smb_filename
*smb_fname_src
)
6179 char *newname
= NULL
;
6180 struct smb_filename
*smb_fname_dst
= NULL
;
6181 NTSTATUS status
= NT_STATUS_OK
;
6182 TALLOC_CTX
*ctx
= talloc_tos();
6185 return NT_STATUS_INVALID_HANDLE
;
6188 if (total_data
< 20) {
6189 return NT_STATUS_INVALID_PARAMETER
;
6192 overwrite
= (CVAL(pdata
,0) ? true : false);
6193 len
= IVAL(pdata
,16);
6195 if (len
> (total_data
- 20) || (len
== 0)) {
6196 return NT_STATUS_INVALID_PARAMETER
;
6199 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6200 &pdata
[20], len
, STR_TERMINATE
,
6202 if (!NT_STATUS_IS_OK(status
)) {
6206 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6209 status
= filename_convert(ctx
,
6211 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6216 if (!NT_STATUS_IS_OK(status
)) {
6220 if (fsp
->base_fsp
) {
6221 /* No stream names. */
6222 return NT_STATUS_NOT_SUPPORTED
;
6225 DEBUG(10,("smb_file_link_information: "
6226 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6227 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6228 smb_fname_str_dbg(smb_fname_dst
)));
6229 status
= hardlink_internals(ctx
,
6236 TALLOC_FREE(smb_fname_dst
);
6240 /****************************************************************************
6241 Deal with SMB_FILE_RENAME_INFORMATION.
6242 ****************************************************************************/
6244 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6245 struct smb_request
*req
,
6249 struct smb_filename
*smb_fname_src
)
6254 char *newname
= NULL
;
6255 struct smb_filename
*smb_fname_dst
= NULL
;
6256 bool dest_has_wcard
= False
;
6257 NTSTATUS status
= NT_STATUS_OK
;
6259 TALLOC_CTX
*ctx
= talloc_tos();
6261 if (total_data
< 13) {
6262 return NT_STATUS_INVALID_PARAMETER
;
6265 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6266 root_fid
= IVAL(pdata
,4);
6267 len
= IVAL(pdata
,8);
6269 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6270 return NT_STATUS_INVALID_PARAMETER
;
6273 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6276 if (!NT_STATUS_IS_OK(status
)) {
6280 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6283 status
= resolve_dfspath_wcard(ctx
, conn
,
6284 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6287 !conn
->sconn
->using_smb2
,
6290 if (!NT_STATUS_IS_OK(status
)) {
6294 /* Check the new name has no '/' characters. */
6295 if (strchr_m(newname
, '/')) {
6296 return NT_STATUS_NOT_SUPPORTED
;
6299 if (fsp
&& fsp
->base_fsp
) {
6300 /* newname must be a stream name. */
6301 if (newname
[0] != ':') {
6302 return NT_STATUS_NOT_SUPPORTED
;
6305 /* Create an smb_fname to call rename_internals_fsp() with. */
6306 status
= create_synthetic_smb_fname(talloc_tos(),
6307 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6309 if (!NT_STATUS_IS_OK(status
)) {
6314 * Set the original last component, since
6315 * rename_internals_fsp() requires it.
6317 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6319 if (smb_fname_dst
->original_lcomp
== NULL
) {
6320 status
= NT_STATUS_NO_MEMORY
;
6326 * Build up an smb_fname_dst based on the filename passed in.
6327 * We basically just strip off the last component, and put on
6328 * the newname instead.
6330 char *base_name
= NULL
;
6332 /* newname must *not* be a stream name. */
6333 if (newname
[0] == ':') {
6334 return NT_STATUS_NOT_SUPPORTED
;
6338 * Strip off the last component (filename) of the path passed
6341 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6343 return NT_STATUS_NO_MEMORY
;
6345 p
= strrchr_m(base_name
, '/');
6349 base_name
= talloc_strdup(ctx
, "");
6351 return NT_STATUS_NO_MEMORY
;
6354 /* Append the new name. */
6355 base_name
= talloc_asprintf_append(base_name
,
6359 return NT_STATUS_NO_MEMORY
;
6362 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6365 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6368 /* If an error we expect this to be
6369 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6371 if (!NT_STATUS_IS_OK(status
)) {
6372 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6376 /* Create an smb_fname to call rename_internals_fsp() */
6377 status
= create_synthetic_smb_fname(ctx
,
6381 if (!NT_STATUS_IS_OK(status
)) {
6388 DEBUG(10,("smb_file_rename_information: "
6389 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6390 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6391 smb_fname_str_dbg(smb_fname_dst
)));
6392 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6395 DEBUG(10,("smb_file_rename_information: "
6396 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6397 smb_fname_str_dbg(smb_fname_src
),
6398 smb_fname_str_dbg(smb_fname_dst
)));
6399 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6400 smb_fname_dst
, 0, overwrite
, false,
6402 FILE_WRITE_ATTRIBUTES
);
6405 TALLOC_FREE(smb_fname_dst
);
6409 /****************************************************************************
6410 Deal with SMB_SET_POSIX_ACL.
6411 ****************************************************************************/
6413 #if defined(HAVE_POSIX_ACLS)
6414 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6418 const struct smb_filename
*smb_fname
)
6420 uint16 posix_acl_version
;
6421 uint16 num_file_acls
;
6422 uint16 num_def_acls
;
6423 bool valid_file_acls
= True
;
6424 bool valid_def_acls
= True
;
6426 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6427 return NT_STATUS_INVALID_PARAMETER
;
6429 posix_acl_version
= SVAL(pdata
,0);
6430 num_file_acls
= SVAL(pdata
,2);
6431 num_def_acls
= SVAL(pdata
,4);
6433 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6434 valid_file_acls
= False
;
6438 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6439 valid_def_acls
= False
;
6443 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6444 return NT_STATUS_INVALID_PARAMETER
;
6447 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6448 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6449 return NT_STATUS_INVALID_PARAMETER
;
6452 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6453 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6454 (unsigned int)num_file_acls
,
6455 (unsigned int)num_def_acls
));
6457 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6458 smb_fname
->base_name
, num_file_acls
,
6459 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6460 return map_nt_error_from_unix(errno
);
6463 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6464 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6465 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6466 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6467 return map_nt_error_from_unix(errno
);
6469 return NT_STATUS_OK
;
6473 /****************************************************************************
6474 Deal with SMB_SET_POSIX_LOCK.
6475 ****************************************************************************/
6477 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6478 struct smb_request
*req
,
6486 bool blocking_lock
= False
;
6487 enum brl_type lock_type
;
6489 NTSTATUS status
= NT_STATUS_OK
;
6491 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6492 return NT_STATUS_INVALID_HANDLE
;
6495 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6496 return NT_STATUS_INVALID_PARAMETER
;
6499 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6500 case POSIX_LOCK_TYPE_READ
:
6501 lock_type
= READ_LOCK
;
6503 case POSIX_LOCK_TYPE_WRITE
:
6504 /* Return the right POSIX-mappable error code for files opened read-only. */
6505 if (!fsp
->can_write
) {
6506 return NT_STATUS_INVALID_HANDLE
;
6508 lock_type
= WRITE_LOCK
;
6510 case POSIX_LOCK_TYPE_UNLOCK
:
6511 lock_type
= UNLOCK_LOCK
;
6514 return NT_STATUS_INVALID_PARAMETER
;
6517 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6518 blocking_lock
= False
;
6519 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6520 blocking_lock
= True
;
6522 return NT_STATUS_INVALID_PARAMETER
;
6525 if (!lp_blocking_locks(SNUM(conn
))) {
6526 blocking_lock
= False
;
6529 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6530 #if defined(HAVE_LONGLONG)
6531 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6532 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6533 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6534 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6535 #else /* HAVE_LONGLONG */
6536 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6537 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6538 #endif /* HAVE_LONGLONG */
6540 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6541 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6543 (unsigned int)lock_type
,
6544 (unsigned long long)smblctx
,
6548 if (lock_type
== UNLOCK_LOCK
) {
6549 status
= do_unlock(req
->sconn
->msg_ctx
,
6556 uint64_t block_smblctx
;
6558 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6570 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6572 * A blocking lock was requested. Package up
6573 * this smb into a queued request and push it
6574 * onto the blocking lock queue.
6576 if(push_blocking_lock_request(br_lck
,
6579 -1, /* infinite timeout. */
6587 TALLOC_FREE(br_lck
);
6591 TALLOC_FREE(br_lck
);
6597 /****************************************************************************
6598 Deal with SMB_SET_FILE_BASIC_INFO.
6599 ****************************************************************************/
6601 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6605 const struct smb_filename
*smb_fname
)
6607 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6608 struct smb_file_time ft
;
6610 NTSTATUS status
= NT_STATUS_OK
;
6614 if (total_data
< 36) {
6615 return NT_STATUS_INVALID_PARAMETER
;
6618 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6619 if (!NT_STATUS_IS_OK(status
)) {
6623 /* Set the attributes */
6624 dosmode
= IVAL(pdata
,32);
6625 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6626 if (!NT_STATUS_IS_OK(status
)) {
6631 ft
.create_time
= interpret_long_date(pdata
);
6634 ft
.atime
= interpret_long_date(pdata
+8);
6637 ft
.mtime
= interpret_long_date(pdata
+16);
6640 ft
.ctime
= interpret_long_date(pdata
+24);
6642 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6643 smb_fname_str_dbg(smb_fname
)));
6645 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6649 /****************************************************************************
6650 Deal with SMB_INFO_STANDARD.
6651 ****************************************************************************/
6653 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6657 const struct smb_filename
*smb_fname
)
6660 struct smb_file_time ft
;
6664 if (total_data
< 12) {
6665 return NT_STATUS_INVALID_PARAMETER
;
6669 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6671 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6673 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6675 DEBUG(10,("smb_set_info_standard: file %s\n",
6676 smb_fname_str_dbg(smb_fname
)));
6678 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6679 if (!NT_STATUS_IS_OK(status
)) {
6683 return smb_set_file_time(conn
,
6690 /****************************************************************************
6691 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6692 ****************************************************************************/
6694 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6695 struct smb_request
*req
,
6699 struct smb_filename
*smb_fname
)
6701 uint64_t allocation_size
= 0;
6702 NTSTATUS status
= NT_STATUS_OK
;
6703 files_struct
*new_fsp
= NULL
;
6705 if (!VALID_STAT(smb_fname
->st
)) {
6706 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6709 if (total_data
< 8) {
6710 return NT_STATUS_INVALID_PARAMETER
;
6713 allocation_size
= (uint64_t)IVAL(pdata
,0);
6714 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6715 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6716 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6717 (double)allocation_size
));
6719 if (allocation_size
) {
6720 allocation_size
= smb_roundup(conn
, allocation_size
);
6723 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6724 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6725 (double)allocation_size
));
6727 if (fsp
&& fsp
->fh
->fd
!= -1) {
6728 /* Open file handle. */
6729 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6730 return NT_STATUS_ACCESS_DENIED
;
6733 /* Only change if needed. */
6734 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6735 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6736 return map_nt_error_from_unix(errno
);
6739 /* But always update the time. */
6741 * This is equivalent to a write. Ensure it's seen immediately
6742 * if there are no pending writes.
6744 trigger_write_time_update_immediate(fsp
);
6745 return NT_STATUS_OK
;
6748 /* Pathname or stat or directory file. */
6749 status
= SMB_VFS_CREATE_FILE(
6752 0, /* root_dir_fid */
6753 smb_fname
, /* fname */
6754 FILE_WRITE_DATA
, /* access_mask */
6755 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6757 FILE_OPEN
, /* create_disposition*/
6758 0, /* create_options */
6759 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6760 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6761 0, /* allocation_size */
6762 0, /* private_flags */
6765 &new_fsp
, /* result */
6768 if (!NT_STATUS_IS_OK(status
)) {
6769 /* NB. We check for open_was_deferred in the caller. */
6773 /* Only change if needed. */
6774 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6775 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6776 status
= map_nt_error_from_unix(errno
);
6777 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6782 /* Changing the allocation size should set the last mod time. */
6784 * This is equivalent to a write. Ensure it's seen immediately
6785 * if there are no pending writes.
6787 trigger_write_time_update_immediate(new_fsp
);
6789 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6790 return NT_STATUS_OK
;
6793 /****************************************************************************
6794 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6795 ****************************************************************************/
6797 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6798 struct smb_request
*req
,
6802 const struct smb_filename
*smb_fname
,
6803 bool fail_after_createfile
)
6807 if (total_data
< 8) {
6808 return NT_STATUS_INVALID_PARAMETER
;
6811 size
= IVAL(pdata
,0);
6812 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6813 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6814 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6817 return smb_set_file_size(conn
, req
,
6822 fail_after_createfile
);
6825 /****************************************************************************
6826 Allow a UNIX info mknod.
6827 ****************************************************************************/
6829 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6832 const struct smb_filename
*smb_fname
)
6834 uint32 file_type
= IVAL(pdata
,56);
6835 #if defined(HAVE_MAKEDEV)
6836 uint32 dev_major
= IVAL(pdata
,60);
6837 uint32 dev_minor
= IVAL(pdata
,68);
6839 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6840 uint32 raw_unixmode
= IVAL(pdata
,84);
6844 if (total_data
< 100) {
6845 return NT_STATUS_INVALID_PARAMETER
;
6848 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6849 PERM_NEW_FILE
, &unixmode
);
6850 if (!NT_STATUS_IS_OK(status
)) {
6854 #if defined(HAVE_MAKEDEV)
6855 dev
= makedev(dev_major
, dev_minor
);
6858 switch (file_type
) {
6859 #if defined(S_IFIFO)
6860 case UNIX_TYPE_FIFO
:
6861 unixmode
|= S_IFIFO
;
6864 #if defined(S_IFSOCK)
6865 case UNIX_TYPE_SOCKET
:
6866 unixmode
|= S_IFSOCK
;
6869 #if defined(S_IFCHR)
6870 case UNIX_TYPE_CHARDEV
:
6871 unixmode
|= S_IFCHR
;
6874 #if defined(S_IFBLK)
6875 case UNIX_TYPE_BLKDEV
:
6876 unixmode
|= S_IFBLK
;
6880 return NT_STATUS_INVALID_PARAMETER
;
6883 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6884 "%.0f mode 0%o for file %s\n", (double)dev
,
6885 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6887 /* Ok - do the mknod. */
6888 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6889 return map_nt_error_from_unix(errno
);
6892 /* If any of the other "set" calls fail we
6893 * don't want to end up with a half-constructed mknod.
6896 if (lp_inherit_perms(SNUM(conn
))) {
6898 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6900 return NT_STATUS_NO_MEMORY
;
6902 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6904 TALLOC_FREE(parent
);
6907 return NT_STATUS_OK
;
6910 /****************************************************************************
6911 Deal with SMB_SET_FILE_UNIX_BASIC.
6912 ****************************************************************************/
6914 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6915 struct smb_request
*req
,
6919 const struct smb_filename
*smb_fname
)
6921 struct smb_file_time ft
;
6922 uint32 raw_unixmode
;
6925 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6926 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6927 NTSTATUS status
= NT_STATUS_OK
;
6928 bool delete_on_fail
= False
;
6929 enum perm_type ptype
;
6930 files_struct
*all_fsps
= NULL
;
6931 bool modify_mtime
= true;
6933 struct smb_filename
*smb_fname_tmp
= NULL
;
6934 SMB_STRUCT_STAT sbuf
;
6938 if (total_data
< 100) {
6939 return NT_STATUS_INVALID_PARAMETER
;
6942 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6943 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6944 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6945 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6948 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6949 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6950 set_owner
= (uid_t
)IVAL(pdata
,40);
6951 set_grp
= (gid_t
)IVAL(pdata
,48);
6952 raw_unixmode
= IVAL(pdata
,84);
6954 if (VALID_STAT(smb_fname
->st
)) {
6955 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6956 ptype
= PERM_EXISTING_DIR
;
6958 ptype
= PERM_EXISTING_FILE
;
6961 ptype
= PERM_NEW_FILE
;
6964 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6966 if (!NT_STATUS_IS_OK(status
)) {
6970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6971 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6972 smb_fname_str_dbg(smb_fname
), (double)size
,
6973 (unsigned int)set_owner
, (unsigned int)set_grp
,
6974 (int)raw_unixmode
));
6976 sbuf
= smb_fname
->st
;
6978 if (!VALID_STAT(sbuf
)) {
6980 * The only valid use of this is to create character and block
6981 * devices, and named pipes. This is deprecated (IMHO) and
6982 * a new info level should be used for mknod. JRA.
6985 status
= smb_unix_mknod(conn
,
6989 if (!NT_STATUS_IS_OK(status
)) {
6993 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6995 if (!NT_STATUS_IS_OK(status
)) {
6999 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7000 status
= map_nt_error_from_unix(errno
);
7001 TALLOC_FREE(smb_fname_tmp
);
7002 SMB_VFS_UNLINK(conn
, smb_fname
);
7006 sbuf
= smb_fname_tmp
->st
;
7007 smb_fname
= smb_fname_tmp
;
7009 /* Ensure we don't try and change anything else. */
7010 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7011 size
= get_file_size_stat(&sbuf
);
7012 ft
.atime
= sbuf
.st_ex_atime
;
7013 ft
.mtime
= sbuf
.st_ex_mtime
;
7015 * We continue here as we might want to change the
7018 delete_on_fail
= True
;
7022 /* Horrible backwards compatibility hack as an old server bug
7023 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7027 size
= get_file_size_stat(&sbuf
);
7032 * Deal with the UNIX specific mode set.
7035 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7036 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7037 "setting mode 0%o for file %s\n",
7038 (unsigned int)unixmode
,
7039 smb_fname_str_dbg(smb_fname
)));
7040 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7041 return map_nt_error_from_unix(errno
);
7046 * Deal with the UNIX specific uid set.
7049 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7050 (sbuf
.st_ex_uid
!= set_owner
)) {
7053 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7054 "changing owner %u for path %s\n",
7055 (unsigned int)set_owner
,
7056 smb_fname_str_dbg(smb_fname
)));
7058 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7059 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7060 set_owner
, (gid_t
)-1);
7062 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7063 set_owner
, (gid_t
)-1);
7067 status
= map_nt_error_from_unix(errno
);
7068 if (delete_on_fail
) {
7069 SMB_VFS_UNLINK(conn
, smb_fname
);
7076 * Deal with the UNIX specific gid set.
7079 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7080 (sbuf
.st_ex_gid
!= set_grp
)) {
7081 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7082 "changing group %u for file %s\n",
7083 (unsigned int)set_owner
,
7084 smb_fname_str_dbg(smb_fname
)));
7085 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7087 status
= map_nt_error_from_unix(errno
);
7088 if (delete_on_fail
) {
7089 SMB_VFS_UNLINK(conn
, smb_fname
);
7095 /* Deal with any size changes. */
7097 status
= smb_set_file_size(conn
, req
,
7103 if (!NT_STATUS_IS_OK(status
)) {
7107 /* Deal with any time changes. */
7108 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7109 /* No change, don't cancel anything. */
7113 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7114 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7115 all_fsps
= file_find_di_next(all_fsps
)) {
7117 * We're setting the time explicitly for UNIX.
7118 * Cancel any pending changes over all handles.
7120 all_fsps
->update_write_time_on_close
= false;
7121 TALLOC_FREE(all_fsps
->update_write_time_event
);
7125 * Override the "setting_write_time"
7126 * parameter here as it almost does what
7127 * we need. Just remember if we modified
7128 * mtime and send the notify ourselves.
7130 if (null_timespec(ft
.mtime
)) {
7131 modify_mtime
= false;
7134 status
= smb_set_file_time(conn
,
7140 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7141 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7146 /****************************************************************************
7147 Deal with SMB_SET_FILE_UNIX_INFO2.
7148 ****************************************************************************/
7150 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7151 struct smb_request
*req
,
7155 const struct smb_filename
*smb_fname
)
7161 if (total_data
< 116) {
7162 return NT_STATUS_INVALID_PARAMETER
;
7165 /* Start by setting all the fields that are common between UNIX_BASIC
7168 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7170 if (!NT_STATUS_IS_OK(status
)) {
7174 smb_fflags
= IVAL(pdata
, 108);
7175 smb_fmask
= IVAL(pdata
, 112);
7177 /* NB: We should only attempt to alter the file flags if the client
7178 * sends a non-zero mask.
7180 if (smb_fmask
!= 0) {
7181 int stat_fflags
= 0;
7183 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7184 smb_fmask
, &stat_fflags
)) {
7185 /* Client asked to alter a flag we don't understand. */
7186 return NT_STATUS_INVALID_PARAMETER
;
7189 if (fsp
&& fsp
->fh
->fd
!= -1) {
7190 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7191 return NT_STATUS_NOT_SUPPORTED
;
7193 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7194 stat_fflags
) != 0) {
7195 return map_nt_error_from_unix(errno
);
7200 /* XXX: need to add support for changing the create_time here. You
7201 * can do this for paths on Darwin with setattrlist(2). The right way
7202 * to hook this up is probably by extending the VFS utimes interface.
7205 return NT_STATUS_OK
;
7208 /****************************************************************************
7209 Create a directory with POSIX semantics.
7210 ****************************************************************************/
7212 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7213 struct smb_request
*req
,
7216 struct smb_filename
*smb_fname
,
7217 int *pdata_return_size
)
7219 NTSTATUS status
= NT_STATUS_OK
;
7220 uint32 raw_unixmode
= 0;
7221 uint32 mod_unixmode
= 0;
7222 mode_t unixmode
= (mode_t
)0;
7223 files_struct
*fsp
= NULL
;
7224 uint16 info_level_return
= 0;
7226 char *pdata
= *ppdata
;
7228 if (total_data
< 18) {
7229 return NT_STATUS_INVALID_PARAMETER
;
7232 raw_unixmode
= IVAL(pdata
,8);
7233 /* Next 4 bytes are not yet defined. */
7235 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7236 PERM_NEW_DIR
, &unixmode
);
7237 if (!NT_STATUS_IS_OK(status
)) {
7241 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7243 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7244 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7246 status
= SMB_VFS_CREATE_FILE(
7249 0, /* root_dir_fid */
7250 smb_fname
, /* fname */
7251 FILE_READ_ATTRIBUTES
, /* access_mask */
7252 FILE_SHARE_NONE
, /* share_access */
7253 FILE_CREATE
, /* create_disposition*/
7254 FILE_DIRECTORY_FILE
, /* create_options */
7255 mod_unixmode
, /* file_attributes */
7256 0, /* oplock_request */
7257 0, /* allocation_size */
7258 0, /* private_flags */
7264 if (NT_STATUS_IS_OK(status
)) {
7265 close_file(req
, fsp
, NORMAL_CLOSE
);
7268 info_level_return
= SVAL(pdata
,16);
7270 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7271 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7272 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7273 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7275 *pdata_return_size
= 12;
7278 /* Realloc the data size */
7279 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7280 if (*ppdata
== NULL
) {
7281 *pdata_return_size
= 0;
7282 return NT_STATUS_NO_MEMORY
;
7286 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7287 SSVAL(pdata
,2,0); /* No fnum. */
7288 SIVAL(pdata
,4,info
); /* Was directory created. */
7290 switch (info_level_return
) {
7291 case SMB_QUERY_FILE_UNIX_BASIC
:
7292 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7293 SSVAL(pdata
,10,0); /* Padding. */
7294 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7297 case SMB_QUERY_FILE_UNIX_INFO2
:
7298 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7299 SSVAL(pdata
,10,0); /* Padding. */
7300 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7304 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7305 SSVAL(pdata
,10,0); /* Padding. */
7312 /****************************************************************************
7313 Open/Create a file with POSIX semantics.
7314 ****************************************************************************/
7316 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7317 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7319 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7320 struct smb_request
*req
,
7323 struct smb_filename
*smb_fname
,
7324 int *pdata_return_size
)
7326 bool extended_oplock_granted
= False
;
7327 char *pdata
= *ppdata
;
7329 uint32 wire_open_mode
= 0;
7330 uint32 raw_unixmode
= 0;
7331 uint32 mod_unixmode
= 0;
7332 uint32 create_disp
= 0;
7333 uint32 access_mask
= 0;
7334 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7335 NTSTATUS status
= NT_STATUS_OK
;
7336 mode_t unixmode
= (mode_t
)0;
7337 files_struct
*fsp
= NULL
;
7338 int oplock_request
= 0;
7340 uint16 info_level_return
= 0;
7342 if (total_data
< 18) {
7343 return NT_STATUS_INVALID_PARAMETER
;
7346 flags
= IVAL(pdata
,0);
7347 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7348 if (oplock_request
) {
7349 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7352 wire_open_mode
= IVAL(pdata
,4);
7354 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7355 return smb_posix_mkdir(conn
, req
,
7362 switch (wire_open_mode
& SMB_ACCMODE
) {
7364 access_mask
= SMB_O_RDONLY_MAPPING
;
7367 access_mask
= SMB_O_WRONLY_MAPPING
;
7370 access_mask
= (SMB_O_RDONLY_MAPPING
|
7371 SMB_O_WRONLY_MAPPING
);
7374 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7375 (unsigned int)wire_open_mode
));
7376 return NT_STATUS_INVALID_PARAMETER
;
7379 wire_open_mode
&= ~SMB_ACCMODE
;
7381 /* First take care of O_CREAT|O_EXCL interactions. */
7382 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7383 case (SMB_O_CREAT
| SMB_O_EXCL
):
7384 /* File exists fail. File not exist create. */
7385 create_disp
= FILE_CREATE
;
7388 /* File exists open. File not exist create. */
7389 create_disp
= FILE_OPEN_IF
;
7392 /* File exists open. File not exist fail. */
7393 create_disp
= FILE_OPEN
;
7396 /* O_EXCL on its own without O_CREAT is undefined. */
7398 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7399 (unsigned int)wire_open_mode
));
7400 return NT_STATUS_INVALID_PARAMETER
;
7403 /* Next factor in the effects of O_TRUNC. */
7404 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7406 if (wire_open_mode
& SMB_O_TRUNC
) {
7407 switch (create_disp
) {
7409 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7410 /* Leave create_disp alone as
7411 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7413 /* File exists fail. File not exist create. */
7416 /* SMB_O_CREAT | SMB_O_TRUNC */
7417 /* File exists overwrite. File not exist create. */
7418 create_disp
= FILE_OVERWRITE_IF
;
7422 /* File exists overwrite. File not exist fail. */
7423 create_disp
= FILE_OVERWRITE
;
7426 /* Cannot get here. */
7427 smb_panic("smb_posix_open: logic error");
7428 return NT_STATUS_INVALID_PARAMETER
;
7432 raw_unixmode
= IVAL(pdata
,8);
7433 /* Next 4 bytes are not yet defined. */
7435 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7436 (VALID_STAT(smb_fname
->st
) ?
7437 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7440 if (!NT_STATUS_IS_OK(status
)) {
7444 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7446 if (wire_open_mode
& SMB_O_SYNC
) {
7447 create_options
|= FILE_WRITE_THROUGH
;
7449 if (wire_open_mode
& SMB_O_APPEND
) {
7450 access_mask
|= FILE_APPEND_DATA
;
7452 if (wire_open_mode
& SMB_O_DIRECT
) {
7453 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7456 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7457 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7458 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7459 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7461 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7462 create_options
|= FILE_DIRECTORY_FILE
;
7465 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7466 smb_fname_str_dbg(smb_fname
),
7467 (unsigned int)wire_open_mode
,
7468 (unsigned int)unixmode
));
7470 status
= SMB_VFS_CREATE_FILE(
7473 0, /* root_dir_fid */
7474 smb_fname
, /* fname */
7475 access_mask
, /* access_mask */
7476 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7478 create_disp
, /* create_disposition*/
7479 create_options
, /* create_options */
7480 mod_unixmode
, /* file_attributes */
7481 oplock_request
, /* oplock_request */
7482 0, /* allocation_size */
7483 0, /* private_flags */
7489 if (!NT_STATUS_IS_OK(status
)) {
7493 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7494 extended_oplock_granted
= True
;
7497 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7498 extended_oplock_granted
= True
;
7501 info_level_return
= SVAL(pdata
,16);
7503 /* Allocate the correct return size. */
7505 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7506 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7507 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7508 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7510 *pdata_return_size
= 12;
7513 /* Realloc the data size */
7514 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7515 if (*ppdata
== NULL
) {
7516 close_file(req
, fsp
, ERROR_CLOSE
);
7517 *pdata_return_size
= 0;
7518 return NT_STATUS_NO_MEMORY
;
7522 if (extended_oplock_granted
) {
7523 if (flags
& REQUEST_BATCH_OPLOCK
) {
7524 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7526 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7528 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7529 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7531 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7534 SSVAL(pdata
,2,fsp
->fnum
);
7535 SIVAL(pdata
,4,info
); /* Was file created etc. */
7537 switch (info_level_return
) {
7538 case SMB_QUERY_FILE_UNIX_BASIC
:
7539 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7540 SSVAL(pdata
,10,0); /* padding. */
7541 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7544 case SMB_QUERY_FILE_UNIX_INFO2
:
7545 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7546 SSVAL(pdata
,10,0); /* padding. */
7547 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7551 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7552 SSVAL(pdata
,10,0); /* padding. */
7555 return NT_STATUS_OK
;
7558 /****************************************************************************
7559 Delete a file with POSIX semantics.
7560 ****************************************************************************/
7562 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7563 struct smb_request
*req
,
7566 struct smb_filename
*smb_fname
)
7568 NTSTATUS status
= NT_STATUS_OK
;
7569 files_struct
*fsp
= NULL
;
7573 int create_options
= 0;
7575 struct share_mode_lock
*lck
= NULL
;
7577 if (total_data
< 2) {
7578 return NT_STATUS_INVALID_PARAMETER
;
7581 flags
= SVAL(pdata
,0);
7583 if (!VALID_STAT(smb_fname
->st
)) {
7584 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7587 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7588 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7589 return NT_STATUS_NOT_A_DIRECTORY
;
7592 DEBUG(10,("smb_posix_unlink: %s %s\n",
7593 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7594 smb_fname_str_dbg(smb_fname
)));
7596 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7597 create_options
|= FILE_DIRECTORY_FILE
;
7600 status
= SMB_VFS_CREATE_FILE(
7603 0, /* root_dir_fid */
7604 smb_fname
, /* fname */
7605 DELETE_ACCESS
, /* access_mask */
7606 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7608 FILE_OPEN
, /* create_disposition*/
7609 create_options
, /* create_options */
7610 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7611 0, /* oplock_request */
7612 0, /* allocation_size */
7613 0, /* private_flags */
7619 if (!NT_STATUS_IS_OK(status
)) {
7624 * Don't lie to client. If we can't really delete due to
7625 * non-POSIX opens return SHARING_VIOLATION.
7628 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7630 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7631 "lock for file %s\n", fsp_str_dbg(fsp
)));
7632 close_file(req
, fsp
, NORMAL_CLOSE
);
7633 return NT_STATUS_INVALID_PARAMETER
;
7637 * See if others still have the file open. If this is the case, then
7638 * don't delete. If all opens are POSIX delete we can set the delete
7639 * on close disposition.
7641 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7642 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7643 if (is_valid_share_mode_entry(e
)) {
7644 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7647 if (share_mode_stale_pid(lck
->data
, i
)) {
7650 /* Fail with sharing violation. */
7651 close_file(req
, fsp
, NORMAL_CLOSE
);
7653 return NT_STATUS_SHARING_VIOLATION
;
7658 * Set the delete on close.
7660 status
= smb_set_file_disposition_info(conn
,
7666 if (!NT_STATUS_IS_OK(status
)) {
7667 close_file(req
, fsp
, NORMAL_CLOSE
);
7672 return close_file(req
, fsp
, NORMAL_CLOSE
);
7675 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7676 struct smb_request
*req
,
7677 TALLOC_CTX
*mem_ctx
,
7678 uint16_t info_level
,
7680 struct smb_filename
*smb_fname
,
7681 char **ppdata
, int total_data
,
7684 char *pdata
= *ppdata
;
7685 NTSTATUS status
= NT_STATUS_OK
;
7686 int data_return_size
= 0;
7690 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7691 return NT_STATUS_INVALID_LEVEL
;
7694 if (!CAN_WRITE(conn
)) {
7695 /* Allow POSIX opens. The open path will deny
7696 * any non-readonly opens. */
7697 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7698 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7702 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7703 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7705 info_level
, total_data
));
7707 switch (info_level
) {
7709 case SMB_INFO_STANDARD
:
7711 status
= smb_set_info_standard(conn
,
7719 case SMB_INFO_SET_EA
:
7721 status
= smb_info_set_ea(conn
,
7729 case SMB_SET_FILE_BASIC_INFO
:
7730 case SMB_FILE_BASIC_INFORMATION
:
7732 status
= smb_set_file_basic_info(conn
,
7740 case SMB_FILE_ALLOCATION_INFORMATION
:
7741 case SMB_SET_FILE_ALLOCATION_INFO
:
7743 status
= smb_set_file_allocation_info(conn
, req
,
7751 case SMB_FILE_END_OF_FILE_INFORMATION
:
7752 case SMB_SET_FILE_END_OF_FILE_INFO
:
7755 * XP/Win7 both fail after the createfile with
7756 * SMB_SET_FILE_END_OF_FILE_INFO but not
7757 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7758 * The level is known here, so pass it down
7762 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7764 status
= smb_set_file_end_of_file_info(conn
, req
,
7773 case SMB_FILE_DISPOSITION_INFORMATION
:
7774 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7777 /* JRA - We used to just ignore this on a path ?
7778 * Shouldn't this be invalid level on a pathname
7781 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7782 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7785 status
= smb_set_file_disposition_info(conn
,
7793 case SMB_FILE_POSITION_INFORMATION
:
7795 status
= smb_file_position_information(conn
,
7802 case SMB_FILE_FULL_EA_INFORMATION
:
7804 status
= smb_set_file_full_ea_info(conn
,
7811 /* From tridge Samba4 :
7812 * MODE_INFORMATION in setfileinfo (I have no
7813 * idea what "mode information" on a file is - it takes a value of 0,
7814 * 2, 4 or 6. What could it be?).
7817 case SMB_FILE_MODE_INFORMATION
:
7819 status
= smb_file_mode_information(conn
,
7826 * CIFS UNIX extensions.
7829 case SMB_SET_FILE_UNIX_BASIC
:
7831 status
= smb_set_file_unix_basic(conn
, req
,
7839 case SMB_SET_FILE_UNIX_INFO2
:
7841 status
= smb_set_file_unix_info2(conn
, req
,
7849 case SMB_SET_FILE_UNIX_LINK
:
7852 /* We must have a pathname for this. */
7853 return NT_STATUS_INVALID_LEVEL
;
7855 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7856 total_data
, smb_fname
);
7860 case SMB_SET_FILE_UNIX_HLINK
:
7863 /* We must have a pathname for this. */
7864 return NT_STATUS_INVALID_LEVEL
;
7866 status
= smb_set_file_unix_hlink(conn
, req
,
7872 case SMB_FILE_RENAME_INFORMATION
:
7874 status
= smb_file_rename_information(conn
, req
,
7880 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7882 /* SMB2 rename information. */
7883 status
= smb2_file_rename_information(conn
, req
,
7889 case SMB_FILE_LINK_INFORMATION
:
7891 status
= smb_file_link_information(conn
, req
,
7897 #if defined(HAVE_POSIX_ACLS)
7898 case SMB_SET_POSIX_ACL
:
7900 status
= smb_set_posix_acl(conn
,
7909 case SMB_SET_POSIX_LOCK
:
7912 return NT_STATUS_INVALID_LEVEL
;
7914 status
= smb_set_posix_lock(conn
, req
,
7915 pdata
, total_data
, fsp
);
7919 case SMB_POSIX_PATH_OPEN
:
7922 /* We must have a pathname for this. */
7923 return NT_STATUS_INVALID_LEVEL
;
7926 status
= smb_posix_open(conn
, req
,
7934 case SMB_POSIX_PATH_UNLINK
:
7937 /* We must have a pathname for this. */
7938 return NT_STATUS_INVALID_LEVEL
;
7941 status
= smb_posix_unlink(conn
, req
,
7949 return NT_STATUS_INVALID_LEVEL
;
7952 if (!NT_STATUS_IS_OK(status
)) {
7956 *ret_data_size
= data_return_size
;
7957 return NT_STATUS_OK
;
7960 /****************************************************************************
7961 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7962 ****************************************************************************/
7964 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7965 struct smb_request
*req
,
7966 unsigned int tran_call
,
7967 char **pparams
, int total_params
,
7968 char **ppdata
, int total_data
,
7969 unsigned int max_data_bytes
)
7971 char *params
= *pparams
;
7972 char *pdata
= *ppdata
;
7974 struct smb_filename
*smb_fname
= NULL
;
7975 files_struct
*fsp
= NULL
;
7976 NTSTATUS status
= NT_STATUS_OK
;
7977 int data_return_size
= 0;
7980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7984 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7985 if (total_params
< 4) {
7986 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7990 fsp
= file_fsp(req
, SVAL(params
,0));
7991 /* Basic check for non-null fsp. */
7992 if (!check_fsp_open(conn
, req
, fsp
)) {
7995 info_level
= SVAL(params
,2);
7997 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7999 if (!NT_STATUS_IS_OK(status
)) {
8000 reply_nterror(req
, status
);
8004 if(fsp
->fh
->fd
== -1) {
8006 * This is actually a SETFILEINFO on a directory
8007 * handle (returned from an NT SMB). NT5.0 seems
8008 * to do this call. JRA.
8010 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8011 /* Always do lstat for UNIX calls. */
8012 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8013 DEBUG(3,("call_trans2setfilepathinfo: "
8014 "SMB_VFS_LSTAT of %s failed "
8016 smb_fname_str_dbg(smb_fname
),
8018 reply_nterror(req
, map_nt_error_from_unix(errno
));
8022 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8023 DEBUG(3,("call_trans2setfilepathinfo: "
8024 "fileinfo of %s failed (%s)\n",
8025 smb_fname_str_dbg(smb_fname
),
8027 reply_nterror(req
, map_nt_error_from_unix(errno
));
8031 } else if (fsp
->print_file
) {
8033 * Doing a DELETE_ON_CLOSE should cancel a print job.
8035 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8036 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8038 DEBUG(3,("call_trans2setfilepathinfo: "
8039 "Cancelling print job (%s)\n",
8043 send_trans2_replies(conn
, req
, params
, 2,
8049 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8054 * Original code - this is an open file.
8056 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8057 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8058 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8060 reply_nterror(req
, map_nt_error_from_unix(errno
));
8066 uint32_t ucf_flags
= 0;
8069 if (total_params
< 7) {
8070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8074 info_level
= SVAL(params
,0);
8075 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8076 total_params
- 6, STR_TERMINATE
,
8078 if (!NT_STATUS_IS_OK(status
)) {
8079 reply_nterror(req
, status
);
8083 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8084 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8085 info_level
== SMB_FILE_RENAME_INFORMATION
||
8086 info_level
== SMB_POSIX_PATH_UNLINK
) {
8087 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8090 status
= filename_convert(req
, conn
,
8091 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8096 if (!NT_STATUS_IS_OK(status
)) {
8097 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8098 reply_botherror(req
,
8099 NT_STATUS_PATH_NOT_COVERED
,
8100 ERRSRV
, ERRbadpath
);
8103 reply_nterror(req
, status
);
8107 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8109 * For CIFS UNIX extensions the target name may not exist.
8112 /* Always do lstat for UNIX calls. */
8113 SMB_VFS_LSTAT(conn
, smb_fname
);
8115 } else if (!VALID_STAT(smb_fname
->st
) &&
8116 SMB_VFS_STAT(conn
, smb_fname
)) {
8117 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8119 smb_fname_str_dbg(smb_fname
),
8121 reply_nterror(req
, map_nt_error_from_unix(errno
));
8126 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8127 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8129 info_level
,total_data
));
8131 /* Realloc the parameter size */
8132 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8133 if (*pparams
== NULL
) {
8134 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8141 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8147 if (!NT_STATUS_IS_OK(status
)) {
8148 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8149 /* We have re-scheduled this call. */
8152 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8153 /* We have re-scheduled this call. */
8156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8157 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8158 ERRSRV
, ERRbadpath
);
8161 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8162 reply_openerror(req
, status
);
8166 reply_nterror(req
, status
);
8170 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8176 /****************************************************************************
8177 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8178 ****************************************************************************/
8180 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8181 char **pparams
, int total_params
,
8182 char **ppdata
, int total_data
,
8183 unsigned int max_data_bytes
)
8185 struct smb_filename
*smb_dname
= NULL
;
8186 char *params
= *pparams
;
8187 char *pdata
= *ppdata
;
8188 char *directory
= NULL
;
8189 NTSTATUS status
= NT_STATUS_OK
;
8190 struct ea_list
*ea_list
= NULL
;
8191 TALLOC_CTX
*ctx
= talloc_tos();
8193 if (!CAN_WRITE(conn
)) {
8194 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8198 if (total_params
< 5) {
8199 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8203 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8204 total_params
- 4, STR_TERMINATE
,
8206 if (!NT_STATUS_IS_OK(status
)) {
8207 reply_nterror(req
, status
);
8211 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8213 status
= filename_convert(ctx
,
8215 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8221 if (!NT_STATUS_IS_OK(status
)) {
8222 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8223 reply_botherror(req
,
8224 NT_STATUS_PATH_NOT_COVERED
,
8225 ERRSRV
, ERRbadpath
);
8228 reply_nterror(req
, status
);
8233 * OS/2 workplace shell seems to send SET_EA requests of "null"
8234 * length (4 bytes containing IVAL 4).
8235 * They seem to have no effect. Bug #3212. JRA.
8238 if (total_data
&& (total_data
!= 4)) {
8239 /* Any data in this call is an EA list. */
8240 if (total_data
< 10) {
8241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8245 if (IVAL(pdata
,0) > total_data
) {
8246 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8247 IVAL(pdata
,0), (unsigned int)total_data
));
8248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8252 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8255 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8259 if (!lp_ea_support(SNUM(conn
))) {
8260 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8264 /* If total_data == 4 Windows doesn't care what values
8265 * are placed in that field, it just ignores them.
8266 * The System i QNTC IBM SMB client puts bad values here,
8267 * so ignore them. */
8269 status
= create_directory(conn
, req
, smb_dname
);
8271 if (!NT_STATUS_IS_OK(status
)) {
8272 reply_nterror(req
, status
);
8276 /* Try and set any given EA. */
8278 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8279 if (!NT_STATUS_IS_OK(status
)) {
8280 reply_nterror(req
, status
);
8285 /* Realloc the parameter and data sizes */
8286 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8287 if(*pparams
== NULL
) {
8288 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8295 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8298 TALLOC_FREE(smb_dname
);
8302 /****************************************************************************
8303 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8304 We don't actually do this - we just send a null response.
8305 ****************************************************************************/
8307 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8308 struct smb_request
*req
,
8309 char **pparams
, int total_params
,
8310 char **ppdata
, int total_data
,
8311 unsigned int max_data_bytes
)
8313 char *params
= *pparams
;
8316 if (total_params
< 6) {
8317 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8321 info_level
= SVAL(params
,4);
8322 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8324 switch (info_level
) {
8329 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8333 /* Realloc the parameter and data sizes */
8334 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8335 if (*pparams
== NULL
) {
8336 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8341 SSVAL(params
,0,fnf_handle
);
8342 SSVAL(params
,2,0); /* No changes */
8343 SSVAL(params
,4,0); /* No EA errors */
8350 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8355 /****************************************************************************
8356 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8357 changes). Currently this does nothing.
8358 ****************************************************************************/
8360 static void call_trans2findnotifynext(connection_struct
*conn
,
8361 struct smb_request
*req
,
8362 char **pparams
, int total_params
,
8363 char **ppdata
, int total_data
,
8364 unsigned int max_data_bytes
)
8366 char *params
= *pparams
;
8368 DEBUG(3,("call_trans2findnotifynext\n"));
8370 /* Realloc the parameter and data sizes */
8371 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8372 if (*pparams
== NULL
) {
8373 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8378 SSVAL(params
,0,0); /* No changes */
8379 SSVAL(params
,2,0); /* No EA errors */
8381 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8386 /****************************************************************************
8387 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8388 ****************************************************************************/
8390 static void call_trans2getdfsreferral(connection_struct
*conn
,
8391 struct smb_request
*req
,
8392 char **pparams
, int total_params
,
8393 char **ppdata
, int total_data
,
8394 unsigned int max_data_bytes
)
8396 char *params
= *pparams
;
8397 char *pathname
= NULL
;
8399 int max_referral_level
;
8400 NTSTATUS status
= NT_STATUS_OK
;
8401 TALLOC_CTX
*ctx
= talloc_tos();
8403 DEBUG(10,("call_trans2getdfsreferral\n"));
8405 if (total_params
< 3) {
8406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8410 max_referral_level
= SVAL(params
,0);
8412 if(!lp_host_msdfs()) {
8413 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8417 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8418 total_params
- 2, STR_TERMINATE
);
8420 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8423 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8424 ppdata
,&status
)) < 0) {
8425 reply_nterror(req
, status
);
8429 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8430 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8431 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8436 #define LMCAT_SPL 0x53
8437 #define LMFUNC_GETJOBID 0x60
8439 /****************************************************************************
8440 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8441 ****************************************************************************/
8443 static void call_trans2ioctl(connection_struct
*conn
,
8444 struct smb_request
*req
,
8445 char **pparams
, int total_params
,
8446 char **ppdata
, int total_data
,
8447 unsigned int max_data_bytes
)
8449 char *pdata
= *ppdata
;
8450 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8452 /* check for an invalid fid before proceeding */
8455 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8459 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8460 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8461 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8462 if (*ppdata
== NULL
) {
8463 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8468 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8469 CAN ACCEPT THIS IN UNICODE. JRA. */
8472 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8474 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8475 lp_netbios_name(), 15,
8476 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8477 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8478 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8479 STR_ASCII
|STR_TERMINATE
); /* Service name */
8480 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8485 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8486 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8489 /****************************************************************************
8490 Reply to a SMBfindclose (stop trans2 directory search).
8491 ****************************************************************************/
8493 void reply_findclose(struct smb_request
*req
)
8496 struct smbd_server_connection
*sconn
= req
->sconn
;
8498 START_PROFILE(SMBfindclose
);
8501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8502 END_PROFILE(SMBfindclose
);
8506 dptr_num
= SVALS(req
->vwv
+0, 0);
8508 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8510 dptr_close(sconn
, &dptr_num
);
8512 reply_outbuf(req
, 0, 0);
8514 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8516 END_PROFILE(SMBfindclose
);
8520 /****************************************************************************
8521 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8522 ****************************************************************************/
8524 void reply_findnclose(struct smb_request
*req
)
8528 START_PROFILE(SMBfindnclose
);
8531 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8532 END_PROFILE(SMBfindnclose
);
8536 dptr_num
= SVAL(req
->vwv
+0, 0);
8538 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8540 /* We never give out valid handles for a
8541 findnotifyfirst - so any dptr_num is ok here.
8544 reply_outbuf(req
, 0, 0);
8546 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8548 END_PROFILE(SMBfindnclose
);
8552 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8553 struct trans_state
*state
)
8555 if (get_Protocol() >= PROTOCOL_NT1
) {
8556 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8557 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8560 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8561 if (state
->call
!= TRANSACT2_QFSINFO
&&
8562 state
->call
!= TRANSACT2_SETFSINFO
) {
8563 DEBUG(0,("handle_trans2: encryption required "
8565 (unsigned int)state
->call
));
8566 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8571 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8573 /* Now we must call the relevant TRANS2 function */
8574 switch(state
->call
) {
8575 case TRANSACT2_OPEN
:
8577 START_PROFILE(Trans2_open
);
8578 call_trans2open(conn
, req
,
8579 &state
->param
, state
->total_param
,
8580 &state
->data
, state
->total_data
,
8581 state
->max_data_return
);
8582 END_PROFILE(Trans2_open
);
8586 case TRANSACT2_FINDFIRST
:
8588 START_PROFILE(Trans2_findfirst
);
8589 call_trans2findfirst(conn
, req
,
8590 &state
->param
, state
->total_param
,
8591 &state
->data
, state
->total_data
,
8592 state
->max_data_return
);
8593 END_PROFILE(Trans2_findfirst
);
8597 case TRANSACT2_FINDNEXT
:
8599 START_PROFILE(Trans2_findnext
);
8600 call_trans2findnext(conn
, req
,
8601 &state
->param
, state
->total_param
,
8602 &state
->data
, state
->total_data
,
8603 state
->max_data_return
);
8604 END_PROFILE(Trans2_findnext
);
8608 case TRANSACT2_QFSINFO
:
8610 START_PROFILE(Trans2_qfsinfo
);
8611 call_trans2qfsinfo(conn
, req
,
8612 &state
->param
, state
->total_param
,
8613 &state
->data
, state
->total_data
,
8614 state
->max_data_return
);
8615 END_PROFILE(Trans2_qfsinfo
);
8619 case TRANSACT2_SETFSINFO
:
8621 START_PROFILE(Trans2_setfsinfo
);
8622 call_trans2setfsinfo(conn
, req
,
8623 &state
->param
, state
->total_param
,
8624 &state
->data
, state
->total_data
,
8625 state
->max_data_return
);
8626 END_PROFILE(Trans2_setfsinfo
);
8630 case TRANSACT2_QPATHINFO
:
8631 case TRANSACT2_QFILEINFO
:
8633 START_PROFILE(Trans2_qpathinfo
);
8634 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8635 &state
->param
, state
->total_param
,
8636 &state
->data
, state
->total_data
,
8637 state
->max_data_return
);
8638 END_PROFILE(Trans2_qpathinfo
);
8642 case TRANSACT2_SETPATHINFO
:
8643 case TRANSACT2_SETFILEINFO
:
8645 START_PROFILE(Trans2_setpathinfo
);
8646 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8647 &state
->param
, state
->total_param
,
8648 &state
->data
, state
->total_data
,
8649 state
->max_data_return
);
8650 END_PROFILE(Trans2_setpathinfo
);
8654 case TRANSACT2_FINDNOTIFYFIRST
:
8656 START_PROFILE(Trans2_findnotifyfirst
);
8657 call_trans2findnotifyfirst(conn
, req
,
8658 &state
->param
, state
->total_param
,
8659 &state
->data
, state
->total_data
,
8660 state
->max_data_return
);
8661 END_PROFILE(Trans2_findnotifyfirst
);
8665 case TRANSACT2_FINDNOTIFYNEXT
:
8667 START_PROFILE(Trans2_findnotifynext
);
8668 call_trans2findnotifynext(conn
, req
,
8669 &state
->param
, state
->total_param
,
8670 &state
->data
, state
->total_data
,
8671 state
->max_data_return
);
8672 END_PROFILE(Trans2_findnotifynext
);
8676 case TRANSACT2_MKDIR
:
8678 START_PROFILE(Trans2_mkdir
);
8679 call_trans2mkdir(conn
, req
,
8680 &state
->param
, state
->total_param
,
8681 &state
->data
, state
->total_data
,
8682 state
->max_data_return
);
8683 END_PROFILE(Trans2_mkdir
);
8687 case TRANSACT2_GET_DFS_REFERRAL
:
8689 START_PROFILE(Trans2_get_dfs_referral
);
8690 call_trans2getdfsreferral(conn
, req
,
8691 &state
->param
, state
->total_param
,
8692 &state
->data
, state
->total_data
,
8693 state
->max_data_return
);
8694 END_PROFILE(Trans2_get_dfs_referral
);
8698 case TRANSACT2_IOCTL
:
8700 START_PROFILE(Trans2_ioctl
);
8701 call_trans2ioctl(conn
, req
,
8702 &state
->param
, state
->total_param
,
8703 &state
->data
, state
->total_data
,
8704 state
->max_data_return
);
8705 END_PROFILE(Trans2_ioctl
);
8710 /* Error in request */
8711 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8712 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8716 /****************************************************************************
8717 Reply to a SMBtrans2.
8718 ****************************************************************************/
8720 void reply_trans2(struct smb_request
*req
)
8722 connection_struct
*conn
= req
->conn
;
8727 unsigned int tran_call
;
8728 struct trans_state
*state
;
8731 START_PROFILE(SMBtrans2
);
8733 if (req
->wct
< 14) {
8734 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8735 END_PROFILE(SMBtrans2
);
8739 dsoff
= SVAL(req
->vwv
+12, 0);
8740 dscnt
= SVAL(req
->vwv
+11, 0);
8741 psoff
= SVAL(req
->vwv
+10, 0);
8742 pscnt
= SVAL(req
->vwv
+9, 0);
8743 tran_call
= SVAL(req
->vwv
+14, 0);
8745 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8746 if (!NT_STATUS_IS_OK(result
)) {
8747 DEBUG(2, ("Got invalid trans2 request: %s\n",
8748 nt_errstr(result
)));
8749 reply_nterror(req
, result
);
8750 END_PROFILE(SMBtrans2
);
8755 switch (tran_call
) {
8756 /* List the allowed trans2 calls on IPC$ */
8757 case TRANSACT2_OPEN
:
8758 case TRANSACT2_GET_DFS_REFERRAL
:
8759 case TRANSACT2_QFILEINFO
:
8760 case TRANSACT2_QFSINFO
:
8761 case TRANSACT2_SETFSINFO
:
8764 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8765 END_PROFILE(SMBtrans2
);
8770 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8771 DEBUG(0, ("talloc failed\n"));
8772 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8773 END_PROFILE(SMBtrans2
);
8777 state
->cmd
= SMBtrans2
;
8779 state
->mid
= req
->mid
;
8780 state
->vuid
= req
->vuid
;
8781 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8782 state
->setup
= NULL
;
8783 state
->total_param
= SVAL(req
->vwv
+0, 0);
8784 state
->param
= NULL
;
8785 state
->total_data
= SVAL(req
->vwv
+1, 0);
8787 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8788 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8789 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8790 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8791 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8793 state
->call
= tran_call
;
8795 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8796 is so as a sanity check */
8797 if (state
->setup_count
!= 1) {
8799 * Need to have rc=0 for ioctl to get job id for OS/2.
8800 * Network printing will fail if function is not successful.
8801 * Similar function in reply.c will be used if protocol
8802 * is LANMAN1.0 instead of LM1.2X002.
8803 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8804 * outbuf doesn't have to be set(only job id is used).
8806 if ( (state
->setup_count
== 4)
8807 && (tran_call
== TRANSACT2_IOCTL
)
8808 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8809 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8810 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8812 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8813 DEBUG(2,("Transaction is %d\n",tran_call
));
8815 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8816 END_PROFILE(SMBtrans2
);
8821 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8824 if (state
->total_data
) {
8826 if (trans_oob(state
->total_data
, 0, dscnt
)
8827 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8831 /* Can't use talloc here, the core routines do realloc on the
8832 * params and data. */
8833 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8834 if (state
->data
== NULL
) {
8835 DEBUG(0,("reply_trans2: data malloc fail for %u "
8836 "bytes !\n", (unsigned int)state
->total_data
));
8838 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8839 END_PROFILE(SMBtrans2
);
8843 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8846 if (state
->total_param
) {
8848 if (trans_oob(state
->total_param
, 0, pscnt
)
8849 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8853 /* Can't use talloc here, the core routines do realloc on the
8854 * params and data. */
8855 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8856 if (state
->param
== NULL
) {
8857 DEBUG(0,("reply_trans: param malloc fail for %u "
8858 "bytes !\n", (unsigned int)state
->total_param
));
8859 SAFE_FREE(state
->data
);
8861 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8862 END_PROFILE(SMBtrans2
);
8866 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8869 state
->received_data
= dscnt
;
8870 state
->received_param
= pscnt
;
8872 if ((state
->received_param
== state
->total_param
) &&
8873 (state
->received_data
== state
->total_data
)) {
8875 handle_trans2(conn
, req
, state
);
8877 SAFE_FREE(state
->data
);
8878 SAFE_FREE(state
->param
);
8880 END_PROFILE(SMBtrans2
);
8884 DLIST_ADD(conn
->pending_trans
, state
);
8886 /* We need to send an interim response then receive the rest
8887 of the parameter/data bytes */
8888 reply_outbuf(req
, 0, 0);
8889 show_msg((char *)req
->outbuf
);
8890 END_PROFILE(SMBtrans2
);
8895 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8896 SAFE_FREE(state
->data
);
8897 SAFE_FREE(state
->param
);
8899 END_PROFILE(SMBtrans2
);
8900 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8904 /****************************************************************************
8905 Reply to a SMBtranss2
8906 ****************************************************************************/
8908 void reply_transs2(struct smb_request
*req
)
8910 connection_struct
*conn
= req
->conn
;
8911 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8912 struct trans_state
*state
;
8914 START_PROFILE(SMBtranss2
);
8916 show_msg((const char *)req
->inbuf
);
8918 /* Windows clients expect all replies to
8919 a transact secondary (SMBtranss2 0x33)
8920 to have a command code of transact
8921 (SMBtrans2 0x32). See bug #8989
8922 and also [MS-CIFS] section 2.2.4.47.2
8925 req
->cmd
= SMBtrans2
;
8928 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8929 END_PROFILE(SMBtranss2
);
8933 for (state
= conn
->pending_trans
; state
!= NULL
;
8934 state
= state
->next
) {
8935 if (state
->mid
== req
->mid
) {
8940 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8941 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8942 END_PROFILE(SMBtranss2
);
8946 /* Revise state->total_param and state->total_data in case they have
8947 changed downwards */
8949 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8950 state
->total_param
= SVAL(req
->vwv
+0, 0);
8951 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8952 state
->total_data
= SVAL(req
->vwv
+1, 0);
8954 pcnt
= SVAL(req
->vwv
+2, 0);
8955 poff
= SVAL(req
->vwv
+3, 0);
8956 pdisp
= SVAL(req
->vwv
+4, 0);
8958 dcnt
= SVAL(req
->vwv
+5, 0);
8959 doff
= SVAL(req
->vwv
+6, 0);
8960 ddisp
= SVAL(req
->vwv
+7, 0);
8962 state
->received_param
+= pcnt
;
8963 state
->received_data
+= dcnt
;
8965 if ((state
->received_data
> state
->total_data
) ||
8966 (state
->received_param
> state
->total_param
))
8970 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8971 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8974 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8978 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8979 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8982 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8985 if ((state
->received_param
< state
->total_param
) ||
8986 (state
->received_data
< state
->total_data
)) {
8987 END_PROFILE(SMBtranss2
);
8991 handle_trans2(conn
, req
, state
);
8993 DLIST_REMOVE(conn
->pending_trans
, state
);
8994 SAFE_FREE(state
->data
);
8995 SAFE_FREE(state
->param
);
8998 END_PROFILE(SMBtranss2
);
9003 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9004 DLIST_REMOVE(conn
->pending_trans
, state
);
9005 SAFE_FREE(state
->data
);
9006 SAFE_FREE(state
->param
);
9008 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9009 END_PROFILE(SMBtranss2
);