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 case PERM_EXISTING_FILE
:
1369 /* Apply mode mask */
1370 ret
&= lp_create_mask(SNUM(conn
));
1371 /* Add in force bits */
1372 ret
|= lp_force_create_mode(SNUM(conn
));
1375 case PERM_EXISTING_DIR
:
1376 ret
&= lp_dir_mask(SNUM(conn
));
1377 /* Add in force bits */
1378 ret
|= lp_force_dir_mode(SNUM(conn
));
1383 return NT_STATUS_OK
;
1386 /****************************************************************************
1387 Needed to show the msdfs symlinks as directories. Modifies psbuf
1388 to be a directory if it's a msdfs link.
1389 ****************************************************************************/
1391 static bool check_msdfs_link(connection_struct
*conn
,
1392 const char *pathname
,
1393 SMB_STRUCT_STAT
*psbuf
)
1395 int saved_errno
= errno
;
1396 if(lp_host_msdfs() &&
1397 lp_msdfs_root(SNUM(conn
)) &&
1398 is_msdfs_link(conn
, pathname
, psbuf
)) {
1400 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1403 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1404 errno
= saved_errno
;
1407 errno
= saved_errno
;
1412 /****************************************************************************
1413 Get a level dependent lanman2 dir entry.
1414 ****************************************************************************/
1416 struct smbd_dirptr_lanman2_state
{
1417 connection_struct
*conn
;
1418 uint32_t info_level
;
1419 bool check_mangled_names
;
1421 bool got_exact_match
;
1424 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1430 struct smbd_dirptr_lanman2_state
*state
=
1431 (struct smbd_dirptr_lanman2_state
*)private_data
;
1433 char mangled_name
[13]; /* mangled 8.3 name. */
1437 /* Mangle fname if it's an illegal name. */
1438 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1439 ok
= name_to_8_3(dname
, mangled_name
,
1440 true, state
->conn
->params
);
1444 fname
= mangled_name
;
1449 got_match
= exact_match(state
->has_wild
,
1450 state
->conn
->case_sensitive
,
1452 state
->got_exact_match
= got_match
;
1454 got_match
= mask_match(fname
, mask
,
1455 state
->conn
->case_sensitive
);
1458 if(!got_match
&& state
->check_mangled_names
&&
1459 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1461 * It turns out that NT matches wildcards against
1462 * both long *and* short names. This may explain some
1463 * of the wildcard wierdness from old DOS clients
1464 * that some people have been seeing.... JRA.
1466 /* Force the mangling into 8.3. */
1467 ok
= name_to_8_3(fname
, mangled_name
,
1468 false, state
->conn
->params
);
1473 got_match
= exact_match(state
->has_wild
,
1474 state
->conn
->case_sensitive
,
1475 mangled_name
, mask
);
1476 state
->got_exact_match
= got_match
;
1478 got_match
= mask_match(mangled_name
, mask
,
1479 state
->conn
->case_sensitive
);
1487 *_fname
= talloc_strdup(ctx
, fname
);
1488 if (*_fname
== NULL
) {
1495 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1497 struct smb_filename
*smb_fname
,
1500 struct smbd_dirptr_lanman2_state
*state
=
1501 (struct smbd_dirptr_lanman2_state
*)private_data
;
1502 bool ms_dfs_link
= false;
1505 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1506 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1507 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1508 "Couldn't lstat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname
),
1513 } else if (!VALID_STAT(smb_fname
->st
) &&
1514 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1515 /* Needed to show the msdfs symlinks as
1518 ms_dfs_link
= check_msdfs_link(state
->conn
,
1519 smb_fname
->base_name
,
1522 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1523 "Couldn't stat [%s] (%s)\n",
1524 smb_fname_str_dbg(smb_fname
),
1531 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1533 mode
= dos_mode(state
->conn
, smb_fname
);
1540 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1541 connection_struct
*conn
,
1543 uint32_t info_level
,
1544 struct ea_list
*name_list
,
1545 bool check_mangled_names
,
1546 bool requires_resume_key
,
1549 const struct smb_filename
*smb_fname
,
1550 int space_remaining
,
1557 uint64_t *last_entry_off
)
1559 char *p
, *q
, *pdata
= *ppdata
;
1561 uint64_t file_size
= 0;
1562 uint64_t allocation_size
= 0;
1563 uint64_t file_index
= 0;
1565 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1566 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1568 char *last_entry_ptr
;
1573 *out_of_space
= false;
1575 ZERO_STRUCT(mdate_ts
);
1576 ZERO_STRUCT(adate_ts
);
1577 ZERO_STRUCT(create_date_ts
);
1578 ZERO_STRUCT(cdate_ts
);
1580 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1581 file_size
= get_file_size_stat(&smb_fname
->st
);
1583 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1585 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1587 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1588 adate_ts
= smb_fname
->st
.st_ex_atime
;
1589 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1590 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1592 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1593 dos_filetime_timespec(&create_date_ts
);
1594 dos_filetime_timespec(&mdate_ts
);
1595 dos_filetime_timespec(&adate_ts
);
1596 dos_filetime_timespec(&cdate_ts
);
1599 create_date
= convert_timespec_to_time_t(create_date_ts
);
1600 mdate
= convert_timespec_to_time_t(mdate_ts
);
1601 adate
= convert_timespec_to_time_t(adate_ts
);
1603 /* align the record */
1604 SMB_ASSERT(align
>= 1);
1606 off
= (int)PTR_DIFF(pdata
, base_data
);
1607 pad
= (off
+ (align
-1)) & ~(align
-1);
1610 if (pad
&& pad
> space_remaining
) {
1611 *out_of_space
= true;
1612 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1613 "for padding (wanted %u, had %d)\n",
1616 return false; /* Not finished - just out of space */
1620 /* initialize padding to 0 */
1622 memset(pdata
, 0, pad
);
1624 space_remaining
-= pad
;
1626 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1636 switch (info_level
) {
1637 case SMB_FIND_INFO_STANDARD
:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1639 if(requires_resume_key
) {
1643 srv_put_dos_date2(p
,0,create_date
);
1644 srv_put_dos_date2(p
,4,adate
);
1645 srv_put_dos_date2(p
,8,mdate
);
1646 SIVAL(p
,12,(uint32
)file_size
);
1647 SIVAL(p
,16,(uint32
)allocation_size
);
1651 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1652 p
+= ucs2_align(base_data
, p
, 0);
1654 len
= srvstr_push(base_data
, flags2
, p
,
1655 fname
, PTR_DIFF(end_data
, p
),
1657 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1659 SCVAL(nameptr
, -1, len
- 2);
1661 SCVAL(nameptr
, -1, 0);
1665 SCVAL(nameptr
, -1, len
- 1);
1667 SCVAL(nameptr
, -1, 0);
1673 case SMB_FIND_EA_SIZE
:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1675 if (requires_resume_key
) {
1679 srv_put_dos_date2(p
,0,create_date
);
1680 srv_put_dos_date2(p
,4,adate
);
1681 srv_put_dos_date2(p
,8,mdate
);
1682 SIVAL(p
,12,(uint32
)file_size
);
1683 SIVAL(p
,16,(uint32
)allocation_size
);
1686 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1688 SIVAL(p
,22,ea_size
); /* Extended attributes */
1692 len
= srvstr_push(base_data
, flags2
,
1693 p
, fname
, PTR_DIFF(end_data
, p
),
1694 STR_TERMINATE
| STR_NOALIGN
);
1695 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1708 SCVAL(nameptr
,0,len
);
1710 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1713 case SMB_FIND_EA_LIST
:
1715 struct ea_list
*file_list
= NULL
;
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1723 if (requires_resume_key
) {
1727 srv_put_dos_date2(p
,0,create_date
);
1728 srv_put_dos_date2(p
,4,adate
);
1729 srv_put_dos_date2(p
,8,mdate
);
1730 SIVAL(p
,12,(uint32
)file_size
);
1731 SIVAL(p
,16,(uint32
)allocation_size
);
1733 p
+= 22; /* p now points to the EA area. */
1735 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1737 &ea_len
, &file_list
);
1738 if (!NT_STATUS_IS_OK(status
)) {
1741 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1743 /* We need to determine if this entry will fit in the space available. */
1744 /* Max string size is 255 bytes. */
1745 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1746 *out_of_space
= true;
1747 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1748 "(wanted %u, had %d)\n",
1749 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1751 return False
; /* Not finished - just out of space */
1754 /* Push the ea_data followed by the name. */
1755 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1757 len
= srvstr_push(base_data
, flags2
,
1758 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1759 STR_TERMINATE
| STR_NOALIGN
);
1760 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1773 SCVAL(nameptr
,0,len
);
1775 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1779 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1781 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1783 SIVAL(p
,0,reskey
); p
+= 4;
1784 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1787 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1788 SOFF_T(p
,0,file_size
); p
+= 8;
1789 SOFF_T(p
,0,allocation_size
); p
+= 8;
1790 SIVAL(p
,0,mode
); p
+= 4;
1791 q
= p
; p
+= 4; /* q is placeholder for name length. */
1793 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1795 SIVAL(p
,0,ea_size
); /* Extended attributes */
1798 /* Clear the short name buffer. This is
1799 * IMPORTANT as not doing so will trigger
1800 * a Win2k client bug. JRA.
1802 if (!was_8_3
&& check_mangled_names
) {
1803 char mangled_name
[13]; /* mangled 8.3 name. */
1804 if (!name_to_8_3(fname
,mangled_name
,True
,
1806 /* Error - mangle failed ! */
1807 memset(mangled_name
,'\0',12);
1809 mangled_name
[12] = 0;
1810 len
= srvstr_push(base_data
, flags2
,
1811 p
+2, mangled_name
, 24,
1812 STR_UPPER
|STR_UNICODE
);
1814 memset(p
+ 2 + len
,'\0',24 - len
);
1821 len
= srvstr_push(base_data
, flags2
, p
,
1822 fname
, PTR_DIFF(end_data
, p
),
1823 STR_TERMINATE_ASCII
);
1827 len
= PTR_DIFF(p
, pdata
);
1828 pad
= (len
+ (align
-1)) & ~(align
-1);
1830 * offset to the next entry, the caller
1831 * will overwrite it for the last entry
1832 * that's why we always include the padding
1836 * set padding to zero
1839 memset(p
, 0, pad
- len
);
1846 case SMB_FIND_FILE_DIRECTORY_INFO
:
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1849 SIVAL(p
,0,reskey
); p
+= 4;
1850 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1851 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1852 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1853 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1854 SOFF_T(p
,0,file_size
); p
+= 8;
1855 SOFF_T(p
,0,allocation_size
); p
+= 8;
1856 SIVAL(p
,0,mode
); p
+= 4;
1857 len
= srvstr_push(base_data
, flags2
,
1858 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1859 STR_TERMINATE_ASCII
);
1863 len
= PTR_DIFF(p
, pdata
);
1864 pad
= (len
+ (align
-1)) & ~(align
-1);
1866 * offset to the next entry, the caller
1867 * will overwrite it for the last entry
1868 * that's why we always include the padding
1872 * set padding to zero
1875 memset(p
, 0, pad
- len
);
1882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1883 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1885 SIVAL(p
,0,reskey
); p
+= 4;
1886 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1887 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1888 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1889 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1890 SOFF_T(p
,0,file_size
); p
+= 8;
1891 SOFF_T(p
,0,allocation_size
); p
+= 8;
1892 SIVAL(p
,0,mode
); p
+= 4;
1893 q
= p
; p
+= 4; /* q is placeholder for name length. */
1895 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1897 SIVAL(p
,0,ea_size
); /* Extended attributes */
1900 len
= srvstr_push(base_data
, flags2
, p
,
1901 fname
, PTR_DIFF(end_data
, p
),
1902 STR_TERMINATE_ASCII
);
1906 len
= PTR_DIFF(p
, pdata
);
1907 pad
= (len
+ (align
-1)) & ~(align
-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1915 * set padding to zero
1918 memset(p
, 0, pad
- len
);
1925 case SMB_FIND_FILE_NAMES_INFO
:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1928 SIVAL(p
,0,reskey
); p
+= 4;
1930 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1931 acl on a dir (tridge) */
1932 len
= srvstr_push(base_data
, flags2
, p
,
1933 fname
, PTR_DIFF(end_data
, p
),
1934 STR_TERMINATE_ASCII
);
1938 len
= PTR_DIFF(p
, pdata
);
1939 pad
= (len
+ (align
-1)) & ~(align
-1);
1941 * offset to the next entry, the caller
1942 * will overwrite it for the last entry
1943 * that's why we always include the padding
1947 * set padding to zero
1950 memset(p
, 0, pad
- len
);
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1958 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1960 SIVAL(p
,0,reskey
); p
+= 4;
1961 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1962 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1963 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1964 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1965 SOFF_T(p
,0,file_size
); p
+= 8;
1966 SOFF_T(p
,0,allocation_size
); p
+= 8;
1967 SIVAL(p
,0,mode
); p
+= 4;
1968 q
= p
; p
+= 4; /* q is placeholder for name length. */
1970 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1972 SIVAL(p
,0,ea_size
); /* Extended attributes */
1975 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1976 SBVAL(p
,0,file_index
); p
+= 8;
1977 len
= srvstr_push(base_data
, flags2
, p
,
1978 fname
, PTR_DIFF(end_data
, p
),
1979 STR_TERMINATE_ASCII
);
1983 len
= PTR_DIFF(p
, pdata
);
1984 pad
= (len
+ (align
-1)) & ~(align
-1);
1986 * offset to the next entry, the caller
1987 * will overwrite it for the last entry
1988 * that's why we always include the padding
1992 * set padding to zero
1995 memset(p
, 0, pad
- len
);
2002 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2006 SIVAL(p
,0,reskey
); p
+= 4;
2007 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2008 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2009 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2010 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2011 SOFF_T(p
,0,file_size
); p
+= 8;
2012 SOFF_T(p
,0,allocation_size
); p
+= 8;
2013 SIVAL(p
,0,mode
); p
+= 4;
2014 q
= p
; p
+= 4; /* q is placeholder for name length */
2016 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2018 SIVAL(p
,0,ea_size
); /* Extended attributes */
2021 /* Clear the short name buffer. This is
2022 * IMPORTANT as not doing so will trigger
2023 * a Win2k client bug. JRA.
2025 if (!was_8_3
&& check_mangled_names
) {
2026 char mangled_name
[13]; /* mangled 8.3 name. */
2027 if (!name_to_8_3(fname
,mangled_name
,True
,
2029 /* Error - mangle failed ! */
2030 memset(mangled_name
,'\0',12);
2032 mangled_name
[12] = 0;
2033 len
= srvstr_push(base_data
, flags2
,
2034 p
+2, mangled_name
, 24,
2035 STR_UPPER
|STR_UNICODE
);
2038 memset(p
+ 2 + len
,'\0',24 - len
);
2045 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2046 SBVAL(p
,0,file_index
); p
+= 8;
2047 len
= srvstr_push(base_data
, flags2
, p
,
2048 fname
, PTR_DIFF(end_data
, p
),
2049 STR_TERMINATE_ASCII
);
2053 len
= PTR_DIFF(p
, pdata
);
2054 pad
= (len
+ (align
-1)) & ~(align
-1);
2056 * offset to the next entry, the caller
2057 * will overwrite it for the last entry
2058 * that's why we always include the padding
2062 * set padding to zero
2065 memset(p
, 0, pad
- len
);
2072 /* CIFS UNIX Extension. */
2074 case SMB_FIND_FILE_UNIX
:
2075 case SMB_FIND_FILE_UNIX_INFO2
:
2077 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2079 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2081 if (info_level
== SMB_FIND_FILE_UNIX
) {
2082 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2083 p
= store_file_unix_basic(conn
, p
,
2084 NULL
, &smb_fname
->st
);
2085 len
= srvstr_push(base_data
, flags2
, p
,
2086 fname
, PTR_DIFF(end_data
, p
),
2089 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2090 p
= store_file_unix_basic_info2(conn
, p
,
2091 NULL
, &smb_fname
->st
);
2094 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2095 PTR_DIFF(end_data
, p
), 0);
2096 SIVAL(nameptr
, 0, len
);
2101 len
= PTR_DIFF(p
, pdata
);
2102 pad
= (len
+ (align
-1)) & ~(align
-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2110 * set padding to zero
2113 memset(p
, 0, pad
- len
);
2118 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2126 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2127 *out_of_space
= true;
2128 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2129 "(wanted %u, had %d)\n",
2130 (unsigned int)PTR_DIFF(p
,pdata
),
2132 return false; /* Not finished - just out of space */
2135 /* Setup the last entry pointer, as an offset from base_data */
2136 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2137 /* Advance the data pointer to the next slot */
2143 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2144 connection_struct
*conn
,
2145 struct dptr_struct
*dirptr
,
2147 const char *path_mask
,
2150 int requires_resume_key
,
2158 int space_remaining
,
2160 bool *got_exact_match
,
2161 int *_last_entry_off
,
2162 struct ea_list
*name_list
)
2165 const char *mask
= NULL
;
2166 long prev_dirpos
= 0;
2169 struct smb_filename
*smb_fname
= NULL
;
2170 struct smbd_dirptr_lanman2_state state
;
2172 uint64_t last_entry_off
= 0;
2176 state
.info_level
= info_level
;
2177 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2178 state
.has_wild
= dptr_has_wild(dirptr
);
2179 state
.got_exact_match
= false;
2181 *out_of_space
= false;
2182 *got_exact_match
= false;
2184 p
= strrchr_m(path_mask
,'/');
2195 ok
= smbd_dirptr_get_entry(ctx
,
2201 smbd_dirptr_lanman2_match_fn
,
2202 smbd_dirptr_lanman2_mode_fn
,
2212 *got_exact_match
= state
.got_exact_match
;
2214 ok
= smbd_marshall_dir_entry(ctx
,
2219 state
.check_mangled_names
,
2220 requires_resume_key
,
2233 TALLOC_FREE(smb_fname
);
2234 if (*out_of_space
) {
2235 dptr_SeekDir(dirptr
, prev_dirpos
);
2242 *_last_entry_off
= last_entry_off
;
2246 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2247 connection_struct
*conn
,
2248 struct dptr_struct
*dirptr
,
2250 const char *path_mask
,
2253 bool requires_resume_key
,
2259 int space_remaining
,
2261 bool *got_exact_match
,
2262 int *last_entry_off
,
2263 struct ea_list
*name_list
)
2266 const bool do_pad
= true;
2268 if (info_level
>= 1 && info_level
<= 3) {
2269 /* No alignment on earlier info levels. */
2273 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2274 path_mask
, dirtype
, info_level
,
2275 requires_resume_key
, dont_descend
, ask_sharemode
,
2277 ppdata
, base_data
, end_data
,
2279 out_of_space
, got_exact_match
,
2280 last_entry_off
, name_list
);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDFIRST.
2285 ****************************************************************************/
2287 static void call_trans2findfirst(connection_struct
*conn
,
2288 struct smb_request
*req
,
2289 char **pparams
, int total_params
,
2290 char **ppdata
, int total_data
,
2291 unsigned int max_data_bytes
)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2298 struct smb_filename
*smb_dname
= NULL
;
2299 char *params
= *pparams
;
2300 char *pdata
= *ppdata
;
2304 uint16 findfirst_flags
;
2305 bool close_after_first
;
2307 bool requires_resume_key
;
2309 char *directory
= NULL
;
2312 int last_entry_off
=0;
2316 bool finished
= False
;
2317 bool dont_descend
= False
;
2318 bool out_of_space
= False
;
2319 int space_remaining
;
2320 bool mask_contains_wcard
= False
;
2321 struct ea_list
*ea_list
= NULL
;
2322 NTSTATUS ntstatus
= NT_STATUS_OK
;
2323 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX
*ctx
= talloc_tos();
2325 struct dptr_struct
*dirptr
= NULL
;
2326 struct smbd_server_connection
*sconn
= req
->sconn
;
2327 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2328 bool backup_priv
= false;
2330 if (total_params
< 13) {
2331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2335 dirtype
= SVAL(params
,0);
2336 maxentries
= SVAL(params
,2);
2337 findfirst_flags
= SVAL(params
,4);
2338 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2339 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2340 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2341 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2342 security_token_has_privilege(get_current_nttok(conn
),
2345 info_level
= SVAL(params
,6);
2347 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2348 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2349 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2351 info_level
, max_data_bytes
));
2354 /* W2K3 seems to treat zero as 1. */
2358 switch (info_level
) {
2359 case SMB_FIND_INFO_STANDARD
:
2360 case SMB_FIND_EA_SIZE
:
2361 case SMB_FIND_EA_LIST
:
2362 case SMB_FIND_FILE_DIRECTORY_INFO
:
2363 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2364 case SMB_FIND_FILE_NAMES_INFO
:
2365 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2366 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2367 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2369 case SMB_FIND_FILE_UNIX
:
2370 case SMB_FIND_FILE_UNIX_INFO2
:
2371 /* Always use filesystem for UNIX mtime query. */
2372 ask_sharemode
= false;
2373 if (!lp_unix_extensions()) {
2374 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2377 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2380 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2384 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2385 params
+12, total_params
- 12,
2386 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2387 if (!NT_STATUS_IS_OK(ntstatus
)) {
2388 reply_nterror(req
, ntstatus
);
2394 ntstatus
= filename_convert_with_privilege(ctx
,
2399 &mask_contains_wcard
,
2402 ntstatus
= filename_convert(ctx
, conn
,
2403 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2406 &mask_contains_wcard
,
2410 if (!NT_STATUS_IS_OK(ntstatus
)) {
2411 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2412 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2413 ERRSRV
, ERRbadpath
);
2416 reply_nterror(req
, ntstatus
);
2420 mask
= smb_dname
->original_lcomp
;
2422 directory
= smb_dname
->base_name
;
2424 p
= strrchr_m(directory
,'/');
2426 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2427 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2428 mask
= talloc_strdup(ctx
,"*");
2430 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2433 mask_contains_wcard
= True
;
2439 if (p
== NULL
|| p
== directory
) {
2440 /* Ensure we don't have a directory name of "". */
2441 directory
= talloc_strdup(talloc_tos(), ".");
2443 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2448 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2450 if (info_level
== SMB_FIND_EA_LIST
) {
2453 if (total_data
< 4) {
2454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2458 ea_size
= IVAL(pdata
,0);
2459 if (ea_size
!= total_data
) {
2460 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2461 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2462 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2466 if (!lp_ea_support(SNUM(conn
))) {
2467 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2471 /* Pull out the list of names. */
2472 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2474 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2479 *ppdata
= (char *)SMB_REALLOC(
2480 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2481 if(*ppdata
== NULL
) {
2482 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2486 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2488 /* Realloc the params space */
2489 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2490 if (*pparams
== NULL
) {
2491 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2496 /* Save the wildcard match and attribs we are using on this directory -
2497 needed as lanman2 assumes these are being saved between calls */
2499 ntstatus
= dptr_create(conn
,
2507 mask_contains_wcard
,
2511 if (!NT_STATUS_IS_OK(ntstatus
)) {
2512 reply_nterror(req
, ntstatus
);
2517 /* Remember this in case we have
2518 to do a findnext. */
2519 dptr_set_priv(dirptr
);
2522 dptr_num
= dptr_dnum(dirptr
);
2523 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2525 /* Initialize per TRANS2_FIND_FIRST operation data */
2526 dptr_init_search_op(dirptr
);
2528 /* We don't need to check for VOL here as this is returned by
2529 a different TRANS2 call. */
2531 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2532 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2533 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2534 dont_descend
= True
;
2537 space_remaining
= max_data_bytes
;
2538 out_of_space
= False
;
2540 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2541 bool got_exact_match
= False
;
2543 /* this is a heuristic to avoid seeking the dirptr except when
2544 absolutely necessary. It allows for a filename of about 40 chars */
2545 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2546 out_of_space
= True
;
2549 finished
= !get_lanman2_dir_entry(ctx
,
2553 mask
,dirtype
,info_level
,
2554 requires_resume_key
,dont_descend
,
2557 space_remaining
, &out_of_space
,
2559 &last_entry_off
, ea_list
);
2562 if (finished
&& out_of_space
)
2565 if (!finished
&& !out_of_space
)
2569 * As an optimisation if we know we aren't looking
2570 * for a wildcard name (ie. the name matches the wildcard exactly)
2571 * then we can finish on any (first) match.
2572 * This speeds up large directory searches. JRA.
2578 /* Ensure space_remaining never goes -ve. */
2579 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2580 space_remaining
= 0;
2581 out_of_space
= true;
2583 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2587 /* Check if we can close the dirptr */
2588 if(close_after_first
|| (finished
&& close_if_end
)) {
2589 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2590 dptr_close(sconn
, &dptr_num
);
2594 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2595 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2596 * the protocol level is less than NT1. Tested with smbclient. JRA.
2597 * This should fix the OS/2 client bug #2335.
2600 if(numentries
== 0) {
2601 dptr_close(sconn
, &dptr_num
);
2602 if (get_Protocol() < PROTOCOL_NT1
) {
2603 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2606 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2607 ERRDOS
, ERRbadfile
);
2612 /* At this point pdata points to numentries directory entries. */
2614 /* Set up the return parameter block */
2615 SSVAL(params
,0,dptr_num
);
2616 SSVAL(params
,2,numentries
);
2617 SSVAL(params
,4,finished
);
2618 SSVAL(params
,6,0); /* Never an EA error */
2619 SSVAL(params
,8,last_entry_off
);
2621 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2624 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2625 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2627 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2631 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2632 smb_fn_name(req
->cmd
),
2633 mask
, directory
, dirtype
, numentries
) );
2636 * Force a name mangle here to ensure that the
2637 * mask as an 8.3 name is top of the mangled cache.
2638 * The reasons for this are subtle. Don't remove
2639 * this code unless you know what you are doing
2640 * (see PR#13758). JRA.
2643 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2644 char mangled_name
[13];
2645 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2653 TALLOC_FREE(smb_dname
);
2657 /****************************************************************************
2658 Reply to a TRANS2_FINDNEXT.
2659 ****************************************************************************/
2661 static void call_trans2findnext(connection_struct
*conn
,
2662 struct smb_request
*req
,
2663 char **pparams
, int total_params
,
2664 char **ppdata
, int total_data
,
2665 unsigned int max_data_bytes
)
2667 /* We must be careful here that we don't return more than the
2668 allowed number of data bytes. If this means returning fewer than
2669 maxentries then so be it. We assume that the redirector has
2670 enough room for the fixed number of parameter bytes it has
2672 char *params
= *pparams
;
2673 char *pdata
= *ppdata
;
2679 uint16 findnext_flags
;
2680 bool close_after_request
;
2682 bool requires_resume_key
;
2684 bool mask_contains_wcard
= False
;
2685 char *resume_name
= NULL
;
2686 const char *mask
= NULL
;
2687 const char *directory
= NULL
;
2691 int i
, last_entry_off
=0;
2692 bool finished
= False
;
2693 bool dont_descend
= False
;
2694 bool out_of_space
= False
;
2695 int space_remaining
;
2696 struct ea_list
*ea_list
= NULL
;
2697 NTSTATUS ntstatus
= NT_STATUS_OK
;
2698 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2699 TALLOC_CTX
*ctx
= talloc_tos();
2700 struct dptr_struct
*dirptr
;
2701 struct smbd_server_connection
*sconn
= req
->sconn
;
2702 bool backup_priv
= false;
2704 if (total_params
< 13) {
2705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2709 dptr_num
= SVAL(params
,0);
2710 maxentries
= SVAL(params
,2);
2711 info_level
= SVAL(params
,4);
2712 resume_key
= IVAL(params
,6);
2713 findnext_flags
= SVAL(params
,10);
2714 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2715 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2716 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2717 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2719 if (!continue_bit
) {
2720 /* We only need resume_name if continue_bit is zero. */
2721 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2723 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2724 &mask_contains_wcard
);
2725 if (!NT_STATUS_IS_OK(ntstatus
)) {
2726 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2727 complain (it thinks we're asking for the directory above the shared
2728 path or an invalid name). Catch this as the resume name is only compared, never used in
2729 a file access. JRA. */
2730 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2731 &resume_name
, params
+12,
2735 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2736 reply_nterror(req
, ntstatus
);
2742 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2743 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2744 resume_key = %d resume name = %s continue=%d level = %d\n",
2745 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2746 requires_resume_key
, resume_key
,
2747 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2750 /* W2K3 seems to treat zero as 1. */
2754 switch (info_level
) {
2755 case SMB_FIND_INFO_STANDARD
:
2756 case SMB_FIND_EA_SIZE
:
2757 case SMB_FIND_EA_LIST
:
2758 case SMB_FIND_FILE_DIRECTORY_INFO
:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2760 case SMB_FIND_FILE_NAMES_INFO
:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2765 case SMB_FIND_FILE_UNIX
:
2766 case SMB_FIND_FILE_UNIX_INFO2
:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode
= false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2775 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2779 if (info_level
== SMB_FIND_EA_LIST
) {
2782 if (total_data
< 4) {
2783 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2787 ea_size
= IVAL(pdata
,0);
2788 if (ea_size
!= total_data
) {
2789 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2790 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2791 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2795 if (!lp_ea_support(SNUM(conn
))) {
2796 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2800 /* Pull out the list of names. */
2801 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2803 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2808 *ppdata
= (char *)SMB_REALLOC(
2809 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2810 if(*ppdata
== NULL
) {
2811 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2816 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2818 /* Realloc the params space */
2819 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2820 if(*pparams
== NULL
) {
2821 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2827 /* Check that the dptr is valid */
2828 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2829 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2833 directory
= dptr_path(sconn
, dptr_num
);
2835 /* Get the wildcard mask from the dptr */
2836 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2837 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2838 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2842 /* Get the attr mask from the dptr */
2843 dirtype
= dptr_attr(sconn
, dptr_num
);
2845 backup_priv
= dptr_get_priv(dirptr
);
2847 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2848 "backup_priv = %d\n",
2849 dptr_num
, mask
, dirtype
,
2851 dptr_TellDir(dirptr
),
2854 /* Initialize per TRANS2_FIND_NEXT operation data */
2855 dptr_init_search_op(dirptr
);
2857 /* We don't need to check for VOL here as this is returned by
2858 a different TRANS2 call. */
2860 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2861 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2862 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2863 dont_descend
= True
;
2866 space_remaining
= max_data_bytes
;
2867 out_of_space
= False
;
2874 * Seek to the correct position. We no longer use the resume key but
2875 * depend on the last file name instead.
2878 if(!continue_bit
&& resume_name
&& *resume_name
) {
2881 long current_pos
= 0;
2883 * Remember, name_to_8_3 is called by
2884 * get_lanman2_dir_entry(), so the resume name
2885 * could be mangled. Ensure we check the unmangled name.
2888 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2889 char *new_resume_name
= NULL
;
2890 mangle_lookup_name_from_8_3(ctx
,
2894 if (new_resume_name
) {
2895 resume_name
= new_resume_name
;
2900 * Fix for NT redirector problem triggered by resume key indexes
2901 * changing between directory scans. We now return a resume key of 0
2902 * and instead look for the filename to continue from (also given
2903 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2904 * findfirst/findnext (as is usual) then the directory pointer
2905 * should already be at the correct place.
2908 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2909 } /* end if resume_name && !continue_bit */
2911 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2912 bool got_exact_match
= False
;
2914 /* this is a heuristic to avoid seeking the dirptr except when
2915 absolutely necessary. It allows for a filename of about 40 chars */
2916 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2917 out_of_space
= True
;
2920 finished
= !get_lanman2_dir_entry(ctx
,
2924 mask
,dirtype
,info_level
,
2925 requires_resume_key
,dont_descend
,
2928 space_remaining
, &out_of_space
,
2930 &last_entry_off
, ea_list
);
2933 if (finished
&& out_of_space
)
2936 if (!finished
&& !out_of_space
)
2940 * As an optimisation if we know we aren't looking
2941 * for a wildcard name (ie. the name matches the wildcard exactly)
2942 * then we can finish on any (first) match.
2943 * This speeds up large directory searches. JRA.
2949 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2952 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2953 smb_fn_name(req
->cmd
),
2954 mask
, directory
, dirtype
, numentries
) );
2956 /* Check if we can close the dirptr */
2957 if(close_after_request
|| (finished
&& close_if_end
)) {
2958 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2959 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2966 /* Set up the return parameter block */
2967 SSVAL(params
,0,numentries
);
2968 SSVAL(params
,2,finished
);
2969 SSVAL(params
,4,0); /* Never an EA error */
2970 SSVAL(params
,6,last_entry_off
);
2972 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2978 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2980 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2984 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2986 SMB_ASSERT(extended_info
!= NULL
);
2988 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2989 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2990 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2991 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2992 #ifdef SAMBA_VERSION_REVISION
2993 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2995 extended_info
->samba_subversion
= 0;
2996 #ifdef SAMBA_VERSION_RC_RELEASE
2997 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2999 #ifdef SAMBA_VERSION_PRE_RELEASE
3000 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3003 #ifdef SAMBA_VERSION_VENDOR_PATCH
3004 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3006 extended_info
->samba_gitcommitdate
= 0;
3007 #ifdef SAMBA_VERSION_COMMIT_TIME
3008 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3011 memset(extended_info
->samba_version_string
, 0,
3012 sizeof(extended_info
->samba_version_string
));
3014 snprintf (extended_info
->samba_version_string
,
3015 sizeof(extended_info
->samba_version_string
),
3016 "%s", samba_version_string());
3019 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3020 TALLOC_CTX
*mem_ctx
,
3021 uint16_t info_level
,
3023 unsigned int max_data_bytes
,
3024 struct smb_filename
*fname
,
3028 char *pdata
, *end_data
;
3029 int data_len
= 0, len
;
3030 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3031 int snum
= SNUM(conn
);
3032 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3033 char *filename
= NULL
;
3034 uint32 additional_flags
= 0;
3035 struct smb_filename smb_fname
;
3038 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3041 filename
= fname
->base_name
;
3045 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3046 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3047 "info level (0x%x) on IPC$.\n",
3048 (unsigned int)info_level
));
3049 return NT_STATUS_ACCESS_DENIED
;
3053 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3055 ZERO_STRUCT(smb_fname
);
3056 smb_fname
.base_name
= discard_const_p(char, filename
);
3058 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3059 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3060 return map_nt_error_from_unix(errno
);
3065 *ppdata
= (char *)SMB_REALLOC(
3066 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3067 if (*ppdata
== NULL
) {
3068 return NT_STATUS_NO_MEMORY
;
3072 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3073 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3075 switch (info_level
) {
3076 case SMB_INFO_ALLOCATION
:
3078 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3080 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3081 return map_nt_error_from_unix(errno
);
3084 block_size
= lp_block_size(snum
);
3085 if (bsize
< block_size
) {
3086 uint64_t factor
= block_size
/bsize
;
3091 if (bsize
> block_size
) {
3092 uint64_t factor
= bsize
/block_size
;
3097 bytes_per_sector
= 512;
3098 sectors_per_unit
= bsize
/bytes_per_sector
;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3102 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3104 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3105 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3106 SIVAL(pdata
,l1_cUnit
,dsize
);
3107 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3108 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3112 case SMB_INFO_VOLUME
:
3113 /* Return volume name */
3115 * Add volume serial number - hash of a combination of
3116 * the called hostname and the service name.
3118 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3120 * Win2k3 and previous mess this up by sending a name length
3121 * one byte short. I believe only older clients (OS/2 Win9x) use
3122 * this call so try fixing this by adding a terminating null to
3123 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3127 pdata
+l2_vol_szVolLabel
, vname
,
3128 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3129 STR_NOALIGN
|STR_TERMINATE
);
3130 SCVAL(pdata
,l2_vol_cch
,len
);
3131 data_len
= l2_vol_szVolLabel
+ len
;
3132 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3133 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3137 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3138 case SMB_FS_ATTRIBUTE_INFORMATION
:
3140 additional_flags
= 0;
3141 #if defined(HAVE_SYS_QUOTAS)
3142 additional_flags
|= FILE_VOLUME_QUOTAS
;
3145 if(lp_nt_acl_support(SNUM(conn
))) {
3146 additional_flags
|= FILE_PERSISTENT_ACLS
;
3149 /* Capabilities are filled in at connection time through STATVFS call */
3150 additional_flags
|= conn
->fs_capabilities
;
3151 additional_flags
|= lp_parm_int(conn
->params
->service
,
3152 "share", "fake_fscaps",
3155 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3156 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3157 additional_flags
); /* FS ATTRIBUTES */
3159 SIVAL(pdata
,4,255); /* Max filename component length */
3160 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3161 and will think we can't do long filenames */
3162 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3163 PTR_DIFF(end_data
, pdata
+12),
3166 data_len
= 12 + len
;
3169 case SMB_QUERY_FS_LABEL_INFO
:
3170 case SMB_FS_LABEL_INFORMATION
:
3171 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3172 PTR_DIFF(end_data
, pdata
+4), 0);
3177 case SMB_QUERY_FS_VOLUME_INFO
:
3178 case SMB_FS_VOLUME_INFORMATION
:
3181 * Add volume serial number - hash of a combination of
3182 * the called hostname and the service name.
3184 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3185 (str_checksum(get_local_machine_name())<<16));
3187 /* Max label len is 32 characters. */
3188 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3189 PTR_DIFF(end_data
, pdata
+18),
3191 SIVAL(pdata
,12,len
);
3194 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3195 (int)strlen(vname
),vname
,
3196 lp_servicename(talloc_tos(), snum
)));
3199 case SMB_QUERY_FS_SIZE_INFO
:
3200 case SMB_FS_SIZE_INFORMATION
:
3202 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3204 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3205 return map_nt_error_from_unix(errno
);
3207 block_size
= lp_block_size(snum
);
3208 if (bsize
< block_size
) {
3209 uint64_t factor
= block_size
/bsize
;
3214 if (bsize
> block_size
) {
3215 uint64_t factor
= bsize
/block_size
;
3220 bytes_per_sector
= 512;
3221 sectors_per_unit
= bsize
/bytes_per_sector
;
3222 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3224 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3225 SBIG_UINT(pdata
,0,dsize
);
3226 SBIG_UINT(pdata
,8,dfree
);
3227 SIVAL(pdata
,16,sectors_per_unit
);
3228 SIVAL(pdata
,20,bytes_per_sector
);
3232 case SMB_FS_FULL_SIZE_INFORMATION
:
3234 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3236 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3237 return map_nt_error_from_unix(errno
);
3239 block_size
= lp_block_size(snum
);
3240 if (bsize
< block_size
) {
3241 uint64_t factor
= block_size
/bsize
;
3246 if (bsize
> block_size
) {
3247 uint64_t factor
= bsize
/block_size
;
3252 bytes_per_sector
= 512;
3253 sectors_per_unit
= bsize
/bytes_per_sector
;
3254 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3255 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3256 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3257 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3258 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3259 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3260 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3261 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3265 case SMB_QUERY_FS_DEVICE_INFO
:
3266 case SMB_FS_DEVICE_INFORMATION
:
3268 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3270 if (!CAN_WRITE(conn
)) {
3271 characteristics
|= FILE_READ_ONLY_DEVICE
;
3274 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3275 SIVAL(pdata
,4,characteristics
);
3279 #ifdef HAVE_SYS_QUOTAS
3280 case SMB_FS_QUOTA_INFORMATION
:
3282 * what we have to send --metze:
3284 * Unknown1: 24 NULL bytes
3285 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3286 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3287 * Quota Flags: 2 byte :
3288 * Unknown3: 6 NULL bytes
3292 * details for Quota Flags:
3294 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3295 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3296 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3297 * 0x0001 Enable Quotas: enable quota for this fs
3301 /* we need to fake up a fsp here,
3302 * because its not send in this call
3305 SMB_NTQUOTA_STRUCT quotas
;
3308 ZERO_STRUCT(quotas
);
3311 fsp
.fnum
= FNUM_FIELD_INVALID
;
3314 if (get_current_uid(conn
) != 0) {
3315 DEBUG(0,("set_user_quota: access_denied "
3316 "service [%s] user [%s]\n",
3317 lp_servicename(talloc_tos(), SNUM(conn
)),
3318 conn
->session_info
->unix_info
->unix_name
));
3319 return NT_STATUS_ACCESS_DENIED
;
3322 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3323 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3324 return map_nt_error_from_unix(errno
);
3329 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3330 lp_servicename(talloc_tos(), SNUM(conn
))));
3332 /* Unknown1 24 NULL bytes*/
3333 SBIG_UINT(pdata
,0,(uint64_t)0);
3334 SBIG_UINT(pdata
,8,(uint64_t)0);
3335 SBIG_UINT(pdata
,16,(uint64_t)0);
3337 /* Default Soft Quota 8 bytes */
3338 SBIG_UINT(pdata
,24,quotas
.softlim
);
3340 /* Default Hard Quota 8 bytes */
3341 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3343 /* Quota flag 2 bytes */
3344 SSVAL(pdata
,40,quotas
.qflags
);
3346 /* Unknown3 6 NULL bytes */
3352 #endif /* HAVE_SYS_QUOTAS */
3353 case SMB_FS_OBJECTID_INFORMATION
:
3355 unsigned char objid
[16];
3356 struct smb_extended_info extended_info
;
3357 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3358 samba_extended_info_version (&extended_info
);
3359 SIVAL(pdata
,16,extended_info
.samba_magic
);
3360 SIVAL(pdata
,20,extended_info
.samba_version
);
3361 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3362 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3363 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3369 * Query the version and capabilities of the CIFS UNIX extensions
3373 case SMB_QUERY_CIFS_UNIX_INFO
:
3375 bool large_write
= lp_min_receive_file_size() &&
3376 !srv_is_signing_active(conn
->sconn
);
3377 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3378 int encrypt_caps
= 0;
3380 if (!lp_unix_extensions()) {
3381 return NT_STATUS_INVALID_LEVEL
;
3384 switch (conn
->encrypt_level
) {
3385 case SMB_SIGNING_OFF
:
3388 case SMB_SIGNING_IF_REQUIRED
:
3389 case SMB_SIGNING_DEFAULT
:
3390 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3392 case SMB_SIGNING_REQUIRED
:
3393 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3394 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3395 large_write
= false;
3401 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3402 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3404 /* We have POSIX ACLs, pathname, encryption,
3405 * large read/write, and locking capability. */
3407 SBIG_UINT(pdata
,4,((uint64_t)(
3408 CIFS_UNIX_POSIX_ACLS_CAP
|
3409 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3410 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3411 CIFS_UNIX_EXTATTR_CAP
|
3412 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3414 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3416 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3420 case SMB_QUERY_POSIX_FS_INFO
:
3423 vfs_statvfs_struct svfs
;
3425 if (!lp_unix_extensions()) {
3426 return NT_STATUS_INVALID_LEVEL
;
3429 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3433 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3434 SIVAL(pdata
,4,svfs
.BlockSize
);
3435 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3436 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3437 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3438 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3439 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3440 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3441 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3443 } else if (rc
== EOPNOTSUPP
) {
3444 return NT_STATUS_INVALID_LEVEL
;
3445 #endif /* EOPNOTSUPP */
3447 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3448 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3453 case SMB_QUERY_POSIX_WHOAMI
:
3459 if (!lp_unix_extensions()) {
3460 return NT_STATUS_INVALID_LEVEL
;
3463 if (max_data_bytes
< 40) {
3464 return NT_STATUS_BUFFER_TOO_SMALL
;
3467 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3468 flags
|= SMB_WHOAMI_GUEST
;
3471 /* NOTE: 8 bytes for UID/GID, irrespective of native
3472 * platform size. This matches
3473 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3475 data_len
= 4 /* flags */
3482 + 4 /* pad/reserved */
3483 + (conn
->session_info
->unix_token
->ngroups
* 8)
3485 + (conn
->session_info
->security_token
->num_sids
*
3489 SIVAL(pdata
, 0, flags
);
3490 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3492 (uint64_t)conn
->session_info
->unix_token
->uid
);
3493 SBIG_UINT(pdata
, 16,
3494 (uint64_t)conn
->session_info
->unix_token
->gid
);
3497 if (data_len
>= max_data_bytes
) {
3498 /* Potential overflow, skip the GIDs and SIDs. */
3500 SIVAL(pdata
, 24, 0); /* num_groups */
3501 SIVAL(pdata
, 28, 0); /* num_sids */
3502 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3503 SIVAL(pdata
, 36, 0); /* reserved */
3509 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3510 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3512 /* We walk the SID list twice, but this call is fairly
3513 * infrequent, and I don't expect that it's performance
3514 * sensitive -- jpeach
3516 for (i
= 0, sid_bytes
= 0;
3517 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3518 sid_bytes
+= ndr_size_dom_sid(
3519 &conn
->session_info
->security_token
->sids
[i
],
3523 /* SID list byte count */
3524 SIVAL(pdata
, 32, sid_bytes
);
3526 /* 4 bytes pad/reserved - must be zero */
3527 SIVAL(pdata
, 36, 0);
3531 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3532 SBIG_UINT(pdata
, data_len
,
3533 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3539 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3540 int sid_len
= ndr_size_dom_sid(
3541 &conn
->session_info
->security_token
->sids
[i
],
3544 sid_linearize(pdata
+ data_len
, sid_len
,
3545 &conn
->session_info
->security_token
->sids
[i
]);
3546 data_len
+= sid_len
;
3552 case SMB_MAC_QUERY_FS_INFO
:
3554 * Thursby MAC extension... ONLY on NTFS filesystems
3555 * once we do streams then we don't need this
3557 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3559 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3564 return NT_STATUS_INVALID_LEVEL
;
3567 *ret_data_len
= data_len
;
3568 return NT_STATUS_OK
;
3571 /****************************************************************************
3572 Reply to a TRANS2_QFSINFO (query filesystem info).
3573 ****************************************************************************/
3575 static void call_trans2qfsinfo(connection_struct
*conn
,
3576 struct smb_request
*req
,
3577 char **pparams
, int total_params
,
3578 char **ppdata
, int total_data
,
3579 unsigned int max_data_bytes
)
3581 char *params
= *pparams
;
3582 uint16_t info_level
;
3586 if (total_params
< 2) {
3587 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3591 info_level
= SVAL(params
,0);
3593 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3594 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3595 DEBUG(0,("call_trans2qfsinfo: encryption required "
3596 "and info level 0x%x sent.\n",
3597 (unsigned int)info_level
));
3598 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3603 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3605 status
= smbd_do_qfsinfo(conn
, req
,
3611 if (!NT_STATUS_IS_OK(status
)) {
3612 reply_nterror(req
, status
);
3616 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3619 DEBUG( 4, ( "%s info_level = %d\n",
3620 smb_fn_name(req
->cmd
), info_level
) );
3625 /****************************************************************************
3626 Reply to a TRANS2_SETFSINFO (set filesystem info).
3627 ****************************************************************************/
3629 static void call_trans2setfsinfo(connection_struct
*conn
,
3630 struct smb_request
*req
,
3631 char **pparams
, int total_params
,
3632 char **ppdata
, int total_data
,
3633 unsigned int max_data_bytes
)
3635 struct smbd_server_connection
*sconn
= req
->sconn
;
3636 char *pdata
= *ppdata
;
3637 char *params
= *pparams
;
3640 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3641 lp_servicename(talloc_tos(), SNUM(conn
))));
3644 if (total_params
< 4) {
3645 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3647 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3651 info_level
= SVAL(params
,2);
3654 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3655 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3656 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3657 "info level (0x%x) on IPC$.\n",
3658 (unsigned int)info_level
));
3659 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3664 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3665 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3666 DEBUG(0,("call_trans2setfsinfo: encryption required "
3667 "and info level 0x%x sent.\n",
3668 (unsigned int)info_level
));
3669 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3674 switch(info_level
) {
3675 case SMB_SET_CIFS_UNIX_INFO
:
3676 if (!lp_unix_extensions()) {
3677 DEBUG(2,("call_trans2setfsinfo: "
3678 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3679 "unix extensions off\n"));
3681 NT_STATUS_INVALID_LEVEL
);
3685 /* There should be 12 bytes of capabilities set. */
3686 if (total_data
< 12) {
3689 NT_STATUS_INVALID_PARAMETER
);
3692 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3693 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3694 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3695 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3696 /* Just print these values for now. */
3697 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3698 "major = %u, minor = %u cap_low = 0x%x, "
3700 (unsigned int)sconn
->
3701 smb1
.unix_info
.client_major
,
3702 (unsigned int)sconn
->
3703 smb1
.unix_info
.client_minor
,
3704 (unsigned int)sconn
->
3705 smb1
.unix_info
.client_cap_low
,
3706 (unsigned int)sconn
->
3707 smb1
.unix_info
.client_cap_high
));
3709 /* Here is where we must switch to posix pathname processing... */
3710 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3711 lp_set_posix_pathnames();
3712 mangle_change_to_posix();
3715 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3716 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3717 /* Client that knows how to do posix locks,
3718 * but not posix open/mkdir operations. Set a
3719 * default type for read/write checks. */
3721 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3726 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3729 size_t param_len
= 0;
3730 size_t data_len
= total_data
;
3732 if (!lp_unix_extensions()) {
3735 NT_STATUS_INVALID_LEVEL
);
3739 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3742 NT_STATUS_NOT_SUPPORTED
);
3746 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3747 DEBUG( 2,("call_trans2setfsinfo: "
3748 "request transport encryption disabled"
3749 "with 'fork echo handler = yes'\n"));
3752 NT_STATUS_NOT_SUPPORTED
);
3756 DEBUG( 4,("call_trans2setfsinfo: "
3757 "request transport encryption.\n"));
3759 status
= srv_request_encryption_setup(conn
,
3760 (unsigned char **)ppdata
,
3762 (unsigned char **)pparams
,
3765 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3766 !NT_STATUS_IS_OK(status
)) {
3767 reply_nterror(req
, status
);
3771 send_trans2_replies(conn
, req
,
3778 if (NT_STATUS_IS_OK(status
)) {
3779 /* Server-side transport
3780 * encryption is now *on*. */
3781 status
= srv_encryption_start(conn
);
3782 if (!NT_STATUS_IS_OK(status
)) {
3783 char *reason
= talloc_asprintf(talloc_tos(),
3784 "Failure in setting "
3785 "up encrypted transport: %s",
3787 exit_server_cleanly(reason
);
3793 case SMB_FS_QUOTA_INFORMATION
:
3795 files_struct
*fsp
= NULL
;
3796 SMB_NTQUOTA_STRUCT quotas
;
3798 ZERO_STRUCT(quotas
);
3801 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3802 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3803 lp_servicename(talloc_tos(), SNUM(conn
)),
3804 conn
->session_info
->unix_info
->unix_name
));
3805 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3809 /* note: normaly there're 48 bytes,
3810 * but we didn't use the last 6 bytes for now
3813 fsp
= file_fsp(req
, SVAL(params
,0));
3815 if (!check_fsp_ntquota_handle(conn
, req
,
3817 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3819 req
, NT_STATUS_INVALID_HANDLE
);
3823 if (total_data
< 42) {
3824 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3828 NT_STATUS_INVALID_PARAMETER
);
3832 /* unknown_1 24 NULL bytes in pdata*/
3834 /* the soft quotas 8 bytes (uint64_t)*/
3835 quotas
.softlim
= BVAL(pdata
,24);
3837 /* the hard quotas 8 bytes (uint64_t)*/
3838 quotas
.hardlim
= BVAL(pdata
,32);
3840 /* quota_flags 2 bytes **/
3841 quotas
.qflags
= SVAL(pdata
,40);
3843 /* unknown_2 6 NULL bytes follow*/
3845 /* now set the quotas */
3846 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3847 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3848 reply_nterror(req
, map_nt_error_from_unix(errno
));
3855 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3857 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3863 * sending this reply works fine,
3864 * but I'm not sure it's the same
3865 * like windows do...
3868 reply_outbuf(req
, 10, 0);
3871 #if defined(HAVE_POSIX_ACLS)
3872 /****************************************************************************
3873 Utility function to count the number of entries in a POSIX acl.
3874 ****************************************************************************/
3876 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3878 unsigned int ace_count
= 0;
3879 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3880 SMB_ACL_ENTRY_T entry
;
3882 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3884 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3885 entry_id
= SMB_ACL_NEXT_ENTRY
;
3892 /****************************************************************************
3893 Utility function to marshall a POSIX acl into wire format.
3894 ****************************************************************************/
3896 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3898 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3899 SMB_ACL_ENTRY_T entry
;
3901 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3902 SMB_ACL_TAG_T tagtype
;
3903 SMB_ACL_PERMSET_T permset
;
3904 unsigned char perms
= 0;
3905 unsigned int own_grp
;
3908 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3909 entry_id
= SMB_ACL_NEXT_ENTRY
;
3912 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3917 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3922 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3923 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3924 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3926 SCVAL(pdata
,1,perms
);
3929 case SMB_ACL_USER_OBJ
:
3930 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3931 own_grp
= (unsigned int)pst
->st_ex_uid
;
3932 SIVAL(pdata
,2,own_grp
);
3937 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3939 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3942 own_grp
= (unsigned int)*puid
;
3943 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3944 SIVAL(pdata
,2,own_grp
);
3948 case SMB_ACL_GROUP_OBJ
:
3949 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3950 own_grp
= (unsigned int)pst
->st_ex_gid
;
3951 SIVAL(pdata
,2,own_grp
);
3956 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3961 own_grp
= (unsigned int)*pgid
;
3962 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3963 SIVAL(pdata
,2,own_grp
);
3968 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3969 SIVAL(pdata
,2,0xFFFFFFFF);
3970 SIVAL(pdata
,6,0xFFFFFFFF);
3973 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3974 SIVAL(pdata
,2,0xFFFFFFFF);
3975 SIVAL(pdata
,6,0xFFFFFFFF);
3978 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3981 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3988 /****************************************************************************
3989 Store the FILE_UNIX_BASIC info.
3990 ****************************************************************************/
3992 static char *store_file_unix_basic(connection_struct
*conn
,
3995 const SMB_STRUCT_STAT
*psbuf
)
3997 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4000 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4001 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4003 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4006 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4009 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4014 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4018 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4022 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4025 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4026 devno
= psbuf
->st_ex_rdev
;
4028 devno
= psbuf
->st_ex_dev
;
4031 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4035 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4039 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4042 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4046 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4053 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4054 * the chflags(2) (or equivalent) flags.
4056 * XXX: this really should be behind the VFS interface. To do this, we would
4057 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4058 * Each VFS module could then implement its own mapping as appropriate for the
4059 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4061 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4065 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4069 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4073 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4077 { UF_HIDDEN
, EXT_HIDDEN
},
4080 /* Do not remove. We need to guarantee that this array has at least one
4081 * entry to build on HP-UX.
4087 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4088 uint32
*smb_fflags
, uint32
*smb_fmask
)
4092 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4093 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4094 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4095 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4100 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4101 const uint32 smb_fflags
,
4102 const uint32 smb_fmask
,
4105 uint32 max_fmask
= 0;
4108 *stat_fflags
= psbuf
->st_ex_flags
;
4110 /* For each flags requested in smb_fmask, check the state of the
4111 * corresponding flag in smb_fflags and set or clear the matching
4115 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4116 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4117 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4118 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4119 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4121 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4126 /* If smb_fmask is asking to set any bits that are not supported by
4127 * our flag mappings, we should fail.
4129 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4137 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4138 * of file flags and birth (create) time.
4140 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4143 const SMB_STRUCT_STAT
*psbuf
)
4145 uint32 file_flags
= 0;
4146 uint32 flags_mask
= 0;
4148 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4150 /* Create (birth) time 64 bit */
4151 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4154 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4155 SIVAL(pdata
, 0, file_flags
); /* flags */
4156 SIVAL(pdata
, 4, flags_mask
); /* mask */
4162 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4163 const struct stream_struct
*streams
,
4165 unsigned int max_data_bytes
,
4166 unsigned int *data_size
)
4169 unsigned int ofs
= 0;
4171 for (i
= 0; i
< num_streams
; i
++) {
4172 unsigned int next_offset
;
4174 smb_ucs2_t
*namebuf
;
4176 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4177 streams
[i
].name
, &namelen
) ||
4180 return NT_STATUS_INVALID_PARAMETER
;
4184 * name_buf is now null-terminated, we need to marshall as not
4191 * We cannot overflow ...
4193 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4194 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4196 TALLOC_FREE(namebuf
);
4197 return STATUS_BUFFER_OVERFLOW
;
4200 SIVAL(data
, ofs
+4, namelen
);
4201 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4202 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4203 memcpy(data
+ofs
+24, namebuf
, namelen
);
4204 TALLOC_FREE(namebuf
);
4206 next_offset
= ofs
+ 24 + namelen
;
4208 if (i
== num_streams
-1) {
4209 SIVAL(data
, ofs
, 0);
4212 unsigned int align
= ndr_align_size(next_offset
, 8);
4214 if ((next_offset
+ align
) > max_data_bytes
) {
4215 DEBUG(10, ("refusing to overflow align "
4216 "reply at stream %u\n",
4218 TALLOC_FREE(namebuf
);
4219 return STATUS_BUFFER_OVERFLOW
;
4222 memset(data
+next_offset
, 0, align
);
4223 next_offset
+= align
;
4225 SIVAL(data
, ofs
, next_offset
- ofs
);
4232 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4236 return NT_STATUS_OK
;
4239 /****************************************************************************
4240 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4241 ****************************************************************************/
4243 static void call_trans2qpipeinfo(connection_struct
*conn
,
4244 struct smb_request
*req
,
4245 unsigned int tran_call
,
4246 char **pparams
, int total_params
,
4247 char **ppdata
, int total_data
,
4248 unsigned int max_data_bytes
)
4250 char *params
= *pparams
;
4251 char *pdata
= *ppdata
;
4252 unsigned int data_size
= 0;
4253 unsigned int param_size
= 2;
4258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4262 if (total_params
< 4) {
4263 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4267 fsp
= file_fsp(req
, SVAL(params
,0));
4268 if (!fsp_is_np(fsp
)) {
4269 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4273 info_level
= SVAL(params
,2);
4275 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4276 if (*pparams
== NULL
) {
4277 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4282 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4283 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4284 if (*ppdata
== NULL
) {
4285 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4290 switch (info_level
) {
4291 case SMB_FILE_STANDARD_INFORMATION
:
4293 SOFF_T(pdata
,0,4096LL);
4300 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4304 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4310 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4311 TALLOC_CTX
*mem_ctx
,
4312 uint16_t info_level
,
4314 struct smb_filename
*smb_fname
,
4315 bool delete_pending
,
4316 struct timespec write_time_ts
,
4317 struct ea_list
*ea_list
,
4318 int lock_data_count
,
4321 unsigned int max_data_bytes
,
4323 unsigned int *pdata_size
)
4325 char *pdata
= *ppdata
;
4326 char *dstart
, *dend
;
4327 unsigned int data_size
;
4328 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4329 time_t create_time
, mtime
, atime
, c_time
;
4330 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4337 uint64_t file_size
= 0;
4339 uint64_t allocation_size
= 0;
4340 uint64_t file_index
= 0;
4341 uint32_t access_mask
= 0;
4343 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4344 return NT_STATUS_INVALID_LEVEL
;
4347 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4348 smb_fname_str_dbg(smb_fname
),
4350 info_level
, max_data_bytes
));
4352 mode
= dos_mode(conn
, smb_fname
);
4353 nlink
= psbuf
->st_ex_nlink
;
4355 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4359 if ((nlink
> 0) && delete_pending
) {
4363 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4364 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4365 if (*ppdata
== NULL
) {
4366 return NT_STATUS_NO_MEMORY
;
4370 dend
= dstart
+ data_size
- 1;
4372 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4373 update_stat_ex_mtime(psbuf
, write_time_ts
);
4376 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4377 mtime_ts
= psbuf
->st_ex_mtime
;
4378 atime_ts
= psbuf
->st_ex_atime
;
4379 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4381 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4382 dos_filetime_timespec(&create_time_ts
);
4383 dos_filetime_timespec(&mtime_ts
);
4384 dos_filetime_timespec(&atime_ts
);
4385 dos_filetime_timespec(&ctime_ts
);
4388 create_time
= convert_timespec_to_time_t(create_time_ts
);
4389 mtime
= convert_timespec_to_time_t(mtime_ts
);
4390 atime
= convert_timespec_to_time_t(atime_ts
);
4391 c_time
= convert_timespec_to_time_t(ctime_ts
);
4393 p
= strrchr_m(smb_fname
->base_name
,'/');
4395 base_name
= smb_fname
->base_name
;
4399 /* NT expects the name to be in an exact form of the *full*
4400 filename. See the trans2 torture test */
4401 if (ISDOT(base_name
)) {
4402 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4404 return NT_STATUS_NO_MEMORY
;
4407 dos_fname
= talloc_asprintf(mem_ctx
,
4409 smb_fname
->base_name
);
4411 return NT_STATUS_NO_MEMORY
;
4413 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4414 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4415 smb_fname
->stream_name
);
4417 return NT_STATUS_NO_MEMORY
;
4421 string_replace(dos_fname
, '/', '\\');
4424 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4427 /* Do we have this path open ? */
4429 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4430 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4431 if (fsp1
&& fsp1
->initial_allocation_size
) {
4432 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4436 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4437 file_size
= get_file_size_stat(psbuf
);
4441 pos
= fsp
->fh
->position_information
;
4445 access_mask
= fsp
->access_mask
;
4447 /* GENERIC_EXECUTE mapping from Windows */
4448 access_mask
= 0x12019F;
4451 /* This should be an index number - looks like
4454 I think this causes us to fail the IFSKIT
4455 BasicFileInformationTest. -tpot */
4456 file_index
= get_FileIndex(conn
, psbuf
);
4458 switch (info_level
) {
4459 case SMB_INFO_STANDARD
:
4460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4462 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4463 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4464 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4465 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4466 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4467 SSVAL(pdata
,l1_attrFile
,mode
);
4470 case SMB_INFO_QUERY_EA_SIZE
:
4472 unsigned int ea_size
=
4473 estimate_ea_size(conn
, fsp
,
4475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4477 srv_put_dos_date2(pdata
,0,create_time
);
4478 srv_put_dos_date2(pdata
,4,atime
);
4479 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4480 SIVAL(pdata
,12,(uint32
)file_size
);
4481 SIVAL(pdata
,16,(uint32
)allocation_size
);
4482 SSVAL(pdata
,20,mode
);
4483 SIVAL(pdata
,22,ea_size
);
4487 case SMB_INFO_IS_NAME_VALID
:
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4490 /* os/2 needs this ? really ?*/
4491 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4493 /* This is only reached for qpathinfo */
4497 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4499 size_t total_ea_len
= 0;
4500 struct ea_list
*ea_file_list
= NULL
;
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4504 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4506 &total_ea_len
, &ea_file_list
);
4507 if (!NT_STATUS_IS_OK(status
)) {
4511 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4513 if (!ea_list
|| (total_ea_len
> data_size
)) {
4515 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4519 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4523 case SMB_INFO_QUERY_ALL_EAS
:
4525 /* We have data_size bytes to put EA's into. */
4526 size_t total_ea_len
= 0;
4527 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4529 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4531 &total_ea_len
, &ea_list
);
4532 if (!NT_STATUS_IS_OK(status
)) {
4536 if (!ea_list
|| (total_ea_len
> data_size
)) {
4538 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4542 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4546 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4548 /* This is FileFullEaInformation - 0xF which maps to
4549 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4551 /* We have data_size bytes to put EA's into. */
4552 size_t total_ea_len
= 0;
4553 struct ea_list
*ea_file_list
= NULL
;
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4557 /*TODO: add filtering and index handling */
4560 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4562 &total_ea_len
, &ea_file_list
);
4563 if (!NT_STATUS_IS_OK(status
)) {
4566 if (!ea_file_list
) {
4567 return NT_STATUS_NO_EAS_ON_FILE
;
4570 status
= fill_ea_chained_buffer(mem_ctx
,
4574 conn
, ea_file_list
);
4575 if (!NT_STATUS_IS_OK(status
)) {
4581 case SMB_FILE_BASIC_INFORMATION
:
4582 case SMB_QUERY_FILE_BASIC_INFO
:
4584 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4586 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4592 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4593 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4594 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4595 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4596 SIVAL(pdata
,32,mode
);
4598 DEBUG(5,("SMB_QFBI - "));
4599 DEBUG(5,("create: %s ", ctime(&create_time
)));
4600 DEBUG(5,("access: %s ", ctime(&atime
)));
4601 DEBUG(5,("write: %s ", ctime(&mtime
)));
4602 DEBUG(5,("change: %s ", ctime(&c_time
)));
4603 DEBUG(5,("mode: %x\n", mode
));
4606 case SMB_FILE_STANDARD_INFORMATION
:
4607 case SMB_QUERY_FILE_STANDARD_INFO
:
4609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4611 SOFF_T(pdata
,0,allocation_size
);
4612 SOFF_T(pdata
,8,file_size
);
4613 SIVAL(pdata
,16,nlink
);
4614 SCVAL(pdata
,20,delete_pending
?1:0);
4615 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4616 SSVAL(pdata
,22,0); /* Padding. */
4619 case SMB_FILE_EA_INFORMATION
:
4620 case SMB_QUERY_FILE_EA_INFO
:
4622 unsigned int ea_size
=
4623 estimate_ea_size(conn
, fsp
, smb_fname
);
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4626 SIVAL(pdata
,0,ea_size
);
4630 /* Get the 8.3 name - used if NT SMB was negotiated. */
4631 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4632 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4635 char mangled_name
[13];
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4637 if (!name_to_8_3(base_name
,mangled_name
,
4638 True
,conn
->params
)) {
4639 return NT_STATUS_NO_MEMORY
;
4641 len
= srvstr_push(dstart
, flags2
,
4642 pdata
+4, mangled_name
,
4643 PTR_DIFF(dend
, pdata
+4),
4645 data_size
= 4 + len
;
4650 case SMB_QUERY_FILE_NAME_INFO
:
4654 this must be *exactly* right for ACLs on mapped drives to work
4656 len
= srvstr_push(dstart
, flags2
,
4658 PTR_DIFF(dend
, pdata
+4),
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4661 data_size
= 4 + len
;
4666 case SMB_FILE_ALLOCATION_INFORMATION
:
4667 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4668 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4670 SOFF_T(pdata
,0,allocation_size
);
4673 case SMB_FILE_END_OF_FILE_INFORMATION
:
4674 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4677 SOFF_T(pdata
,0,file_size
);
4680 case SMB_QUERY_FILE_ALL_INFO
:
4681 case SMB_FILE_ALL_INFORMATION
:
4684 unsigned int ea_size
=
4685 estimate_ea_size(conn
, fsp
, smb_fname
);
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4687 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4688 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4689 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4690 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4691 SIVAL(pdata
,32,mode
);
4692 SIVAL(pdata
,36,0); /* padding. */
4694 SOFF_T(pdata
,0,allocation_size
);
4695 SOFF_T(pdata
,8,file_size
);
4696 SIVAL(pdata
,16,nlink
);
4697 SCVAL(pdata
,20,delete_pending
);
4698 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4701 SIVAL(pdata
,0,ea_size
);
4702 pdata
+= 4; /* EA info */
4703 len
= srvstr_push(dstart
, flags2
,
4705 PTR_DIFF(dend
, pdata
+4),
4709 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4713 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4716 unsigned int ea_size
=
4717 estimate_ea_size(conn
, fsp
, smb_fname
);
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4719 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4720 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4721 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4722 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4723 SIVAL(pdata
, 0x20, mode
);
4724 SIVAL(pdata
, 0x24, 0); /* padding. */
4725 SBVAL(pdata
, 0x28, allocation_size
);
4726 SBVAL(pdata
, 0x30, file_size
);
4727 SIVAL(pdata
, 0x38, nlink
);
4728 SCVAL(pdata
, 0x3C, delete_pending
);
4729 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4730 SSVAL(pdata
, 0x3E, 0); /* padding */
4731 SBVAL(pdata
, 0x40, file_index
);
4732 SIVAL(pdata
, 0x48, ea_size
);
4733 SIVAL(pdata
, 0x4C, access_mask
);
4734 SBVAL(pdata
, 0x50, pos
);
4735 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4736 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4740 len
= srvstr_push(dstart
, flags2
,
4742 PTR_DIFF(dend
, pdata
+4),
4746 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4749 case SMB_FILE_INTERNAL_INFORMATION
:
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4752 SBVAL(pdata
, 0, file_index
);
4756 case SMB_FILE_ACCESS_INFORMATION
:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4758 SIVAL(pdata
, 0, access_mask
);
4762 case SMB_FILE_NAME_INFORMATION
:
4763 /* Pathname with leading '\'. */
4766 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4767 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4768 SIVAL(pdata
,0,byte_len
);
4769 data_size
= 4 + byte_len
;
4773 case SMB_FILE_DISPOSITION_INFORMATION
:
4774 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4776 SCVAL(pdata
,0,delete_pending
);
4779 case SMB_FILE_POSITION_INFORMATION
:
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4782 SOFF_T(pdata
,0,pos
);
4785 case SMB_FILE_MODE_INFORMATION
:
4786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4787 SIVAL(pdata
,0,mode
);
4791 case SMB_FILE_ALIGNMENT_INFORMATION
:
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4793 SIVAL(pdata
,0,0); /* No alignment needed. */
4798 * NT4 server just returns "invalid query" to this - if we try
4799 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4802 /* The first statement above is false - verified using Thursby
4803 * client against NT4 -- gcolley.
4805 case SMB_QUERY_FILE_STREAM_INFO
:
4806 case SMB_FILE_STREAM_INFORMATION
: {
4807 unsigned int num_streams
= 0;
4808 struct stream_struct
*streams
= NULL
;
4810 DEBUG(10,("smbd_do_qfilepathinfo: "
4811 "SMB_FILE_STREAM_INFORMATION\n"));
4813 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4814 return NT_STATUS_INVALID_PARAMETER
;
4817 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4818 talloc_tos(), &num_streams
, &streams
);
4820 if (!NT_STATUS_IS_OK(status
)) {
4821 DEBUG(10, ("could not get stream info: %s\n",
4822 nt_errstr(status
)));
4826 status
= marshall_stream_info(num_streams
, streams
,
4827 pdata
, max_data_bytes
,
4830 if (!NT_STATUS_IS_OK(status
)) {
4831 DEBUG(10, ("marshall_stream_info failed: %s\n",
4832 nt_errstr(status
)));
4833 TALLOC_FREE(streams
);
4837 TALLOC_FREE(streams
);
4841 case SMB_QUERY_COMPRESSION_INFO
:
4842 case SMB_FILE_COMPRESSION_INFORMATION
:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4844 SOFF_T(pdata
,0,file_size
);
4845 SIVAL(pdata
,8,0); /* ??? */
4846 SIVAL(pdata
,12,0); /* ??? */
4850 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4851 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4852 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4853 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4854 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4855 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4856 SOFF_T(pdata
,32,allocation_size
);
4857 SOFF_T(pdata
,40,file_size
);
4858 SIVAL(pdata
,48,mode
);
4859 SIVAL(pdata
,52,0); /* ??? */
4863 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4865 SIVAL(pdata
,0,mode
);
4871 * CIFS UNIX Extensions.
4874 case SMB_QUERY_FILE_UNIX_BASIC
:
4876 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4877 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4879 DEBUG(4,("smbd_do_qfilepathinfo: "
4880 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4881 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4885 case SMB_QUERY_FILE_UNIX_INFO2
:
4887 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4888 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4892 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4894 for (i
=0; i
<100; i
++)
4895 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4901 case SMB_QUERY_FILE_UNIX_LINK
:
4904 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4907 return NT_STATUS_NO_MEMORY
;
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4912 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4913 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4916 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4918 len
= SMB_VFS_READLINK(conn
,
4919 smb_fname
->base_name
,
4922 return map_nt_error_from_unix(errno
);
4925 len
= srvstr_push(dstart
, flags2
,
4927 PTR_DIFF(dend
, pdata
),
4930 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4935 #if defined(HAVE_POSIX_ACLS)
4936 case SMB_QUERY_POSIX_ACL
:
4938 SMB_ACL_T file_acl
= NULL
;
4939 SMB_ACL_T def_acl
= NULL
;
4940 uint16 num_file_acls
= 0;
4941 uint16 num_def_acls
= 0;
4943 if (fsp
&& fsp
->fh
->fd
!= -1) {
4944 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
4948 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4949 smb_fname
->base_name
,
4950 SMB_ACL_TYPE_ACCESS
,
4954 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4955 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4956 "not implemented on "
4957 "filesystem containing %s\n",
4958 smb_fname
->base_name
));
4959 return NT_STATUS_NOT_IMPLEMENTED
;
4962 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4963 if (fsp
&& fsp
->is_directory
) {
4965 SMB_VFS_SYS_ACL_GET_FILE(
4967 fsp
->fsp_name
->base_name
,
4968 SMB_ACL_TYPE_DEFAULT
,
4972 SMB_VFS_SYS_ACL_GET_FILE(
4974 smb_fname
->base_name
,
4975 SMB_ACL_TYPE_DEFAULT
,
4978 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4981 num_file_acls
= count_acl_entries(conn
, file_acl
);
4982 num_def_acls
= count_acl_entries(conn
, def_acl
);
4984 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4985 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4987 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4988 SMB_POSIX_ACL_HEADER_SIZE
) ));
4990 TALLOC_FREE(file_acl
);
4993 TALLOC_FREE(def_acl
);
4995 return NT_STATUS_BUFFER_TOO_SMALL
;
4998 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4999 SSVAL(pdata
,2,num_file_acls
);
5000 SSVAL(pdata
,4,num_def_acls
);
5001 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5003 TALLOC_FREE(file_acl
);
5006 TALLOC_FREE(def_acl
);
5008 return NT_STATUS_INTERNAL_ERROR
;
5010 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5012 TALLOC_FREE(file_acl
);
5015 TALLOC_FREE(def_acl
);
5017 return NT_STATUS_INTERNAL_ERROR
;
5021 TALLOC_FREE(file_acl
);
5024 TALLOC_FREE(def_acl
);
5026 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5032 case SMB_QUERY_POSIX_LOCK
:
5037 enum brl_type lock_type
;
5039 /* We need an open file with a real fd for this. */
5040 if (!fsp
|| fsp
->fh
->fd
== -1) {
5041 return NT_STATUS_INVALID_LEVEL
;
5044 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5045 return NT_STATUS_INVALID_PARAMETER
;
5048 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5049 case POSIX_LOCK_TYPE_READ
:
5050 lock_type
= READ_LOCK
;
5052 case POSIX_LOCK_TYPE_WRITE
:
5053 lock_type
= WRITE_LOCK
;
5055 case POSIX_LOCK_TYPE_UNLOCK
:
5057 /* There's no point in asking for an unlock... */
5058 return NT_STATUS_INVALID_PARAMETER
;
5061 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5062 #if defined(HAVE_LONGLONG)
5063 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5064 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5065 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5066 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5067 #else /* HAVE_LONGLONG */
5068 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5069 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5070 #endif /* HAVE_LONGLONG */
5072 status
= query_lock(fsp
,
5079 if (ERROR_WAS_LOCK_DENIED(status
)) {
5080 /* Here we need to report who has it locked... */
5081 data_size
= POSIX_LOCK_DATA_SIZE
;
5083 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5084 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5085 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5086 #if defined(HAVE_LONGLONG)
5087 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5088 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5089 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5090 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5091 #else /* HAVE_LONGLONG */
5092 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5093 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5094 #endif /* HAVE_LONGLONG */
5096 } else if (NT_STATUS_IS_OK(status
)) {
5097 /* For success we just return a copy of what we sent
5098 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5099 data_size
= POSIX_LOCK_DATA_SIZE
;
5100 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5101 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5109 return NT_STATUS_INVALID_LEVEL
;
5112 *pdata_size
= data_size
;
5113 return NT_STATUS_OK
;
5116 /****************************************************************************
5117 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5118 file name or file id).
5119 ****************************************************************************/
5121 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5122 struct smb_request
*req
,
5123 unsigned int tran_call
,
5124 char **pparams
, int total_params
,
5125 char **ppdata
, int total_data
,
5126 unsigned int max_data_bytes
)
5128 char *params
= *pparams
;
5129 char *pdata
= *ppdata
;
5131 unsigned int data_size
= 0;
5132 unsigned int param_size
= 2;
5133 struct smb_filename
*smb_fname
= NULL
;
5134 bool delete_pending
= False
;
5135 struct timespec write_time_ts
;
5136 files_struct
*fsp
= NULL
;
5137 struct file_id fileid
;
5138 struct ea_list
*ea_list
= NULL
;
5139 int lock_data_count
= 0;
5140 char *lock_data
= NULL
;
5141 NTSTATUS status
= NT_STATUS_OK
;
5144 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5148 ZERO_STRUCT(write_time_ts
);
5150 if (tran_call
== TRANSACT2_QFILEINFO
) {
5151 if (total_params
< 4) {
5152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5157 call_trans2qpipeinfo(conn
, req
, tran_call
,
5158 pparams
, total_params
,
5164 fsp
= file_fsp(req
, SVAL(params
,0));
5165 info_level
= SVAL(params
,2);
5167 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5169 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5170 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5174 /* Initial check for valid fsp ptr. */
5175 if (!check_fsp_open(conn
, req
, fsp
)) {
5179 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5181 if (!NT_STATUS_IS_OK(status
)) {
5182 reply_nterror(req
, status
);
5186 if(fsp
->fake_file_handle
) {
5188 * This is actually for the QUOTA_FAKE_FILE --metze
5191 /* We know this name is ok, it's already passed the checks. */
5193 } else if(fsp
->fh
->fd
== -1) {
5195 * This is actually a QFILEINFO on a directory
5196 * handle (returned from an NT SMB). NT5.0 seems
5197 * to do this call. JRA.
5200 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5201 /* Always do lstat for UNIX calls. */
5202 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "SMB_VFS_LSTAT of %s failed "
5206 smb_fname_str_dbg(smb_fname
),
5209 map_nt_error_from_unix(errno
));
5212 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5213 DEBUG(3,("call_trans2qfilepathinfo: "
5214 "SMB_VFS_STAT of %s failed (%s)\n",
5215 smb_fname_str_dbg(smb_fname
),
5218 map_nt_error_from_unix(errno
));
5222 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5223 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5226 * Original code - this is an open file.
5228 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5229 DEBUG(3, ("fstat of %s failed (%s)\n",
5230 fsp_fnum_dbg(fsp
), strerror(errno
)));
5232 map_nt_error_from_unix(errno
));
5235 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5236 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5242 uint32_t ucf_flags
= 0;
5245 if (total_params
< 7) {
5246 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5250 info_level
= SVAL(params
,0);
5252 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5254 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5255 if (!lp_unix_extensions()) {
5256 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5259 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5260 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5261 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5262 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5266 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5268 STR_TERMINATE
, &status
);
5269 if (!NT_STATUS_IS_OK(status
)) {
5270 reply_nterror(req
, status
);
5274 status
= filename_convert(req
,
5276 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5281 if (!NT_STATUS_IS_OK(status
)) {
5282 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5283 reply_botherror(req
,
5284 NT_STATUS_PATH_NOT_COVERED
,
5285 ERRSRV
, ERRbadpath
);
5288 reply_nterror(req
, status
);
5292 /* If this is a stream, check if there is a delete_pending. */
5293 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5294 && is_ntfs_stream_smb_fname(smb_fname
)) {
5295 struct smb_filename
*smb_fname_base
= NULL
;
5297 /* Create an smb_filename with stream_name == NULL. */
5299 create_synthetic_smb_fname(talloc_tos(),
5300 smb_fname
->base_name
,
5303 if (!NT_STATUS_IS_OK(status
)) {
5304 reply_nterror(req
, status
);
5308 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5309 /* Always do lstat for UNIX calls. */
5310 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "SMB_VFS_LSTAT of %s failed "
5314 smb_fname_str_dbg(smb_fname_base
),
5316 TALLOC_FREE(smb_fname_base
);
5318 map_nt_error_from_unix(errno
));
5322 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5323 DEBUG(3,("call_trans2qfilepathinfo: "
5324 "fileinfo of %s failed "
5326 smb_fname_str_dbg(smb_fname_base
),
5328 TALLOC_FREE(smb_fname_base
);
5330 map_nt_error_from_unix(errno
));
5335 status
= file_name_hash(conn
,
5336 smb_fname_str_dbg(smb_fname_base
),
5338 if (!NT_STATUS_IS_OK(status
)) {
5339 TALLOC_FREE(smb_fname_base
);
5340 reply_nterror(req
, status
);
5344 fileid
= vfs_file_id_from_sbuf(conn
,
5345 &smb_fname_base
->st
);
5346 TALLOC_FREE(smb_fname_base
);
5347 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5348 if (delete_pending
) {
5349 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5354 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5355 /* Always do lstat for UNIX calls. */
5356 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5357 DEBUG(3,("call_trans2qfilepathinfo: "
5358 "SMB_VFS_LSTAT of %s failed (%s)\n",
5359 smb_fname_str_dbg(smb_fname
),
5362 map_nt_error_from_unix(errno
));
5367 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5368 DEBUG(3,("call_trans2qfilepathinfo: "
5369 "SMB_VFS_STAT of %s failed (%s)\n",
5370 smb_fname_str_dbg(smb_fname
),
5373 map_nt_error_from_unix(errno
));
5378 status
= file_name_hash(conn
,
5379 smb_fname_str_dbg(smb_fname
),
5381 if (!NT_STATUS_IS_OK(status
)) {
5382 reply_nterror(req
, status
);
5386 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5387 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5388 if (delete_pending
) {
5389 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5394 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5395 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5397 info_level
,tran_call
,total_data
));
5399 /* Pull out any data sent here before we realloc. */
5400 switch (info_level
) {
5401 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5403 /* Pull any EA list from the data portion. */
5406 if (total_data
< 4) {
5408 req
, NT_STATUS_INVALID_PARAMETER
);
5411 ea_size
= IVAL(pdata
,0);
5413 if (total_data
> 0 && ea_size
!= total_data
) {
5414 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5415 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5417 req
, NT_STATUS_INVALID_PARAMETER
);
5421 if (!lp_ea_support(SNUM(conn
))) {
5422 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5426 /* Pull out the list of names. */
5427 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5430 req
, NT_STATUS_INVALID_PARAMETER
);
5436 case SMB_QUERY_POSIX_LOCK
:
5438 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5439 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5443 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5445 req
, NT_STATUS_INVALID_PARAMETER
);
5449 /* Copy the lock range data. */
5450 lock_data
= (char *)talloc_memdup(
5451 req
, pdata
, total_data
);
5453 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5456 lock_data_count
= total_data
;
5462 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5463 if (*pparams
== NULL
) {
5464 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5471 * draft-leach-cifs-v1-spec-02.txt
5472 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5475 * The requested information is placed in the Data portion of the
5476 * transaction response. For the information levels greater than 0x100,
5477 * the transaction response has 1 parameter word which should be
5478 * ignored by the client.
5480 * However Windows only follows this rule for the IS_NAME_VALID call.
5482 switch (info_level
) {
5483 case SMB_INFO_IS_NAME_VALID
:
5488 if ((info_level
& 0xFF00) == 0xFF00) {
5490 * We use levels that start with 0xFF00
5491 * internally to represent SMB2 specific levels
5493 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5497 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5499 delete_pending
, write_time_ts
,
5501 lock_data_count
, lock_data
,
5502 req
->flags2
, max_data_bytes
,
5503 ppdata
, &data_size
);
5504 if (!NT_STATUS_IS_OK(status
)) {
5505 reply_nterror(req
, status
);
5509 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5515 /****************************************************************************
5516 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5518 ****************************************************************************/
5520 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5521 connection_struct
*conn
,
5522 struct smb_request
*req
,
5523 bool overwrite_if_exists
,
5524 const struct smb_filename
*smb_fname_old
,
5525 struct smb_filename
*smb_fname_new
)
5527 NTSTATUS status
= NT_STATUS_OK
;
5529 /* source must already exist. */
5530 if (!VALID_STAT(smb_fname_old
->st
)) {
5531 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5534 if (VALID_STAT(smb_fname_new
->st
)) {
5535 if (overwrite_if_exists
) {
5536 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5537 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5539 status
= unlink_internals(conn
,
5541 FILE_ATTRIBUTE_NORMAL
,
5544 if (!NT_STATUS_IS_OK(status
)) {
5548 /* Disallow if newname already exists. */
5549 return NT_STATUS_OBJECT_NAME_COLLISION
;
5553 /* No links from a directory. */
5554 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5555 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5558 /* Setting a hardlink to/from a stream isn't currently supported. */
5559 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5560 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5561 return NT_STATUS_INVALID_PARAMETER
;
5564 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5565 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5567 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5568 smb_fname_new
->base_name
) != 0) {
5569 status
= map_nt_error_from_unix(errno
);
5570 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5571 nt_errstr(status
), smb_fname_old
->base_name
,
5572 smb_fname_new
->base_name
));
5577 /****************************************************************************
5578 Deal with setting the time from any of the setfilepathinfo functions.
5579 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5580 calling this function.
5581 ****************************************************************************/
5583 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5585 const struct smb_filename
*smb_fname
,
5586 struct smb_file_time
*ft
,
5587 bool setting_write_time
)
5589 struct smb_filename smb_fname_base
;
5591 FILE_NOTIFY_CHANGE_LAST_ACCESS
5592 |FILE_NOTIFY_CHANGE_LAST_WRITE
5593 |FILE_NOTIFY_CHANGE_CREATION
;
5595 if (!VALID_STAT(smb_fname
->st
)) {
5596 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5599 /* get some defaults (no modifications) if any info is zero or -1. */
5600 if (null_timespec(ft
->create_time
)) {
5601 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5604 if (null_timespec(ft
->atime
)) {
5605 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5608 if (null_timespec(ft
->mtime
)) {
5609 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5612 if (!setting_write_time
) {
5613 /* ft->mtime comes from change time, not write time. */
5614 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5617 /* Ensure the resolution is the correct for
5618 * what we can store on this filesystem. */
5620 round_timespec(conn
->ts_res
, &ft
->create_time
);
5621 round_timespec(conn
->ts_res
, &ft
->ctime
);
5622 round_timespec(conn
->ts_res
, &ft
->atime
);
5623 round_timespec(conn
->ts_res
, &ft
->mtime
);
5625 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5626 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5627 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5628 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5629 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5630 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5631 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5632 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5634 if (setting_write_time
) {
5636 * This was a Windows setfileinfo on an open file.
5637 * NT does this a lot. We also need to
5638 * set the time here, as it can be read by
5639 * FindFirst/FindNext and with the patch for bug #2045
5640 * in smbd/fileio.c it ensures that this timestamp is
5641 * kept sticky even after a write. We save the request
5642 * away and will set it on file close and after a write. JRA.
5645 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5646 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5649 if (fsp
->base_fsp
) {
5650 set_sticky_write_time_fsp(fsp
->base_fsp
,
5653 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5656 set_sticky_write_time_path(
5657 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5662 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5664 /* Always call ntimes on the base, even if a stream was passed in. */
5665 smb_fname_base
= *smb_fname
;
5666 smb_fname_base
.stream_name
= NULL
;
5668 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5669 return map_nt_error_from_unix(errno
);
5672 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5673 smb_fname
->base_name
);
5674 return NT_STATUS_OK
;
5677 /****************************************************************************
5678 Deal with setting the dosmode from any of the setfilepathinfo functions.
5679 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5680 done before calling this function.
5681 ****************************************************************************/
5683 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5684 const struct smb_filename
*smb_fname
,
5687 struct smb_filename
*smb_fname_base
= NULL
;
5690 if (!VALID_STAT(smb_fname
->st
)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5694 /* Always operate on the base_name, even if a stream was passed in. */
5695 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5696 NULL
, &smb_fname
->st
,
5698 if (!NT_STATUS_IS_OK(status
)) {
5703 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5704 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5706 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5710 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5712 /* check the mode isn't different, before changing it */
5713 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5714 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5715 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5716 (unsigned int)dosmode
));
5718 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5720 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5722 smb_fname_str_dbg(smb_fname_base
),
5724 status
= map_nt_error_from_unix(errno
);
5728 status
= NT_STATUS_OK
;
5730 TALLOC_FREE(smb_fname_base
);
5734 /****************************************************************************
5735 Deal with setting the size from any of the setfilepathinfo functions.
5736 ****************************************************************************/
5738 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5739 struct smb_request
*req
,
5741 const struct smb_filename
*smb_fname
,
5742 const SMB_STRUCT_STAT
*psbuf
,
5744 bool fail_after_createfile
)
5746 NTSTATUS status
= NT_STATUS_OK
;
5747 struct smb_filename
*smb_fname_tmp
= NULL
;
5748 files_struct
*new_fsp
= NULL
;
5750 if (!VALID_STAT(*psbuf
)) {
5751 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5754 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5756 if (size
== get_file_size_stat(psbuf
)) {
5757 return NT_STATUS_OK
;
5760 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5761 smb_fname_str_dbg(smb_fname
), (double)size
));
5763 if (fsp
&& fsp
->fh
->fd
!= -1) {
5764 /* Handle based call. */
5765 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5766 return NT_STATUS_ACCESS_DENIED
;
5769 if (vfs_set_filelen(fsp
, size
) == -1) {
5770 return map_nt_error_from_unix(errno
);
5772 trigger_write_time_update_immediate(fsp
);
5773 return NT_STATUS_OK
;
5776 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5777 if (!NT_STATUS_IS_OK(status
)) {
5781 smb_fname_tmp
->st
= *psbuf
;
5783 status
= SMB_VFS_CREATE_FILE(
5786 0, /* root_dir_fid */
5787 smb_fname_tmp
, /* fname */
5788 FILE_WRITE_DATA
, /* access_mask */
5789 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5791 FILE_OPEN
, /* create_disposition*/
5792 0, /* create_options */
5793 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5794 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5795 0, /* allocation_size */
5796 0, /* private_flags */
5799 &new_fsp
, /* result */
5802 TALLOC_FREE(smb_fname_tmp
);
5804 if (!NT_STATUS_IS_OK(status
)) {
5805 /* NB. We check for open_was_deferred in the caller. */
5809 /* See RAW-SFILEINFO-END-OF-FILE */
5810 if (fail_after_createfile
) {
5811 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5812 return NT_STATUS_INVALID_LEVEL
;
5815 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5816 status
= map_nt_error_from_unix(errno
);
5817 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5821 trigger_write_time_update_immediate(new_fsp
);
5822 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5823 return NT_STATUS_OK
;
5826 /****************************************************************************
5827 Deal with SMB_INFO_SET_EA.
5828 ****************************************************************************/
5830 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5834 const struct smb_filename
*smb_fname
)
5836 struct ea_list
*ea_list
= NULL
;
5837 TALLOC_CTX
*ctx
= NULL
;
5838 NTSTATUS status
= NT_STATUS_OK
;
5840 if (total_data
< 10) {
5842 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5843 length. They seem to have no effect. Bug #3212. JRA */
5845 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5846 /* We're done. We only get EA info in this call. */
5847 return NT_STATUS_OK
;
5850 return NT_STATUS_INVALID_PARAMETER
;
5853 if (IVAL(pdata
,0) > total_data
) {
5854 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5855 IVAL(pdata
,0), (unsigned int)total_data
));
5856 return NT_STATUS_INVALID_PARAMETER
;
5860 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5862 return NT_STATUS_INVALID_PARAMETER
;
5865 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5870 /****************************************************************************
5871 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5872 ****************************************************************************/
5874 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5879 struct ea_list
*ea_list
= NULL
;
5883 return NT_STATUS_INVALID_HANDLE
;
5886 if (!lp_ea_support(SNUM(conn
))) {
5887 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5888 "EA's not supported.\n",
5889 (unsigned int)total_data
));
5890 return NT_STATUS_EAS_NOT_SUPPORTED
;
5893 if (total_data
< 10) {
5894 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5896 (unsigned int)total_data
));
5897 return NT_STATUS_INVALID_PARAMETER
;
5900 ea_list
= read_nttrans_ea_list(talloc_tos(),
5905 return NT_STATUS_INVALID_PARAMETER
;
5908 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5910 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5911 smb_fname_str_dbg(fsp
->fsp_name
),
5912 nt_errstr(status
) ));
5918 /****************************************************************************
5919 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5920 ****************************************************************************/
5922 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5926 struct smb_filename
*smb_fname
)
5928 NTSTATUS status
= NT_STATUS_OK
;
5929 bool delete_on_close
;
5932 if (total_data
< 1) {
5933 return NT_STATUS_INVALID_PARAMETER
;
5937 return NT_STATUS_INVALID_HANDLE
;
5940 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5941 dosmode
= dos_mode(conn
, smb_fname
);
5943 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5944 "delete_on_close = %u\n",
5945 smb_fname_str_dbg(smb_fname
),
5946 (unsigned int)dosmode
,
5947 (unsigned int)delete_on_close
));
5949 if (delete_on_close
) {
5950 status
= can_set_delete_on_close(fsp
, dosmode
);
5951 if (!NT_STATUS_IS_OK(status
)) {
5956 /* The set is across all open files on this dev/inode pair. */
5957 if (!set_delete_on_close(fsp
, delete_on_close
,
5958 conn
->session_info
->security_token
,
5959 conn
->session_info
->unix_token
)) {
5960 return NT_STATUS_ACCESS_DENIED
;
5962 return NT_STATUS_OK
;
5965 /****************************************************************************
5966 Deal with SMB_FILE_POSITION_INFORMATION.
5967 ****************************************************************************/
5969 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5974 uint64_t position_information
;
5976 if (total_data
< 8) {
5977 return NT_STATUS_INVALID_PARAMETER
;
5981 /* Ignore on pathname based set. */
5982 return NT_STATUS_OK
;
5985 position_information
= (uint64_t)IVAL(pdata
,0);
5986 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5988 DEBUG(10,("smb_file_position_information: Set file position "
5989 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5990 (double)position_information
));
5991 fsp
->fh
->position_information
= position_information
;
5992 return NT_STATUS_OK
;
5995 /****************************************************************************
5996 Deal with SMB_FILE_MODE_INFORMATION.
5997 ****************************************************************************/
5999 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6005 if (total_data
< 4) {
6006 return NT_STATUS_INVALID_PARAMETER
;
6008 mode
= IVAL(pdata
,0);
6009 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6010 return NT_STATUS_INVALID_PARAMETER
;
6012 return NT_STATUS_OK
;
6015 /****************************************************************************
6016 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6017 ****************************************************************************/
6019 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6020 struct smb_request
*req
,
6023 const struct smb_filename
*smb_fname
)
6025 char *link_target
= NULL
;
6026 const char *newname
= smb_fname
->base_name
;
6027 TALLOC_CTX
*ctx
= talloc_tos();
6029 /* Set a symbolic link. */
6030 /* Don't allow this if follow links is false. */
6032 if (total_data
== 0) {
6033 return NT_STATUS_INVALID_PARAMETER
;
6036 if (!lp_symlinks(SNUM(conn
))) {
6037 return NT_STATUS_ACCESS_DENIED
;
6040 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6041 total_data
, STR_TERMINATE
);
6044 return NT_STATUS_INVALID_PARAMETER
;
6047 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6048 newname
, link_target
));
6050 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6051 return map_nt_error_from_unix(errno
);
6054 return NT_STATUS_OK
;
6057 /****************************************************************************
6058 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6059 ****************************************************************************/
6061 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6062 struct smb_request
*req
,
6063 const char *pdata
, int total_data
,
6064 struct smb_filename
*smb_fname_new
)
6066 char *oldname
= NULL
;
6067 struct smb_filename
*smb_fname_old
= NULL
;
6068 TALLOC_CTX
*ctx
= talloc_tos();
6069 NTSTATUS status
= NT_STATUS_OK
;
6071 /* Set a hard link. */
6072 if (total_data
== 0) {
6073 return NT_STATUS_INVALID_PARAMETER
;
6076 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6077 total_data
, STR_TERMINATE
, &status
);
6078 if (!NT_STATUS_IS_OK(status
)) {
6082 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6083 smb_fname_str_dbg(smb_fname_new
), oldname
));
6085 status
= filename_convert(ctx
,
6087 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6092 if (!NT_STATUS_IS_OK(status
)) {
6096 return hardlink_internals(ctx
, conn
, req
, false,
6097 smb_fname_old
, smb_fname_new
);
6100 /****************************************************************************
6101 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6102 ****************************************************************************/
6104 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6105 struct smb_request
*req
,
6109 struct smb_filename
*smb_fname_src
)
6113 char *newname
= NULL
;
6114 struct smb_filename
*smb_fname_dst
= NULL
;
6115 NTSTATUS status
= NT_STATUS_OK
;
6116 TALLOC_CTX
*ctx
= talloc_tos();
6119 return NT_STATUS_INVALID_HANDLE
;
6122 if (total_data
< 20) {
6123 return NT_STATUS_INVALID_PARAMETER
;
6126 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6127 len
= IVAL(pdata
,16);
6129 if (len
> (total_data
- 20) || (len
== 0)) {
6130 return NT_STATUS_INVALID_PARAMETER
;
6133 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6134 &pdata
[20], len
, STR_TERMINATE
,
6136 if (!NT_STATUS_IS_OK(status
)) {
6140 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6143 status
= filename_convert(ctx
,
6145 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6150 if (!NT_STATUS_IS_OK(status
)) {
6154 if (fsp
->base_fsp
) {
6155 /* newname must be a stream name. */
6156 if (newname
[0] != ':') {
6157 return NT_STATUS_NOT_SUPPORTED
;
6160 /* Create an smb_fname to call rename_internals_fsp() with. */
6161 status
= create_synthetic_smb_fname(talloc_tos(),
6162 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6164 if (!NT_STATUS_IS_OK(status
)) {
6169 * Set the original last component, since
6170 * rename_internals_fsp() requires it.
6172 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6174 if (smb_fname_dst
->original_lcomp
== NULL
) {
6175 status
= NT_STATUS_NO_MEMORY
;
6181 DEBUG(10,("smb2_file_rename_information: "
6182 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6183 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6184 smb_fname_str_dbg(smb_fname_dst
)));
6185 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6186 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6190 TALLOC_FREE(smb_fname_dst
);
6194 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6195 struct smb_request
*req
,
6199 struct smb_filename
*smb_fname_src
)
6203 char *newname
= NULL
;
6204 struct smb_filename
*smb_fname_dst
= NULL
;
6205 NTSTATUS status
= NT_STATUS_OK
;
6206 TALLOC_CTX
*ctx
= talloc_tos();
6209 return NT_STATUS_INVALID_HANDLE
;
6212 if (total_data
< 20) {
6213 return NT_STATUS_INVALID_PARAMETER
;
6216 overwrite
= (CVAL(pdata
,0) ? true : false);
6217 len
= IVAL(pdata
,16);
6219 if (len
> (total_data
- 20) || (len
== 0)) {
6220 return NT_STATUS_INVALID_PARAMETER
;
6223 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6224 &pdata
[20], len
, STR_TERMINATE
,
6226 if (!NT_STATUS_IS_OK(status
)) {
6230 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6233 status
= filename_convert(ctx
,
6235 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6240 if (!NT_STATUS_IS_OK(status
)) {
6244 if (fsp
->base_fsp
) {
6245 /* No stream names. */
6246 return NT_STATUS_NOT_SUPPORTED
;
6249 DEBUG(10,("smb_file_link_information: "
6250 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6251 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6252 smb_fname_str_dbg(smb_fname_dst
)));
6253 status
= hardlink_internals(ctx
,
6260 TALLOC_FREE(smb_fname_dst
);
6264 /****************************************************************************
6265 Deal with SMB_FILE_RENAME_INFORMATION.
6266 ****************************************************************************/
6268 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6269 struct smb_request
*req
,
6273 struct smb_filename
*smb_fname_src
)
6278 char *newname
= NULL
;
6279 struct smb_filename
*smb_fname_dst
= NULL
;
6280 bool dest_has_wcard
= False
;
6281 NTSTATUS status
= NT_STATUS_OK
;
6283 TALLOC_CTX
*ctx
= talloc_tos();
6285 if (total_data
< 13) {
6286 return NT_STATUS_INVALID_PARAMETER
;
6289 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6290 root_fid
= IVAL(pdata
,4);
6291 len
= IVAL(pdata
,8);
6293 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6294 return NT_STATUS_INVALID_PARAMETER
;
6297 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6300 if (!NT_STATUS_IS_OK(status
)) {
6304 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6307 status
= resolve_dfspath_wcard(ctx
, conn
,
6308 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6311 !conn
->sconn
->using_smb2
,
6314 if (!NT_STATUS_IS_OK(status
)) {
6318 /* Check the new name has no '/' characters. */
6319 if (strchr_m(newname
, '/')) {
6320 return NT_STATUS_NOT_SUPPORTED
;
6323 if (fsp
&& fsp
->base_fsp
) {
6324 /* newname must be a stream name. */
6325 if (newname
[0] != ':') {
6326 return NT_STATUS_NOT_SUPPORTED
;
6329 /* Create an smb_fname to call rename_internals_fsp() with. */
6330 status
= create_synthetic_smb_fname(talloc_tos(),
6331 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6333 if (!NT_STATUS_IS_OK(status
)) {
6338 * Set the original last component, since
6339 * rename_internals_fsp() requires it.
6341 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6343 if (smb_fname_dst
->original_lcomp
== NULL
) {
6344 status
= NT_STATUS_NO_MEMORY
;
6350 * Build up an smb_fname_dst based on the filename passed in.
6351 * We basically just strip off the last component, and put on
6352 * the newname instead.
6354 char *base_name
= NULL
;
6356 /* newname must *not* be a stream name. */
6357 if (newname
[0] == ':') {
6358 return NT_STATUS_NOT_SUPPORTED
;
6362 * Strip off the last component (filename) of the path passed
6365 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6367 return NT_STATUS_NO_MEMORY
;
6369 p
= strrchr_m(base_name
, '/');
6373 base_name
= talloc_strdup(ctx
, "");
6375 return NT_STATUS_NO_MEMORY
;
6378 /* Append the new name. */
6379 base_name
= talloc_asprintf_append(base_name
,
6383 return NT_STATUS_NO_MEMORY
;
6386 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6389 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6392 /* If an error we expect this to be
6393 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6395 if (!NT_STATUS_IS_OK(status
)) {
6396 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6400 /* Create an smb_fname to call rename_internals_fsp() */
6401 status
= create_synthetic_smb_fname(ctx
,
6405 if (!NT_STATUS_IS_OK(status
)) {
6412 DEBUG(10,("smb_file_rename_information: "
6413 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6414 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6415 smb_fname_str_dbg(smb_fname_dst
)));
6416 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6419 DEBUG(10,("smb_file_rename_information: "
6420 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6421 smb_fname_str_dbg(smb_fname_src
),
6422 smb_fname_str_dbg(smb_fname_dst
)));
6423 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6424 smb_fname_dst
, 0, overwrite
, false,
6426 FILE_WRITE_ATTRIBUTES
);
6429 TALLOC_FREE(smb_fname_dst
);
6433 /****************************************************************************
6434 Deal with SMB_SET_POSIX_ACL.
6435 ****************************************************************************/
6437 #if defined(HAVE_POSIX_ACLS)
6438 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6442 const struct smb_filename
*smb_fname
)
6444 uint16 posix_acl_version
;
6445 uint16 num_file_acls
;
6446 uint16 num_def_acls
;
6447 bool valid_file_acls
= True
;
6448 bool valid_def_acls
= True
;
6450 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6451 return NT_STATUS_INVALID_PARAMETER
;
6453 posix_acl_version
= SVAL(pdata
,0);
6454 num_file_acls
= SVAL(pdata
,2);
6455 num_def_acls
= SVAL(pdata
,4);
6457 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6458 valid_file_acls
= False
;
6462 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6463 valid_def_acls
= False
;
6467 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6468 return NT_STATUS_INVALID_PARAMETER
;
6471 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6472 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6473 return NT_STATUS_INVALID_PARAMETER
;
6476 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6477 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6478 (unsigned int)num_file_acls
,
6479 (unsigned int)num_def_acls
));
6481 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6482 smb_fname
->base_name
, num_file_acls
,
6483 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6484 return map_nt_error_from_unix(errno
);
6487 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6488 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6489 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6490 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6491 return map_nt_error_from_unix(errno
);
6493 return NT_STATUS_OK
;
6497 /****************************************************************************
6498 Deal with SMB_SET_POSIX_LOCK.
6499 ****************************************************************************/
6501 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6502 struct smb_request
*req
,
6510 bool blocking_lock
= False
;
6511 enum brl_type lock_type
;
6513 NTSTATUS status
= NT_STATUS_OK
;
6515 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6516 return NT_STATUS_INVALID_HANDLE
;
6519 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6520 return NT_STATUS_INVALID_PARAMETER
;
6523 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6524 case POSIX_LOCK_TYPE_READ
:
6525 lock_type
= READ_LOCK
;
6527 case POSIX_LOCK_TYPE_WRITE
:
6528 /* Return the right POSIX-mappable error code for files opened read-only. */
6529 if (!fsp
->can_write
) {
6530 return NT_STATUS_INVALID_HANDLE
;
6532 lock_type
= WRITE_LOCK
;
6534 case POSIX_LOCK_TYPE_UNLOCK
:
6535 lock_type
= UNLOCK_LOCK
;
6538 return NT_STATUS_INVALID_PARAMETER
;
6541 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6542 blocking_lock
= False
;
6543 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6544 blocking_lock
= True
;
6546 return NT_STATUS_INVALID_PARAMETER
;
6549 if (!lp_blocking_locks(SNUM(conn
))) {
6550 blocking_lock
= False
;
6553 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6554 #if defined(HAVE_LONGLONG)
6555 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6556 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6557 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6558 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6559 #else /* HAVE_LONGLONG */
6560 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6561 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6562 #endif /* HAVE_LONGLONG */
6564 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6565 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6567 (unsigned int)lock_type
,
6568 (unsigned long long)smblctx
,
6572 if (lock_type
== UNLOCK_LOCK
) {
6573 status
= do_unlock(req
->sconn
->msg_ctx
,
6580 uint64_t block_smblctx
;
6582 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6594 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6596 * A blocking lock was requested. Package up
6597 * this smb into a queued request and push it
6598 * onto the blocking lock queue.
6600 if(push_blocking_lock_request(br_lck
,
6603 -1, /* infinite timeout. */
6611 TALLOC_FREE(br_lck
);
6615 TALLOC_FREE(br_lck
);
6621 /****************************************************************************
6622 Deal with SMB_SET_FILE_BASIC_INFO.
6623 ****************************************************************************/
6625 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6629 const struct smb_filename
*smb_fname
)
6631 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6632 struct smb_file_time ft
;
6634 NTSTATUS status
= NT_STATUS_OK
;
6638 if (total_data
< 36) {
6639 return NT_STATUS_INVALID_PARAMETER
;
6642 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6643 if (!NT_STATUS_IS_OK(status
)) {
6647 /* Set the attributes */
6648 dosmode
= IVAL(pdata
,32);
6649 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6650 if (!NT_STATUS_IS_OK(status
)) {
6655 ft
.create_time
= interpret_long_date(pdata
);
6658 ft
.atime
= interpret_long_date(pdata
+8);
6661 ft
.mtime
= interpret_long_date(pdata
+16);
6664 ft
.ctime
= interpret_long_date(pdata
+24);
6666 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6667 smb_fname_str_dbg(smb_fname
)));
6669 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6673 /****************************************************************************
6674 Deal with SMB_INFO_STANDARD.
6675 ****************************************************************************/
6677 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6681 const struct smb_filename
*smb_fname
)
6684 struct smb_file_time ft
;
6688 if (total_data
< 12) {
6689 return NT_STATUS_INVALID_PARAMETER
;
6693 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6695 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6697 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6699 DEBUG(10,("smb_set_info_standard: file %s\n",
6700 smb_fname_str_dbg(smb_fname
)));
6702 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6703 if (!NT_STATUS_IS_OK(status
)) {
6707 return smb_set_file_time(conn
,
6714 /****************************************************************************
6715 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6716 ****************************************************************************/
6718 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6719 struct smb_request
*req
,
6723 struct smb_filename
*smb_fname
)
6725 uint64_t allocation_size
= 0;
6726 NTSTATUS status
= NT_STATUS_OK
;
6727 files_struct
*new_fsp
= NULL
;
6729 if (!VALID_STAT(smb_fname
->st
)) {
6730 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6733 if (total_data
< 8) {
6734 return NT_STATUS_INVALID_PARAMETER
;
6737 allocation_size
= (uint64_t)IVAL(pdata
,0);
6738 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6739 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6740 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6741 (double)allocation_size
));
6743 if (allocation_size
) {
6744 allocation_size
= smb_roundup(conn
, allocation_size
);
6747 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6748 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6749 (double)allocation_size
));
6751 if (fsp
&& fsp
->fh
->fd
!= -1) {
6752 /* Open file handle. */
6753 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6754 return NT_STATUS_ACCESS_DENIED
;
6757 /* Only change if needed. */
6758 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6759 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6760 return map_nt_error_from_unix(errno
);
6763 /* But always update the time. */
6765 * This is equivalent to a write. Ensure it's seen immediately
6766 * if there are no pending writes.
6768 trigger_write_time_update_immediate(fsp
);
6769 return NT_STATUS_OK
;
6772 /* Pathname or stat or directory file. */
6773 status
= SMB_VFS_CREATE_FILE(
6776 0, /* root_dir_fid */
6777 smb_fname
, /* fname */
6778 FILE_WRITE_DATA
, /* access_mask */
6779 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6781 FILE_OPEN
, /* create_disposition*/
6782 0, /* create_options */
6783 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6784 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6785 0, /* allocation_size */
6786 0, /* private_flags */
6789 &new_fsp
, /* result */
6792 if (!NT_STATUS_IS_OK(status
)) {
6793 /* NB. We check for open_was_deferred in the caller. */
6797 /* Only change if needed. */
6798 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6799 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6800 status
= map_nt_error_from_unix(errno
);
6801 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6806 /* Changing the allocation size should set the last mod time. */
6808 * This is equivalent to a write. Ensure it's seen immediately
6809 * if there are no pending writes.
6811 trigger_write_time_update_immediate(new_fsp
);
6813 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6814 return NT_STATUS_OK
;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6819 ****************************************************************************/
6821 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6822 struct smb_request
*req
,
6826 const struct smb_filename
*smb_fname
,
6827 bool fail_after_createfile
)
6831 if (total_data
< 8) {
6832 return NT_STATUS_INVALID_PARAMETER
;
6835 size
= IVAL(pdata
,0);
6836 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6837 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6838 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6841 return smb_set_file_size(conn
, req
,
6846 fail_after_createfile
);
6849 /****************************************************************************
6850 Allow a UNIX info mknod.
6851 ****************************************************************************/
6853 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6856 const struct smb_filename
*smb_fname
)
6858 uint32 file_type
= IVAL(pdata
,56);
6859 #if defined(HAVE_MAKEDEV)
6860 uint32 dev_major
= IVAL(pdata
,60);
6861 uint32 dev_minor
= IVAL(pdata
,68);
6863 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6864 uint32 raw_unixmode
= IVAL(pdata
,84);
6868 if (total_data
< 100) {
6869 return NT_STATUS_INVALID_PARAMETER
;
6872 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6873 PERM_NEW_FILE
, &unixmode
);
6874 if (!NT_STATUS_IS_OK(status
)) {
6878 #if defined(HAVE_MAKEDEV)
6879 dev
= makedev(dev_major
, dev_minor
);
6882 switch (file_type
) {
6883 #if defined(S_IFIFO)
6884 case UNIX_TYPE_FIFO
:
6885 unixmode
|= S_IFIFO
;
6888 #if defined(S_IFSOCK)
6889 case UNIX_TYPE_SOCKET
:
6890 unixmode
|= S_IFSOCK
;
6893 #if defined(S_IFCHR)
6894 case UNIX_TYPE_CHARDEV
:
6895 unixmode
|= S_IFCHR
;
6898 #if defined(S_IFBLK)
6899 case UNIX_TYPE_BLKDEV
:
6900 unixmode
|= S_IFBLK
;
6904 return NT_STATUS_INVALID_PARAMETER
;
6907 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6908 "%.0f mode 0%o for file %s\n", (double)dev
,
6909 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6911 /* Ok - do the mknod. */
6912 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6913 return map_nt_error_from_unix(errno
);
6916 /* If any of the other "set" calls fail we
6917 * don't want to end up with a half-constructed mknod.
6920 if (lp_inherit_perms(SNUM(conn
))) {
6922 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6924 return NT_STATUS_NO_MEMORY
;
6926 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6928 TALLOC_FREE(parent
);
6931 return NT_STATUS_OK
;
6934 /****************************************************************************
6935 Deal with SMB_SET_FILE_UNIX_BASIC.
6936 ****************************************************************************/
6938 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6939 struct smb_request
*req
,
6943 const struct smb_filename
*smb_fname
)
6945 struct smb_file_time ft
;
6946 uint32 raw_unixmode
;
6949 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6950 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6951 NTSTATUS status
= NT_STATUS_OK
;
6952 bool delete_on_fail
= False
;
6953 enum perm_type ptype
;
6954 files_struct
*all_fsps
= NULL
;
6955 bool modify_mtime
= true;
6957 struct smb_filename
*smb_fname_tmp
= NULL
;
6958 SMB_STRUCT_STAT sbuf
;
6962 if (total_data
< 100) {
6963 return NT_STATUS_INVALID_PARAMETER
;
6966 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6967 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6968 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6969 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6972 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6973 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6974 set_owner
= (uid_t
)IVAL(pdata
,40);
6975 set_grp
= (gid_t
)IVAL(pdata
,48);
6976 raw_unixmode
= IVAL(pdata
,84);
6978 if (VALID_STAT(smb_fname
->st
)) {
6979 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6980 ptype
= PERM_EXISTING_DIR
;
6982 ptype
= PERM_EXISTING_FILE
;
6985 ptype
= PERM_NEW_FILE
;
6988 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6990 if (!NT_STATUS_IS_OK(status
)) {
6994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6995 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6996 smb_fname_str_dbg(smb_fname
), (double)size
,
6997 (unsigned int)set_owner
, (unsigned int)set_grp
,
6998 (int)raw_unixmode
));
7000 sbuf
= smb_fname
->st
;
7002 if (!VALID_STAT(sbuf
)) {
7004 * The only valid use of this is to create character and block
7005 * devices, and named pipes. This is deprecated (IMHO) and
7006 * a new info level should be used for mknod. JRA.
7009 status
= smb_unix_mknod(conn
,
7013 if (!NT_STATUS_IS_OK(status
)) {
7017 status
= copy_smb_filename(talloc_tos(), smb_fname
,
7019 if (!NT_STATUS_IS_OK(status
)) {
7023 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7024 status
= map_nt_error_from_unix(errno
);
7025 TALLOC_FREE(smb_fname_tmp
);
7026 SMB_VFS_UNLINK(conn
, smb_fname
);
7030 sbuf
= smb_fname_tmp
->st
;
7031 smb_fname
= smb_fname_tmp
;
7033 /* Ensure we don't try and change anything else. */
7034 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7035 size
= get_file_size_stat(&sbuf
);
7036 ft
.atime
= sbuf
.st_ex_atime
;
7037 ft
.mtime
= sbuf
.st_ex_mtime
;
7039 * We continue here as we might want to change the
7042 delete_on_fail
= True
;
7046 /* Horrible backwards compatibility hack as an old server bug
7047 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7051 size
= get_file_size_stat(&sbuf
);
7056 * Deal with the UNIX specific mode set.
7059 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7060 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7061 "setting mode 0%o for file %s\n",
7062 (unsigned int)unixmode
,
7063 smb_fname_str_dbg(smb_fname
)));
7064 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7065 return map_nt_error_from_unix(errno
);
7070 * Deal with the UNIX specific uid set.
7073 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7074 (sbuf
.st_ex_uid
!= set_owner
)) {
7077 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7078 "changing owner %u for path %s\n",
7079 (unsigned int)set_owner
,
7080 smb_fname_str_dbg(smb_fname
)));
7082 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7083 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7084 set_owner
, (gid_t
)-1);
7086 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7087 set_owner
, (gid_t
)-1);
7091 status
= map_nt_error_from_unix(errno
);
7092 if (delete_on_fail
) {
7093 SMB_VFS_UNLINK(conn
, smb_fname
);
7100 * Deal with the UNIX specific gid set.
7103 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7104 (sbuf
.st_ex_gid
!= set_grp
)) {
7105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7106 "changing group %u for file %s\n",
7107 (unsigned int)set_owner
,
7108 smb_fname_str_dbg(smb_fname
)));
7109 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7111 status
= map_nt_error_from_unix(errno
);
7112 if (delete_on_fail
) {
7113 SMB_VFS_UNLINK(conn
, smb_fname
);
7119 /* Deal with any size changes. */
7121 status
= smb_set_file_size(conn
, req
,
7127 if (!NT_STATUS_IS_OK(status
)) {
7131 /* Deal with any time changes. */
7132 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7133 /* No change, don't cancel anything. */
7137 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7138 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7139 all_fsps
= file_find_di_next(all_fsps
)) {
7141 * We're setting the time explicitly for UNIX.
7142 * Cancel any pending changes over all handles.
7144 all_fsps
->update_write_time_on_close
= false;
7145 TALLOC_FREE(all_fsps
->update_write_time_event
);
7149 * Override the "setting_write_time"
7150 * parameter here as it almost does what
7151 * we need. Just remember if we modified
7152 * mtime and send the notify ourselves.
7154 if (null_timespec(ft
.mtime
)) {
7155 modify_mtime
= false;
7158 status
= smb_set_file_time(conn
,
7164 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7165 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7170 /****************************************************************************
7171 Deal with SMB_SET_FILE_UNIX_INFO2.
7172 ****************************************************************************/
7174 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7175 struct smb_request
*req
,
7179 const struct smb_filename
*smb_fname
)
7185 if (total_data
< 116) {
7186 return NT_STATUS_INVALID_PARAMETER
;
7189 /* Start by setting all the fields that are common between UNIX_BASIC
7192 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7194 if (!NT_STATUS_IS_OK(status
)) {
7198 smb_fflags
= IVAL(pdata
, 108);
7199 smb_fmask
= IVAL(pdata
, 112);
7201 /* NB: We should only attempt to alter the file flags if the client
7202 * sends a non-zero mask.
7204 if (smb_fmask
!= 0) {
7205 int stat_fflags
= 0;
7207 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7208 smb_fmask
, &stat_fflags
)) {
7209 /* Client asked to alter a flag we don't understand. */
7210 return NT_STATUS_INVALID_PARAMETER
;
7213 if (fsp
&& fsp
->fh
->fd
!= -1) {
7214 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7215 return NT_STATUS_NOT_SUPPORTED
;
7217 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7218 stat_fflags
) != 0) {
7219 return map_nt_error_from_unix(errno
);
7224 /* XXX: need to add support for changing the create_time here. You
7225 * can do this for paths on Darwin with setattrlist(2). The right way
7226 * to hook this up is probably by extending the VFS utimes interface.
7229 return NT_STATUS_OK
;
7232 /****************************************************************************
7233 Create a directory with POSIX semantics.
7234 ****************************************************************************/
7236 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7237 struct smb_request
*req
,
7240 struct smb_filename
*smb_fname
,
7241 int *pdata_return_size
)
7243 NTSTATUS status
= NT_STATUS_OK
;
7244 uint32 raw_unixmode
= 0;
7245 uint32 mod_unixmode
= 0;
7246 mode_t unixmode
= (mode_t
)0;
7247 files_struct
*fsp
= NULL
;
7248 uint16 info_level_return
= 0;
7250 char *pdata
= *ppdata
;
7252 if (total_data
< 18) {
7253 return NT_STATUS_INVALID_PARAMETER
;
7256 raw_unixmode
= IVAL(pdata
,8);
7257 /* Next 4 bytes are not yet defined. */
7259 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7260 PERM_NEW_DIR
, &unixmode
);
7261 if (!NT_STATUS_IS_OK(status
)) {
7265 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7267 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7268 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7270 status
= SMB_VFS_CREATE_FILE(
7273 0, /* root_dir_fid */
7274 smb_fname
, /* fname */
7275 FILE_READ_ATTRIBUTES
, /* access_mask */
7276 FILE_SHARE_NONE
, /* share_access */
7277 FILE_CREATE
, /* create_disposition*/
7278 FILE_DIRECTORY_FILE
, /* create_options */
7279 mod_unixmode
, /* file_attributes */
7280 0, /* oplock_request */
7281 0, /* allocation_size */
7282 0, /* private_flags */
7288 if (NT_STATUS_IS_OK(status
)) {
7289 close_file(req
, fsp
, NORMAL_CLOSE
);
7292 info_level_return
= SVAL(pdata
,16);
7294 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7295 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7296 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7297 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7299 *pdata_return_size
= 12;
7302 /* Realloc the data size */
7303 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7304 if (*ppdata
== NULL
) {
7305 *pdata_return_size
= 0;
7306 return NT_STATUS_NO_MEMORY
;
7310 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7311 SSVAL(pdata
,2,0); /* No fnum. */
7312 SIVAL(pdata
,4,info
); /* Was directory created. */
7314 switch (info_level_return
) {
7315 case SMB_QUERY_FILE_UNIX_BASIC
:
7316 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7317 SSVAL(pdata
,10,0); /* Padding. */
7318 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7321 case SMB_QUERY_FILE_UNIX_INFO2
:
7322 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7323 SSVAL(pdata
,10,0); /* Padding. */
7324 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7328 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7329 SSVAL(pdata
,10,0); /* Padding. */
7336 /****************************************************************************
7337 Open/Create a file with POSIX semantics.
7338 ****************************************************************************/
7340 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7341 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7343 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7344 struct smb_request
*req
,
7347 struct smb_filename
*smb_fname
,
7348 int *pdata_return_size
)
7350 bool extended_oplock_granted
= False
;
7351 char *pdata
= *ppdata
;
7353 uint32 wire_open_mode
= 0;
7354 uint32 raw_unixmode
= 0;
7355 uint32 mod_unixmode
= 0;
7356 uint32 create_disp
= 0;
7357 uint32 access_mask
= 0;
7358 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7359 NTSTATUS status
= NT_STATUS_OK
;
7360 mode_t unixmode
= (mode_t
)0;
7361 files_struct
*fsp
= NULL
;
7362 int oplock_request
= 0;
7364 uint16 info_level_return
= 0;
7366 if (total_data
< 18) {
7367 return NT_STATUS_INVALID_PARAMETER
;
7370 flags
= IVAL(pdata
,0);
7371 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7372 if (oplock_request
) {
7373 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7376 wire_open_mode
= IVAL(pdata
,4);
7378 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7379 return smb_posix_mkdir(conn
, req
,
7386 switch (wire_open_mode
& SMB_ACCMODE
) {
7388 access_mask
= SMB_O_RDONLY_MAPPING
;
7391 access_mask
= SMB_O_WRONLY_MAPPING
;
7394 access_mask
= (SMB_O_RDONLY_MAPPING
|
7395 SMB_O_WRONLY_MAPPING
);
7398 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7399 (unsigned int)wire_open_mode
));
7400 return NT_STATUS_INVALID_PARAMETER
;
7403 wire_open_mode
&= ~SMB_ACCMODE
;
7405 /* First take care of O_CREAT|O_EXCL interactions. */
7406 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7407 case (SMB_O_CREAT
| SMB_O_EXCL
):
7408 /* File exists fail. File not exist create. */
7409 create_disp
= FILE_CREATE
;
7412 /* File exists open. File not exist create. */
7413 create_disp
= FILE_OPEN_IF
;
7416 /* O_EXCL on its own without O_CREAT is undefined.
7417 We deliberately ignore it as some versions of
7418 Linux CIFSFS can send a bare O_EXCL on the
7419 wire which other filesystems in the kernel
7420 ignore. See bug 9519 for details. */
7425 /* File exists open. File not exist fail. */
7426 create_disp
= FILE_OPEN
;
7429 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7430 (unsigned int)wire_open_mode
));
7431 return NT_STATUS_INVALID_PARAMETER
;
7434 /* Next factor in the effects of O_TRUNC. */
7435 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7437 if (wire_open_mode
& SMB_O_TRUNC
) {
7438 switch (create_disp
) {
7440 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7441 /* Leave create_disp alone as
7442 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7444 /* File exists fail. File not exist create. */
7447 /* SMB_O_CREAT | SMB_O_TRUNC */
7448 /* File exists overwrite. File not exist create. */
7449 create_disp
= FILE_OVERWRITE_IF
;
7453 /* File exists overwrite. File not exist fail. */
7454 create_disp
= FILE_OVERWRITE
;
7457 /* Cannot get here. */
7458 smb_panic("smb_posix_open: logic error");
7459 return NT_STATUS_INVALID_PARAMETER
;
7463 raw_unixmode
= IVAL(pdata
,8);
7464 /* Next 4 bytes are not yet defined. */
7466 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7467 (VALID_STAT(smb_fname
->st
) ?
7468 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7471 if (!NT_STATUS_IS_OK(status
)) {
7475 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7477 if (wire_open_mode
& SMB_O_SYNC
) {
7478 create_options
|= FILE_WRITE_THROUGH
;
7480 if (wire_open_mode
& SMB_O_APPEND
) {
7481 access_mask
|= FILE_APPEND_DATA
;
7483 if (wire_open_mode
& SMB_O_DIRECT
) {
7484 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7487 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7488 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7489 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7490 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7492 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7493 create_options
|= FILE_DIRECTORY_FILE
;
7496 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7497 smb_fname_str_dbg(smb_fname
),
7498 (unsigned int)wire_open_mode
,
7499 (unsigned int)unixmode
));
7501 status
= SMB_VFS_CREATE_FILE(
7504 0, /* root_dir_fid */
7505 smb_fname
, /* fname */
7506 access_mask
, /* access_mask */
7507 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7509 create_disp
, /* create_disposition*/
7510 create_options
, /* create_options */
7511 mod_unixmode
, /* file_attributes */
7512 oplock_request
, /* oplock_request */
7513 0, /* allocation_size */
7514 0, /* private_flags */
7520 if (!NT_STATUS_IS_OK(status
)) {
7524 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7525 extended_oplock_granted
= True
;
7528 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7529 extended_oplock_granted
= True
;
7532 info_level_return
= SVAL(pdata
,16);
7534 /* Allocate the correct return size. */
7536 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7537 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7538 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7539 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7541 *pdata_return_size
= 12;
7544 /* Realloc the data size */
7545 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7546 if (*ppdata
== NULL
) {
7547 close_file(req
, fsp
, ERROR_CLOSE
);
7548 *pdata_return_size
= 0;
7549 return NT_STATUS_NO_MEMORY
;
7553 if (extended_oplock_granted
) {
7554 if (flags
& REQUEST_BATCH_OPLOCK
) {
7555 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7557 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7559 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7560 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7562 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7565 SSVAL(pdata
,2,fsp
->fnum
);
7566 SIVAL(pdata
,4,info
); /* Was file created etc. */
7568 switch (info_level_return
) {
7569 case SMB_QUERY_FILE_UNIX_BASIC
:
7570 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7571 SSVAL(pdata
,10,0); /* padding. */
7572 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7575 case SMB_QUERY_FILE_UNIX_INFO2
:
7576 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7577 SSVAL(pdata
,10,0); /* padding. */
7578 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7582 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7583 SSVAL(pdata
,10,0); /* padding. */
7586 return NT_STATUS_OK
;
7589 /****************************************************************************
7590 Delete a file with POSIX semantics.
7591 ****************************************************************************/
7593 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7594 struct smb_request
*req
,
7597 struct smb_filename
*smb_fname
)
7599 NTSTATUS status
= NT_STATUS_OK
;
7600 files_struct
*fsp
= NULL
;
7604 int create_options
= 0;
7606 struct share_mode_lock
*lck
= NULL
;
7608 if (total_data
< 2) {
7609 return NT_STATUS_INVALID_PARAMETER
;
7612 flags
= SVAL(pdata
,0);
7614 if (!VALID_STAT(smb_fname
->st
)) {
7615 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7618 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7619 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7620 return NT_STATUS_NOT_A_DIRECTORY
;
7623 DEBUG(10,("smb_posix_unlink: %s %s\n",
7624 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7625 smb_fname_str_dbg(smb_fname
)));
7627 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7628 create_options
|= FILE_DIRECTORY_FILE
;
7631 status
= SMB_VFS_CREATE_FILE(
7634 0, /* root_dir_fid */
7635 smb_fname
, /* fname */
7636 DELETE_ACCESS
, /* access_mask */
7637 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7639 FILE_OPEN
, /* create_disposition*/
7640 create_options
, /* create_options */
7641 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7642 0, /* oplock_request */
7643 0, /* allocation_size */
7644 0, /* private_flags */
7650 if (!NT_STATUS_IS_OK(status
)) {
7655 * Don't lie to client. If we can't really delete due to
7656 * non-POSIX opens return SHARING_VIOLATION.
7659 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7661 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7662 "lock for file %s\n", fsp_str_dbg(fsp
)));
7663 close_file(req
, fsp
, NORMAL_CLOSE
);
7664 return NT_STATUS_INVALID_PARAMETER
;
7668 * See if others still have the file open. If this is the case, then
7669 * don't delete. If all opens are POSIX delete we can set the delete
7670 * on close disposition.
7672 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7673 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7674 if (is_valid_share_mode_entry(e
)) {
7675 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7678 if (share_mode_stale_pid(lck
->data
, i
)) {
7681 /* Fail with sharing violation. */
7683 close_file(req
, fsp
, NORMAL_CLOSE
);
7684 return NT_STATUS_SHARING_VIOLATION
;
7689 * Set the delete on close.
7691 status
= smb_set_file_disposition_info(conn
,
7699 if (!NT_STATUS_IS_OK(status
)) {
7700 close_file(req
, fsp
, NORMAL_CLOSE
);
7703 return close_file(req
, fsp
, NORMAL_CLOSE
);
7706 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7707 struct smb_request
*req
,
7708 TALLOC_CTX
*mem_ctx
,
7709 uint16_t info_level
,
7711 struct smb_filename
*smb_fname
,
7712 char **ppdata
, int total_data
,
7715 char *pdata
= *ppdata
;
7716 NTSTATUS status
= NT_STATUS_OK
;
7717 int data_return_size
= 0;
7721 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7722 return NT_STATUS_INVALID_LEVEL
;
7725 if (!CAN_WRITE(conn
)) {
7726 /* Allow POSIX opens. The open path will deny
7727 * any non-readonly opens. */
7728 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7729 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7733 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7734 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7736 info_level
, total_data
));
7738 switch (info_level
) {
7740 case SMB_INFO_STANDARD
:
7742 status
= smb_set_info_standard(conn
,
7750 case SMB_INFO_SET_EA
:
7752 status
= smb_info_set_ea(conn
,
7760 case SMB_SET_FILE_BASIC_INFO
:
7761 case SMB_FILE_BASIC_INFORMATION
:
7763 status
= smb_set_file_basic_info(conn
,
7771 case SMB_FILE_ALLOCATION_INFORMATION
:
7772 case SMB_SET_FILE_ALLOCATION_INFO
:
7774 status
= smb_set_file_allocation_info(conn
, req
,
7782 case SMB_FILE_END_OF_FILE_INFORMATION
:
7783 case SMB_SET_FILE_END_OF_FILE_INFO
:
7786 * XP/Win7 both fail after the createfile with
7787 * SMB_SET_FILE_END_OF_FILE_INFO but not
7788 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7789 * The level is known here, so pass it down
7793 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7795 status
= smb_set_file_end_of_file_info(conn
, req
,
7804 case SMB_FILE_DISPOSITION_INFORMATION
:
7805 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7808 /* JRA - We used to just ignore this on a path ?
7809 * Shouldn't this be invalid level on a pathname
7812 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7813 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7816 status
= smb_set_file_disposition_info(conn
,
7824 case SMB_FILE_POSITION_INFORMATION
:
7826 status
= smb_file_position_information(conn
,
7833 case SMB_FILE_FULL_EA_INFORMATION
:
7835 status
= smb_set_file_full_ea_info(conn
,
7842 /* From tridge Samba4 :
7843 * MODE_INFORMATION in setfileinfo (I have no
7844 * idea what "mode information" on a file is - it takes a value of 0,
7845 * 2, 4 or 6. What could it be?).
7848 case SMB_FILE_MODE_INFORMATION
:
7850 status
= smb_file_mode_information(conn
,
7857 * CIFS UNIX extensions.
7860 case SMB_SET_FILE_UNIX_BASIC
:
7862 status
= smb_set_file_unix_basic(conn
, req
,
7870 case SMB_SET_FILE_UNIX_INFO2
:
7872 status
= smb_set_file_unix_info2(conn
, req
,
7880 case SMB_SET_FILE_UNIX_LINK
:
7883 /* We must have a pathname for this. */
7884 return NT_STATUS_INVALID_LEVEL
;
7886 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7887 total_data
, smb_fname
);
7891 case SMB_SET_FILE_UNIX_HLINK
:
7894 /* We must have a pathname for this. */
7895 return NT_STATUS_INVALID_LEVEL
;
7897 status
= smb_set_file_unix_hlink(conn
, req
,
7903 case SMB_FILE_RENAME_INFORMATION
:
7905 status
= smb_file_rename_information(conn
, req
,
7911 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7913 /* SMB2 rename information. */
7914 status
= smb2_file_rename_information(conn
, req
,
7920 case SMB_FILE_LINK_INFORMATION
:
7922 status
= smb_file_link_information(conn
, req
,
7928 #if defined(HAVE_POSIX_ACLS)
7929 case SMB_SET_POSIX_ACL
:
7931 status
= smb_set_posix_acl(conn
,
7940 case SMB_SET_POSIX_LOCK
:
7943 return NT_STATUS_INVALID_LEVEL
;
7945 status
= smb_set_posix_lock(conn
, req
,
7946 pdata
, total_data
, fsp
);
7950 case SMB_POSIX_PATH_OPEN
:
7953 /* We must have a pathname for this. */
7954 return NT_STATUS_INVALID_LEVEL
;
7957 status
= smb_posix_open(conn
, req
,
7965 case SMB_POSIX_PATH_UNLINK
:
7968 /* We must have a pathname for this. */
7969 return NT_STATUS_INVALID_LEVEL
;
7972 status
= smb_posix_unlink(conn
, req
,
7980 return NT_STATUS_INVALID_LEVEL
;
7983 if (!NT_STATUS_IS_OK(status
)) {
7987 *ret_data_size
= data_return_size
;
7988 return NT_STATUS_OK
;
7991 /****************************************************************************
7992 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7993 ****************************************************************************/
7995 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7996 struct smb_request
*req
,
7997 unsigned int tran_call
,
7998 char **pparams
, int total_params
,
7999 char **ppdata
, int total_data
,
8000 unsigned int max_data_bytes
)
8002 char *params
= *pparams
;
8003 char *pdata
= *ppdata
;
8005 struct smb_filename
*smb_fname
= NULL
;
8006 files_struct
*fsp
= NULL
;
8007 NTSTATUS status
= NT_STATUS_OK
;
8008 int data_return_size
= 0;
8011 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8015 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8016 if (total_params
< 4) {
8017 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8021 fsp
= file_fsp(req
, SVAL(params
,0));
8022 /* Basic check for non-null fsp. */
8023 if (!check_fsp_open(conn
, req
, fsp
)) {
8026 info_level
= SVAL(params
,2);
8028 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
8030 if (!NT_STATUS_IS_OK(status
)) {
8031 reply_nterror(req
, status
);
8035 if(fsp
->fh
->fd
== -1) {
8037 * This is actually a SETFILEINFO on a directory
8038 * handle (returned from an NT SMB). NT5.0 seems
8039 * to do this call. JRA.
8041 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8042 /* Always do lstat for UNIX calls. */
8043 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8044 DEBUG(3,("call_trans2setfilepathinfo: "
8045 "SMB_VFS_LSTAT of %s failed "
8047 smb_fname_str_dbg(smb_fname
),
8049 reply_nterror(req
, map_nt_error_from_unix(errno
));
8053 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8054 DEBUG(3,("call_trans2setfilepathinfo: "
8055 "fileinfo of %s failed (%s)\n",
8056 smb_fname_str_dbg(smb_fname
),
8058 reply_nterror(req
, map_nt_error_from_unix(errno
));
8062 } else if (fsp
->print_file
) {
8064 * Doing a DELETE_ON_CLOSE should cancel a print job.
8066 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8067 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8069 DEBUG(3,("call_trans2setfilepathinfo: "
8070 "Cancelling print job (%s)\n",
8074 send_trans2_replies(conn
, req
, params
, 2,
8080 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8085 * Original code - this is an open file.
8087 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8088 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8089 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8091 reply_nterror(req
, map_nt_error_from_unix(errno
));
8097 uint32_t ucf_flags
= 0;
8100 if (total_params
< 7) {
8101 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8105 info_level
= SVAL(params
,0);
8106 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8107 total_params
- 6, STR_TERMINATE
,
8109 if (!NT_STATUS_IS_OK(status
)) {
8110 reply_nterror(req
, status
);
8114 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8115 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8116 info_level
== SMB_FILE_RENAME_INFORMATION
||
8117 info_level
== SMB_POSIX_PATH_UNLINK
) {
8118 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8121 status
= filename_convert(req
, conn
,
8122 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8127 if (!NT_STATUS_IS_OK(status
)) {
8128 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8129 reply_botherror(req
,
8130 NT_STATUS_PATH_NOT_COVERED
,
8131 ERRSRV
, ERRbadpath
);
8134 reply_nterror(req
, status
);
8138 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8140 * For CIFS UNIX extensions the target name may not exist.
8143 /* Always do lstat for UNIX calls. */
8144 SMB_VFS_LSTAT(conn
, smb_fname
);
8146 } else if (!VALID_STAT(smb_fname
->st
) &&
8147 SMB_VFS_STAT(conn
, smb_fname
)) {
8148 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8150 smb_fname_str_dbg(smb_fname
),
8152 reply_nterror(req
, map_nt_error_from_unix(errno
));
8157 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8158 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8160 info_level
,total_data
));
8162 /* Realloc the parameter size */
8163 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8164 if (*pparams
== NULL
) {
8165 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8172 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8178 if (!NT_STATUS_IS_OK(status
)) {
8179 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8180 /* We have re-scheduled this call. */
8183 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8184 /* We have re-scheduled this call. */
8187 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8188 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8189 ERRSRV
, ERRbadpath
);
8192 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8193 reply_openerror(req
, status
);
8197 reply_nterror(req
, status
);
8201 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8207 /****************************************************************************
8208 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8209 ****************************************************************************/
8211 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8212 char **pparams
, int total_params
,
8213 char **ppdata
, int total_data
,
8214 unsigned int max_data_bytes
)
8216 struct smb_filename
*smb_dname
= NULL
;
8217 char *params
= *pparams
;
8218 char *pdata
= *ppdata
;
8219 char *directory
= NULL
;
8220 NTSTATUS status
= NT_STATUS_OK
;
8221 struct ea_list
*ea_list
= NULL
;
8222 TALLOC_CTX
*ctx
= talloc_tos();
8224 if (!CAN_WRITE(conn
)) {
8225 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8229 if (total_params
< 5) {
8230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8234 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8235 total_params
- 4, STR_TERMINATE
,
8237 if (!NT_STATUS_IS_OK(status
)) {
8238 reply_nterror(req
, status
);
8242 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8244 status
= filename_convert(ctx
,
8246 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8252 if (!NT_STATUS_IS_OK(status
)) {
8253 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8254 reply_botherror(req
,
8255 NT_STATUS_PATH_NOT_COVERED
,
8256 ERRSRV
, ERRbadpath
);
8259 reply_nterror(req
, status
);
8264 * OS/2 workplace shell seems to send SET_EA requests of "null"
8265 * length (4 bytes containing IVAL 4).
8266 * They seem to have no effect. Bug #3212. JRA.
8269 if (total_data
&& (total_data
!= 4)) {
8270 /* Any data in this call is an EA list. */
8271 if (total_data
< 10) {
8272 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8276 if (IVAL(pdata
,0) > total_data
) {
8277 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8278 IVAL(pdata
,0), (unsigned int)total_data
));
8279 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8283 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8286 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8290 if (!lp_ea_support(SNUM(conn
))) {
8291 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8295 /* If total_data == 4 Windows doesn't care what values
8296 * are placed in that field, it just ignores them.
8297 * The System i QNTC IBM SMB client puts bad values here,
8298 * so ignore them. */
8300 status
= create_directory(conn
, req
, smb_dname
);
8302 if (!NT_STATUS_IS_OK(status
)) {
8303 reply_nterror(req
, status
);
8307 /* Try and set any given EA. */
8309 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8310 if (!NT_STATUS_IS_OK(status
)) {
8311 reply_nterror(req
, status
);
8316 /* Realloc the parameter and data sizes */
8317 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8318 if(*pparams
== NULL
) {
8319 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8326 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8329 TALLOC_FREE(smb_dname
);
8333 /****************************************************************************
8334 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8335 We don't actually do this - we just send a null response.
8336 ****************************************************************************/
8338 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8339 struct smb_request
*req
,
8340 char **pparams
, int total_params
,
8341 char **ppdata
, int total_data
,
8342 unsigned int max_data_bytes
)
8344 char *params
= *pparams
;
8347 if (total_params
< 6) {
8348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8352 info_level
= SVAL(params
,4);
8353 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8355 switch (info_level
) {
8360 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8364 /* Realloc the parameter and data sizes */
8365 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8366 if (*pparams
== NULL
) {
8367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8372 SSVAL(params
,0,fnf_handle
);
8373 SSVAL(params
,2,0); /* No changes */
8374 SSVAL(params
,4,0); /* No EA errors */
8381 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8386 /****************************************************************************
8387 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8388 changes). Currently this does nothing.
8389 ****************************************************************************/
8391 static void call_trans2findnotifynext(connection_struct
*conn
,
8392 struct smb_request
*req
,
8393 char **pparams
, int total_params
,
8394 char **ppdata
, int total_data
,
8395 unsigned int max_data_bytes
)
8397 char *params
= *pparams
;
8399 DEBUG(3,("call_trans2findnotifynext\n"));
8401 /* Realloc the parameter and data sizes */
8402 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8403 if (*pparams
== NULL
) {
8404 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8409 SSVAL(params
,0,0); /* No changes */
8410 SSVAL(params
,2,0); /* No EA errors */
8412 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8417 /****************************************************************************
8418 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8419 ****************************************************************************/
8421 static void call_trans2getdfsreferral(connection_struct
*conn
,
8422 struct smb_request
*req
,
8423 char **pparams
, int total_params
,
8424 char **ppdata
, int total_data
,
8425 unsigned int max_data_bytes
)
8427 char *params
= *pparams
;
8428 char *pathname
= NULL
;
8430 int max_referral_level
;
8431 NTSTATUS status
= NT_STATUS_OK
;
8432 TALLOC_CTX
*ctx
= talloc_tos();
8434 DEBUG(10,("call_trans2getdfsreferral\n"));
8436 if (total_params
< 3) {
8437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8441 max_referral_level
= SVAL(params
,0);
8443 if(!lp_host_msdfs()) {
8444 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8448 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8449 total_params
- 2, STR_TERMINATE
);
8451 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8454 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8455 ppdata
,&status
)) < 0) {
8456 reply_nterror(req
, status
);
8460 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8461 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8462 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8467 #define LMCAT_SPL 0x53
8468 #define LMFUNC_GETJOBID 0x60
8470 /****************************************************************************
8471 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8472 ****************************************************************************/
8474 static void call_trans2ioctl(connection_struct
*conn
,
8475 struct smb_request
*req
,
8476 char **pparams
, int total_params
,
8477 char **ppdata
, int total_data
,
8478 unsigned int max_data_bytes
)
8480 char *pdata
= *ppdata
;
8481 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8483 /* check for an invalid fid before proceeding */
8486 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8490 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8491 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8492 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8493 if (*ppdata
== NULL
) {
8494 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8499 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8500 CAN ACCEPT THIS IN UNICODE. JRA. */
8503 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8505 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8506 lp_netbios_name(), 15,
8507 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8508 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8509 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8510 STR_ASCII
|STR_TERMINATE
); /* Service name */
8511 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8516 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8517 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8520 /****************************************************************************
8521 Reply to a SMBfindclose (stop trans2 directory search).
8522 ****************************************************************************/
8524 void reply_findclose(struct smb_request
*req
)
8527 struct smbd_server_connection
*sconn
= req
->sconn
;
8529 START_PROFILE(SMBfindclose
);
8532 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8533 END_PROFILE(SMBfindclose
);
8537 dptr_num
= SVALS(req
->vwv
+0, 0);
8539 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8541 dptr_close(sconn
, &dptr_num
);
8543 reply_outbuf(req
, 0, 0);
8545 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8547 END_PROFILE(SMBfindclose
);
8551 /****************************************************************************
8552 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8553 ****************************************************************************/
8555 void reply_findnclose(struct smb_request
*req
)
8559 START_PROFILE(SMBfindnclose
);
8562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8563 END_PROFILE(SMBfindnclose
);
8567 dptr_num
= SVAL(req
->vwv
+0, 0);
8569 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8571 /* We never give out valid handles for a
8572 findnotifyfirst - so any dptr_num is ok here.
8575 reply_outbuf(req
, 0, 0);
8577 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8579 END_PROFILE(SMBfindnclose
);
8583 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8584 struct trans_state
*state
)
8586 if (get_Protocol() >= PROTOCOL_NT1
) {
8587 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8588 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8591 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8592 if (state
->call
!= TRANSACT2_QFSINFO
&&
8593 state
->call
!= TRANSACT2_SETFSINFO
) {
8594 DEBUG(0,("handle_trans2: encryption required "
8596 (unsigned int)state
->call
));
8597 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8602 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8604 /* Now we must call the relevant TRANS2 function */
8605 switch(state
->call
) {
8606 case TRANSACT2_OPEN
:
8608 START_PROFILE(Trans2_open
);
8609 call_trans2open(conn
, req
,
8610 &state
->param
, state
->total_param
,
8611 &state
->data
, state
->total_data
,
8612 state
->max_data_return
);
8613 END_PROFILE(Trans2_open
);
8617 case TRANSACT2_FINDFIRST
:
8619 START_PROFILE(Trans2_findfirst
);
8620 call_trans2findfirst(conn
, req
,
8621 &state
->param
, state
->total_param
,
8622 &state
->data
, state
->total_data
,
8623 state
->max_data_return
);
8624 END_PROFILE(Trans2_findfirst
);
8628 case TRANSACT2_FINDNEXT
:
8630 START_PROFILE(Trans2_findnext
);
8631 call_trans2findnext(conn
, req
,
8632 &state
->param
, state
->total_param
,
8633 &state
->data
, state
->total_data
,
8634 state
->max_data_return
);
8635 END_PROFILE(Trans2_findnext
);
8639 case TRANSACT2_QFSINFO
:
8641 START_PROFILE(Trans2_qfsinfo
);
8642 call_trans2qfsinfo(conn
, req
,
8643 &state
->param
, state
->total_param
,
8644 &state
->data
, state
->total_data
,
8645 state
->max_data_return
);
8646 END_PROFILE(Trans2_qfsinfo
);
8650 case TRANSACT2_SETFSINFO
:
8652 START_PROFILE(Trans2_setfsinfo
);
8653 call_trans2setfsinfo(conn
, req
,
8654 &state
->param
, state
->total_param
,
8655 &state
->data
, state
->total_data
,
8656 state
->max_data_return
);
8657 END_PROFILE(Trans2_setfsinfo
);
8661 case TRANSACT2_QPATHINFO
:
8662 case TRANSACT2_QFILEINFO
:
8664 START_PROFILE(Trans2_qpathinfo
);
8665 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8666 &state
->param
, state
->total_param
,
8667 &state
->data
, state
->total_data
,
8668 state
->max_data_return
);
8669 END_PROFILE(Trans2_qpathinfo
);
8673 case TRANSACT2_SETPATHINFO
:
8674 case TRANSACT2_SETFILEINFO
:
8676 START_PROFILE(Trans2_setpathinfo
);
8677 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8678 &state
->param
, state
->total_param
,
8679 &state
->data
, state
->total_data
,
8680 state
->max_data_return
);
8681 END_PROFILE(Trans2_setpathinfo
);
8685 case TRANSACT2_FINDNOTIFYFIRST
:
8687 START_PROFILE(Trans2_findnotifyfirst
);
8688 call_trans2findnotifyfirst(conn
, req
,
8689 &state
->param
, state
->total_param
,
8690 &state
->data
, state
->total_data
,
8691 state
->max_data_return
);
8692 END_PROFILE(Trans2_findnotifyfirst
);
8696 case TRANSACT2_FINDNOTIFYNEXT
:
8698 START_PROFILE(Trans2_findnotifynext
);
8699 call_trans2findnotifynext(conn
, req
,
8700 &state
->param
, state
->total_param
,
8701 &state
->data
, state
->total_data
,
8702 state
->max_data_return
);
8703 END_PROFILE(Trans2_findnotifynext
);
8707 case TRANSACT2_MKDIR
:
8709 START_PROFILE(Trans2_mkdir
);
8710 call_trans2mkdir(conn
, req
,
8711 &state
->param
, state
->total_param
,
8712 &state
->data
, state
->total_data
,
8713 state
->max_data_return
);
8714 END_PROFILE(Trans2_mkdir
);
8718 case TRANSACT2_GET_DFS_REFERRAL
:
8720 START_PROFILE(Trans2_get_dfs_referral
);
8721 call_trans2getdfsreferral(conn
, req
,
8722 &state
->param
, state
->total_param
,
8723 &state
->data
, state
->total_data
,
8724 state
->max_data_return
);
8725 END_PROFILE(Trans2_get_dfs_referral
);
8729 case TRANSACT2_IOCTL
:
8731 START_PROFILE(Trans2_ioctl
);
8732 call_trans2ioctl(conn
, req
,
8733 &state
->param
, state
->total_param
,
8734 &state
->data
, state
->total_data
,
8735 state
->max_data_return
);
8736 END_PROFILE(Trans2_ioctl
);
8741 /* Error in request */
8742 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8743 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8747 /****************************************************************************
8748 Reply to a SMBtrans2.
8749 ****************************************************************************/
8751 void reply_trans2(struct smb_request
*req
)
8753 connection_struct
*conn
= req
->conn
;
8758 unsigned int tran_call
;
8759 struct trans_state
*state
;
8762 START_PROFILE(SMBtrans2
);
8764 if (req
->wct
< 14) {
8765 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8766 END_PROFILE(SMBtrans2
);
8770 dsoff
= SVAL(req
->vwv
+12, 0);
8771 dscnt
= SVAL(req
->vwv
+11, 0);
8772 psoff
= SVAL(req
->vwv
+10, 0);
8773 pscnt
= SVAL(req
->vwv
+9, 0);
8774 tran_call
= SVAL(req
->vwv
+14, 0);
8776 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8777 if (!NT_STATUS_IS_OK(result
)) {
8778 DEBUG(2, ("Got invalid trans2 request: %s\n",
8779 nt_errstr(result
)));
8780 reply_nterror(req
, result
);
8781 END_PROFILE(SMBtrans2
);
8786 switch (tran_call
) {
8787 /* List the allowed trans2 calls on IPC$ */
8788 case TRANSACT2_OPEN
:
8789 case TRANSACT2_GET_DFS_REFERRAL
:
8790 case TRANSACT2_QFILEINFO
:
8791 case TRANSACT2_QFSINFO
:
8792 case TRANSACT2_SETFSINFO
:
8795 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8796 END_PROFILE(SMBtrans2
);
8801 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8802 DEBUG(0, ("talloc failed\n"));
8803 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8804 END_PROFILE(SMBtrans2
);
8808 state
->cmd
= SMBtrans2
;
8810 state
->mid
= req
->mid
;
8811 state
->vuid
= req
->vuid
;
8812 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8813 state
->setup
= NULL
;
8814 state
->total_param
= SVAL(req
->vwv
+0, 0);
8815 state
->param
= NULL
;
8816 state
->total_data
= SVAL(req
->vwv
+1, 0);
8818 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8819 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8820 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8821 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8822 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8824 state
->call
= tran_call
;
8826 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8827 is so as a sanity check */
8828 if (state
->setup_count
!= 1) {
8830 * Need to have rc=0 for ioctl to get job id for OS/2.
8831 * Network printing will fail if function is not successful.
8832 * Similar function in reply.c will be used if protocol
8833 * is LANMAN1.0 instead of LM1.2X002.
8834 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8835 * outbuf doesn't have to be set(only job id is used).
8837 if ( (state
->setup_count
== 4)
8838 && (tran_call
== TRANSACT2_IOCTL
)
8839 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8840 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8841 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8843 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8844 DEBUG(2,("Transaction is %d\n",tran_call
));
8846 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8847 END_PROFILE(SMBtrans2
);
8852 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8855 if (state
->total_data
) {
8857 if (trans_oob(state
->total_data
, 0, dscnt
)
8858 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8862 /* Can't use talloc here, the core routines do realloc on the
8863 * params and data. */
8864 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8865 if (state
->data
== NULL
) {
8866 DEBUG(0,("reply_trans2: data malloc fail for %u "
8867 "bytes !\n", (unsigned int)state
->total_data
));
8869 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8870 END_PROFILE(SMBtrans2
);
8874 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8877 if (state
->total_param
) {
8879 if (trans_oob(state
->total_param
, 0, pscnt
)
8880 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8884 /* Can't use talloc here, the core routines do realloc on the
8885 * params and data. */
8886 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8887 if (state
->param
== NULL
) {
8888 DEBUG(0,("reply_trans: param malloc fail for %u "
8889 "bytes !\n", (unsigned int)state
->total_param
));
8890 SAFE_FREE(state
->data
);
8892 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8893 END_PROFILE(SMBtrans2
);
8897 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8900 state
->received_data
= dscnt
;
8901 state
->received_param
= pscnt
;
8903 if ((state
->received_param
== state
->total_param
) &&
8904 (state
->received_data
== state
->total_data
)) {
8906 handle_trans2(conn
, req
, state
);
8908 SAFE_FREE(state
->data
);
8909 SAFE_FREE(state
->param
);
8911 END_PROFILE(SMBtrans2
);
8915 DLIST_ADD(conn
->pending_trans
, state
);
8917 /* We need to send an interim response then receive the rest
8918 of the parameter/data bytes */
8919 reply_outbuf(req
, 0, 0);
8920 show_msg((char *)req
->outbuf
);
8921 END_PROFILE(SMBtrans2
);
8926 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8927 SAFE_FREE(state
->data
);
8928 SAFE_FREE(state
->param
);
8930 END_PROFILE(SMBtrans2
);
8931 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8935 /****************************************************************************
8936 Reply to a SMBtranss2
8937 ****************************************************************************/
8939 void reply_transs2(struct smb_request
*req
)
8941 connection_struct
*conn
= req
->conn
;
8942 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8943 struct trans_state
*state
;
8945 START_PROFILE(SMBtranss2
);
8947 show_msg((const char *)req
->inbuf
);
8949 /* Windows clients expect all replies to
8950 a transact secondary (SMBtranss2 0x33)
8951 to have a command code of transact
8952 (SMBtrans2 0x32). See bug #8989
8953 and also [MS-CIFS] section 2.2.4.47.2
8956 req
->cmd
= SMBtrans2
;
8959 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8960 END_PROFILE(SMBtranss2
);
8964 for (state
= conn
->pending_trans
; state
!= NULL
;
8965 state
= state
->next
) {
8966 if (state
->mid
== req
->mid
) {
8971 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8972 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8973 END_PROFILE(SMBtranss2
);
8977 /* Revise state->total_param and state->total_data in case they have
8978 changed downwards */
8980 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8981 state
->total_param
= SVAL(req
->vwv
+0, 0);
8982 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8983 state
->total_data
= SVAL(req
->vwv
+1, 0);
8985 pcnt
= SVAL(req
->vwv
+2, 0);
8986 poff
= SVAL(req
->vwv
+3, 0);
8987 pdisp
= SVAL(req
->vwv
+4, 0);
8989 dcnt
= SVAL(req
->vwv
+5, 0);
8990 doff
= SVAL(req
->vwv
+6, 0);
8991 ddisp
= SVAL(req
->vwv
+7, 0);
8993 state
->received_param
+= pcnt
;
8994 state
->received_data
+= dcnt
;
8996 if ((state
->received_data
> state
->total_data
) ||
8997 (state
->received_param
> state
->total_param
))
9001 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9002 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9005 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9009 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9010 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9013 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9016 if ((state
->received_param
< state
->total_param
) ||
9017 (state
->received_data
< state
->total_data
)) {
9018 END_PROFILE(SMBtranss2
);
9022 handle_trans2(conn
, req
, state
);
9024 DLIST_REMOVE(conn
->pending_trans
, state
);
9025 SAFE_FREE(state
->data
);
9026 SAFE_FREE(state
->param
);
9029 END_PROFILE(SMBtranss2
);
9034 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9035 DLIST_REMOVE(conn
->pending_trans
, state
);
9036 SAFE_FREE(state
->data
);
9037 SAFE_FREE(state
->param
);
9039 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9040 END_PROFILE(SMBtranss2
);