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
;
328 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
331 if (!NT_STATUS_IS_OK(status
)) {
335 if (num_names
== 0) {
340 for (i
=0; i
<num_names
; i
++) {
341 struct ea_list
*listp
;
344 if (strnequal(names
[i
], "system.", 7)
345 || samba_private_attr_name(names
[i
]))
348 listp
= talloc(mem_ctx
, struct ea_list
);
350 return NT_STATUS_NO_MEMORY
;
353 status
= get_ea_value(mem_ctx
, conn
, fsp
,
357 if (!NT_STATUS_IS_OK(status
)) {
361 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
364 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
366 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
367 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
368 (unsigned int)listp
->ea
.value
.length
));
370 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
374 /* Add on 4 for total length. */
375 if (*pea_total_len
) {
379 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
380 (unsigned int)*pea_total_len
));
382 *ea_list
= ea_list_head
;
386 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
387 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
392 if (!lp_ea_support(SNUM(conn
))) {
396 if (is_ntfs_stream_smb_fname(smb_fname
)) {
397 return NT_STATUS_INVALID_PARAMETER
;
400 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
403 /****************************************************************************
404 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
406 ****************************************************************************/
408 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
409 connection_struct
*conn
, struct ea_list
*ea_list
)
411 unsigned int ret_data_size
= 4;
414 SMB_ASSERT(total_data_size
>= 4);
416 if (!lp_ea_support(SNUM(conn
))) {
421 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
424 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
425 dos_namelen
= strlen(dos_ea_name
);
426 if (dos_namelen
> 255 || dos_namelen
== 0) {
429 if (ea_list
->ea
.value
.length
> 65535) {
432 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
436 /* We know we have room. */
437 SCVAL(p
,0,ea_list
->ea
.flags
);
438 SCVAL(p
,1,dos_namelen
);
439 SSVAL(p
,2,ea_list
->ea
.value
.length
);
440 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
441 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
443 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
444 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
447 ret_data_size
= PTR_DIFF(p
, pdata
);
448 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
449 SIVAL(pdata
,0,ret_data_size
);
450 return ret_data_size
;
453 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
455 unsigned int total_data_size
,
456 unsigned int *ret_data_size
,
457 connection_struct
*conn
,
458 struct ea_list
*ea_list
)
460 uint8_t *p
= (uint8_t *)pdata
;
461 uint8_t *last_start
= NULL
;
462 bool do_store_data
= (pdata
!= NULL
);
466 if (!lp_ea_support(SNUM(conn
))) {
467 return NT_STATUS_NO_EAS_ON_FILE
;
470 for (; ea_list
; ea_list
= ea_list
->next
) {
475 if (last_start
!= NULL
&& do_store_data
) {
476 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
480 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
481 dos_namelen
= strlen(dos_ea_name
);
482 if (dos_namelen
> 255 || dos_namelen
== 0) {
483 return NT_STATUS_INTERNAL_ERROR
;
485 if (ea_list
->ea
.value
.length
> 65535) {
486 return NT_STATUS_INTERNAL_ERROR
;
489 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
492 size_t pad
= 4 - (this_size
% 4);
497 if (this_size
> total_data_size
) {
498 return NT_STATUS_INFO_LENGTH_MISMATCH
;
501 /* We know we have room. */
502 SIVAL(p
, 0x00, 0); /* next offset */
503 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
504 SCVAL(p
, 0x05, dos_namelen
);
505 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
506 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
507 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
508 total_data_size
-= this_size
;
514 *ret_data_size
= PTR_DIFF(p
, pdata
);
515 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
519 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
521 size_t total_ea_len
= 0;
523 struct ea_list
*ea_list
= NULL
;
525 if (!lp_ea_support(SNUM(conn
))) {
528 mem_ctx
= talloc_stackframe();
530 /* If this is a stream fsp, then we need to instead find the
531 * estimated ea len from the main file, not the stream
532 * (streams cannot have EAs), but the estimate isn't just 0 in
534 if (is_ntfs_stream_smb_fname(smb_fname
)) {
537 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
538 TALLOC_FREE(mem_ctx
);
542 /****************************************************************************
543 Ensure the EA name is case insensitive by matching any existing EA name.
544 ****************************************************************************/
546 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
549 TALLOC_CTX
*mem_ctx
= talloc_tos();
550 struct ea_list
*ea_list
;
551 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
552 if (!NT_STATUS_IS_OK(status
)) {
556 for (; ea_list
; ea_list
= ea_list
->next
) {
557 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
558 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
559 &unix_ea_name
[5], ea_list
->ea
.name
));
560 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
566 /****************************************************************************
567 Set or delete an extended attribute.
568 ****************************************************************************/
570 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
571 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
576 if (!lp_ea_support(SNUM(conn
))) {
577 return NT_STATUS_EAS_NOT_SUPPORTED
;
580 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
581 if (!NT_STATUS_IS_OK(status
)) {
585 /* Setting EAs on streams isn't supported. */
586 if (is_ntfs_stream_smb_fname(smb_fname
)) {
587 return NT_STATUS_INVALID_PARAMETER
;
590 fname
= smb_fname
->base_name
;
592 for (;ea_list
; ea_list
= ea_list
->next
) {
594 fstring unix_ea_name
;
596 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
597 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
599 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
601 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
603 if (samba_private_attr_name(unix_ea_name
)) {
604 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
605 return NT_STATUS_ACCESS_DENIED
;
608 if (ea_list
->ea
.value
.length
== 0) {
609 /* Remove the attribute. */
610 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
611 DEBUG(10,("set_ea: deleting ea name %s on "
612 "file %s by file descriptor.\n",
613 unix_ea_name
, fsp_str_dbg(fsp
)));
614 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
616 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
617 unix_ea_name
, fname
));
618 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
621 /* Removing a non existent attribute always succeeds. */
622 if (ret
== -1 && errno
== ENOATTR
) {
623 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
629 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
630 DEBUG(10,("set_ea: setting ea name %s on file "
631 "%s by file descriptor.\n",
632 unix_ea_name
, fsp_str_dbg(fsp
)));
633 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
634 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
636 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
637 unix_ea_name
, fname
));
638 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
639 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
645 if (errno
== ENOTSUP
) {
646 return NT_STATUS_EAS_NOT_SUPPORTED
;
649 return map_nt_error_from_unix(errno
);
655 /****************************************************************************
656 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
657 ****************************************************************************/
659 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
661 struct ea_list
*ea_list_head
= NULL
;
662 size_t converted_size
, offset
= 0;
664 while (offset
+ 2 < data_size
) {
665 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
666 unsigned int namelen
= CVAL(pdata
,offset
);
668 offset
++; /* Go past the namelen byte. */
670 /* integer wrap paranioa. */
671 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
672 (offset
> data_size
) || (namelen
> data_size
) ||
673 (offset
+ namelen
>= data_size
)) {
676 /* Ensure the name is null terminated. */
677 if (pdata
[offset
+ namelen
] != '\0') {
680 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
682 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
683 "failed: %s", strerror(errno
)));
689 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
690 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
691 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
697 /****************************************************************************
698 Read one EA list entry from the buffer.
699 ****************************************************************************/
701 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
703 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
705 unsigned int namelen
;
706 size_t converted_size
;
716 eal
->ea
.flags
= CVAL(pdata
,0);
717 namelen
= CVAL(pdata
,1);
718 val_len
= SVAL(pdata
,2);
720 if (4 + namelen
+ 1 + val_len
> data_size
) {
724 /* Ensure the name is null terminated. */
725 if (pdata
[namelen
+ 4] != '\0') {
728 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
729 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
736 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
737 if (!eal
->ea
.value
.data
) {
741 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
743 /* Ensure we're null terminated just in case we print the value. */
744 eal
->ea
.value
.data
[val_len
] = '\0';
745 /* But don't count the null. */
746 eal
->ea
.value
.length
--;
749 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
752 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
753 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
758 /****************************************************************************
759 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
760 ****************************************************************************/
762 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
764 struct ea_list
*ea_list_head
= NULL
;
766 size_t bytes_used
= 0;
768 while (offset
< data_size
) {
769 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
775 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
776 offset
+= bytes_used
;
782 /****************************************************************************
783 Count the total EA size needed.
784 ****************************************************************************/
786 static size_t ea_list_size(struct ea_list
*ealist
)
789 struct ea_list
*listp
;
792 for (listp
= ealist
; listp
; listp
= listp
->next
) {
793 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
794 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
796 /* Add on 4 for total length. */
804 /****************************************************************************
805 Return a union of EA's from a file list and a list of names.
806 The TALLOC context for the two lists *MUST* be identical as we steal
807 memory from one list to add to another. JRA.
808 ****************************************************************************/
810 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
812 struct ea_list
*nlistp
, *flistp
;
814 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
815 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
816 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
822 /* Copy the data from this entry. */
823 nlistp
->ea
.flags
= flistp
->ea
.flags
;
824 nlistp
->ea
.value
= flistp
->ea
.value
;
827 nlistp
->ea
.flags
= 0;
828 ZERO_STRUCT(nlistp
->ea
.value
);
832 *total_ea_len
= ea_list_size(name_list
);
836 /****************************************************************************
837 Send the required number of replies back.
838 We assume all fields other than the data fields are
839 set correctly for the type of call.
840 HACK ! Always assumes smb_setup field is zero.
841 ****************************************************************************/
843 void send_trans2_replies(connection_struct
*conn
,
844 struct smb_request
*req
,
851 /* As we are using a protocol > LANMAN1 then the max_send
852 variable must have been set in the sessetupX call.
853 This takes precedence over the max_xmit field in the
854 global struct. These different max_xmit variables should
855 be merged as this is now too confusing */
857 int data_to_send
= datasize
;
858 int params_to_send
= paramsize
;
860 const char *pp
= params
;
861 const char *pd
= pdata
;
862 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
863 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
864 int data_alignment_offset
= 0;
865 bool overflow
= False
;
866 struct smbd_server_connection
*sconn
= req
->sconn
;
867 int max_send
= sconn
->smb1
.sessions
.max_send
;
869 /* Modify the data_to_send and datasize and set the error if
870 we're trying to send more than max_data_bytes. We still send
871 the part of the packet(s) that fit. Strange, but needed
874 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
875 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
876 max_data_bytes
, datasize
));
877 datasize
= data_to_send
= max_data_bytes
;
881 /* If there genuinely are no parameters or data to send just send the empty packet */
883 if(params_to_send
== 0 && data_to_send
== 0) {
884 reply_outbuf(req
, 10, 0);
885 show_msg((char *)req
->outbuf
);
886 if (!srv_send_smb(sconn
,
889 IS_CONN_ENCRYPTED(conn
),
891 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
893 TALLOC_FREE(req
->outbuf
);
897 /* When sending params and data ensure that both are nicely aligned */
898 /* Only do this alignment when there is also data to send - else
899 can cause NT redirector problems. */
901 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
902 data_alignment_offset
= 4 - (params_to_send
% 4);
904 /* Space is bufsize minus Netbios over TCP header minus SMB header */
905 /* The alignment_offset is to align the param bytes on an even byte
906 boundary. NT 4.0 Beta needs this to work correctly. */
908 useable_space
= max_send
- (smb_size
911 + data_alignment_offset
);
913 if (useable_space
< 0) {
914 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
915 "= %d!!!", useable_space
));
916 exit_server_cleanly("send_trans2_replies: Not enough space");
919 while (params_to_send
|| data_to_send
) {
920 /* Calculate whether we will totally or partially fill this packet */
922 total_sent_thistime
= params_to_send
+ data_to_send
;
924 /* We can never send more than useable_space */
926 * Note that 'useable_space' does not include the alignment offsets,
927 * but we must include the alignment offsets in the calculation of
928 * the length of the data we send over the wire, as the alignment offsets
929 * are sent here. Fix from Marc_Jacobsen@hp.com.
932 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
934 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
935 + data_alignment_offset
);
937 /* Set total params and data to be sent */
938 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
939 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
941 /* Calculate how many parameters and data we can fit into
942 * this packet. Parameters get precedence
945 params_sent_thistime
= MIN(params_to_send
,useable_space
);
946 data_sent_thistime
= useable_space
- params_sent_thistime
;
947 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
949 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
951 /* smb_proff is the offset from the start of the SMB header to the
952 parameter bytes, however the first 4 bytes of outbuf are
953 the Netbios over TCP header. Thus use smb_base() to subtract
954 them from the calculation */
956 SSVAL(req
->outbuf
,smb_proff
,
957 ((smb_buf(req
->outbuf
)+alignment_offset
)
958 - smb_base(req
->outbuf
)));
960 if(params_sent_thistime
== 0)
961 SSVAL(req
->outbuf
,smb_prdisp
,0);
963 /* Absolute displacement of param bytes sent in this packet */
964 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
966 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
967 if(data_sent_thistime
== 0) {
968 SSVAL(req
->outbuf
,smb_droff
,0);
969 SSVAL(req
->outbuf
,smb_drdisp
, 0);
971 /* The offset of the data bytes is the offset of the
972 parameter bytes plus the number of parameters being sent this time */
973 SSVAL(req
->outbuf
, smb_droff
,
974 ((smb_buf(req
->outbuf
)+alignment_offset
)
975 - smb_base(req
->outbuf
))
976 + params_sent_thistime
+ data_alignment_offset
);
977 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
980 /* Initialize the padding for alignment */
982 if (alignment_offset
!= 0) {
983 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
986 /* Copy the param bytes into the packet */
988 if(params_sent_thistime
) {
989 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
990 params_sent_thistime
);
993 /* Copy in the data bytes */
994 if(data_sent_thistime
) {
995 if (data_alignment_offset
!= 0) {
996 memset((smb_buf(req
->outbuf
)+alignment_offset
+
997 params_sent_thistime
), 0,
998 data_alignment_offset
);
1000 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1001 +params_sent_thistime
+data_alignment_offset
,
1002 pd
,data_sent_thistime
);
1005 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1006 params_sent_thistime
, data_sent_thistime
, useable_space
));
1007 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1008 params_to_send
, data_to_send
, paramsize
, datasize
));
1011 error_packet_set((char *)req
->outbuf
,
1012 ERRDOS
,ERRbufferoverflow
,
1013 STATUS_BUFFER_OVERFLOW
,
1017 /* Send the packet */
1018 show_msg((char *)req
->outbuf
);
1019 if (!srv_send_smb(sconn
,
1020 (char *)req
->outbuf
,
1021 true, req
->seqnum
+1,
1022 IS_CONN_ENCRYPTED(conn
),
1024 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1026 TALLOC_FREE(req
->outbuf
);
1028 pp
+= params_sent_thistime
;
1029 pd
+= data_sent_thistime
;
1031 params_to_send
-= params_sent_thistime
;
1032 data_to_send
-= data_sent_thistime
;
1035 if(params_to_send
< 0 || data_to_send
< 0) {
1036 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1037 params_to_send
, data_to_send
));
1045 /****************************************************************************
1046 Reply to a TRANSACT2_OPEN.
1047 ****************************************************************************/
1049 static void call_trans2open(connection_struct
*conn
,
1050 struct smb_request
*req
,
1051 char **pparams
, int total_params
,
1052 char **ppdata
, int total_data
,
1053 unsigned int max_data_bytes
)
1055 struct smb_filename
*smb_fname
= NULL
;
1056 char *params
= *pparams
;
1057 char *pdata
= *ppdata
;
1060 bool oplock_request
;
1062 bool return_additional_info
;
1071 int fattr
=0,mtime
=0;
1072 SMB_INO_T inode
= 0;
1075 struct ea_list
*ea_list
= NULL
;
1080 uint32 create_disposition
;
1081 uint32 create_options
= 0;
1082 uint32_t private_flags
= 0;
1083 TALLOC_CTX
*ctx
= talloc_tos();
1086 * Ensure we have enough parameters to perform the operation.
1089 if (total_params
< 29) {
1090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1094 flags
= SVAL(params
, 0);
1095 deny_mode
= SVAL(params
, 2);
1096 open_attr
= SVAL(params
,6);
1097 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1098 if (oplock_request
) {
1099 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1103 return_additional_info
= BITSETW(params
,0);
1104 open_sattr
= SVAL(params
, 4);
1105 open_time
= make_unix_date3(params
+8);
1107 open_ofun
= SVAL(params
,12);
1108 open_size
= IVAL(params
,14);
1109 pname
= ¶ms
[28];
1112 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1116 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1117 total_params
- 28, STR_TERMINATE
,
1119 if (!NT_STATUS_IS_OK(status
)) {
1120 reply_nterror(req
, status
);
1124 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1125 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1126 (unsigned int)open_ofun
, open_size
));
1128 status
= filename_convert(ctx
,
1130 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1135 if (!NT_STATUS_IS_OK(status
)) {
1136 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1137 reply_botherror(req
,
1138 NT_STATUS_PATH_NOT_COVERED
,
1139 ERRSRV
, ERRbadpath
);
1142 reply_nterror(req
, status
);
1146 if (open_ofun
== 0) {
1147 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1151 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1153 &access_mask
, &share_mode
,
1154 &create_disposition
,
1157 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1161 /* Any data in this call is an EA list. */
1162 if (total_data
&& (total_data
!= 4)) {
1163 if (total_data
< 10) {
1164 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1168 if (IVAL(pdata
,0) > total_data
) {
1169 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1170 IVAL(pdata
,0), (unsigned int)total_data
));
1171 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1175 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1178 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1182 if (!lp_ea_support(SNUM(conn
))) {
1183 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1188 status
= SMB_VFS_CREATE_FILE(
1191 0, /* root_dir_fid */
1192 smb_fname
, /* fname */
1193 access_mask
, /* access_mask */
1194 share_mode
, /* share_access */
1195 create_disposition
, /* create_disposition*/
1196 create_options
, /* create_options */
1197 open_attr
, /* file_attributes */
1198 oplock_request
, /* oplock_request */
1199 open_size
, /* allocation_size */
1202 ea_list
, /* ea_list */
1204 &smb_action
); /* psbuf */
1206 if (!NT_STATUS_IS_OK(status
)) {
1207 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1208 /* We have re-scheduled this call. */
1211 reply_openerror(req
, status
);
1215 size
= get_file_size_stat(&smb_fname
->st
);
1216 fattr
= dos_mode(conn
, smb_fname
);
1217 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1218 inode
= smb_fname
->st
.st_ex_ino
;
1219 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1220 close_file(req
, fsp
, ERROR_CLOSE
);
1221 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1225 /* Realloc the size of parameters and data we will return */
1226 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1227 if(*pparams
== NULL
) {
1228 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1233 SSVAL(params
,0,fsp
->fnum
);
1234 SSVAL(params
,2,fattr
);
1235 srv_put_dos_date2(params
,4, mtime
);
1236 SIVAL(params
,8, (uint32
)size
);
1237 SSVAL(params
,12,deny_mode
);
1238 SSVAL(params
,14,0); /* open_type - file or directory. */
1239 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1241 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1242 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1245 SSVAL(params
,18,smb_action
);
1248 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1250 SIVAL(params
,20,inode
);
1251 SSVAL(params
,24,0); /* Padding. */
1253 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1255 SIVAL(params
, 26, ea_size
);
1257 SIVAL(params
, 26, 0);
1260 /* Send the required number of replies */
1261 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1263 TALLOC_FREE(smb_fname
);
1266 /*********************************************************
1267 Routine to check if a given string matches exactly.
1268 as a special case a mask of "." does NOT match. That
1269 is required for correct wildcard semantics
1270 Case can be significant or not.
1271 **********************************************************/
1273 static bool exact_match(bool has_wild
,
1274 bool case_sensitive
,
1278 if (mask
[0] == '.' && mask
[1] == 0) {
1286 if (case_sensitive
) {
1287 return strcmp(str
,mask
)==0;
1289 return strcasecmp_m(str
,mask
) == 0;
1293 /****************************************************************************
1294 Return the filetype for UNIX extensions.
1295 ****************************************************************************/
1297 static uint32
unix_filetype(mode_t mode
)
1300 return UNIX_TYPE_FILE
;
1301 else if(S_ISDIR(mode
))
1302 return UNIX_TYPE_DIR
;
1304 else if(S_ISLNK(mode
))
1305 return UNIX_TYPE_SYMLINK
;
1308 else if(S_ISCHR(mode
))
1309 return UNIX_TYPE_CHARDEV
;
1312 else if(S_ISBLK(mode
))
1313 return UNIX_TYPE_BLKDEV
;
1316 else if(S_ISFIFO(mode
))
1317 return UNIX_TYPE_FIFO
;
1320 else if(S_ISSOCK(mode
))
1321 return UNIX_TYPE_SOCKET
;
1324 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1325 return UNIX_TYPE_UNKNOWN
;
1328 /****************************************************************************
1329 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1330 ****************************************************************************/
1332 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1334 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1335 const SMB_STRUCT_STAT
*psbuf
,
1337 enum perm_type ptype
,
1342 if (perms
== SMB_MODE_NO_CHANGE
) {
1343 if (!VALID_STAT(*psbuf
)) {
1344 return NT_STATUS_INVALID_PARAMETER
;
1346 *ret_perms
= psbuf
->st_ex_mode
;
1347 return NT_STATUS_OK
;
1351 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1352 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1353 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1354 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1355 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1356 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1357 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1358 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1359 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1361 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1364 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1367 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1372 case PERM_EXISTING_FILE
:
1373 /* Apply mode mask */
1374 ret
&= lp_create_mask(SNUM(conn
));
1375 /* Add in force bits */
1376 ret
|= lp_force_create_mode(SNUM(conn
));
1379 case PERM_EXISTING_DIR
:
1380 ret
&= lp_dir_mask(SNUM(conn
));
1381 /* Add in force bits */
1382 ret
|= lp_force_dir_mode(SNUM(conn
));
1387 return NT_STATUS_OK
;
1390 /****************************************************************************
1391 Needed to show the msdfs symlinks as directories. Modifies psbuf
1392 to be a directory if it's a msdfs link.
1393 ****************************************************************************/
1395 static bool check_msdfs_link(connection_struct
*conn
,
1396 const char *pathname
,
1397 SMB_STRUCT_STAT
*psbuf
)
1399 int saved_errno
= errno
;
1400 if(lp_host_msdfs() &&
1401 lp_msdfs_root(SNUM(conn
)) &&
1402 is_msdfs_link(conn
, pathname
, psbuf
)) {
1404 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1407 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1408 errno
= saved_errno
;
1411 errno
= saved_errno
;
1416 /****************************************************************************
1417 Get a level dependent lanman2 dir entry.
1418 ****************************************************************************/
1420 struct smbd_dirptr_lanman2_state
{
1421 connection_struct
*conn
;
1422 uint32_t info_level
;
1423 bool check_mangled_names
;
1425 bool got_exact_match
;
1428 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1434 struct smbd_dirptr_lanman2_state
*state
=
1435 (struct smbd_dirptr_lanman2_state
*)private_data
;
1437 char mangled_name
[13]; /* mangled 8.3 name. */
1441 /* Mangle fname if it's an illegal name. */
1442 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1443 ok
= name_to_8_3(dname
, mangled_name
,
1444 true, state
->conn
->params
);
1448 fname
= mangled_name
;
1453 got_match
= exact_match(state
->has_wild
,
1454 state
->conn
->case_sensitive
,
1456 state
->got_exact_match
= got_match
;
1458 got_match
= mask_match(fname
, mask
,
1459 state
->conn
->case_sensitive
);
1462 if(!got_match
&& state
->check_mangled_names
&&
1463 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1465 * It turns out that NT matches wildcards against
1466 * both long *and* short names. This may explain some
1467 * of the wildcard wierdness from old DOS clients
1468 * that some people have been seeing.... JRA.
1470 /* Force the mangling into 8.3. */
1471 ok
= name_to_8_3(fname
, mangled_name
,
1472 false, state
->conn
->params
);
1477 got_match
= exact_match(state
->has_wild
,
1478 state
->conn
->case_sensitive
,
1479 mangled_name
, mask
);
1480 state
->got_exact_match
= got_match
;
1482 got_match
= mask_match(mangled_name
, mask
,
1483 state
->conn
->case_sensitive
);
1491 *_fname
= talloc_strdup(ctx
, fname
);
1492 if (*_fname
== NULL
) {
1499 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1501 struct smb_filename
*smb_fname
,
1504 struct smbd_dirptr_lanman2_state
*state
=
1505 (struct smbd_dirptr_lanman2_state
*)private_data
;
1506 bool ms_dfs_link
= false;
1509 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1510 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1511 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1512 "Couldn't lstat [%s] (%s)\n",
1513 smb_fname_str_dbg(smb_fname
),
1517 } else if (!VALID_STAT(smb_fname
->st
) &&
1518 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1519 /* Needed to show the msdfs symlinks as
1522 ms_dfs_link
= check_msdfs_link(state
->conn
,
1523 smb_fname
->base_name
,
1526 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1527 "Couldn't stat [%s] (%s)\n",
1528 smb_fname_str_dbg(smb_fname
),
1535 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1537 mode
= dos_mode(state
->conn
, smb_fname
);
1544 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1545 connection_struct
*conn
,
1547 uint32_t info_level
,
1548 struct ea_list
*name_list
,
1549 bool check_mangled_names
,
1550 bool requires_resume_key
,
1553 const struct smb_filename
*smb_fname
,
1554 int space_remaining
,
1561 uint64_t *last_entry_off
)
1563 char *p
, *q
, *pdata
= *ppdata
;
1565 uint64_t file_size
= 0;
1566 uint64_t allocation_size
= 0;
1567 uint64_t file_index
= 0;
1569 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1570 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1572 char *last_entry_ptr
;
1577 *out_of_space
= false;
1579 ZERO_STRUCT(mdate_ts
);
1580 ZERO_STRUCT(adate_ts
);
1581 ZERO_STRUCT(create_date_ts
);
1582 ZERO_STRUCT(cdate_ts
);
1584 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1585 file_size
= get_file_size_stat(&smb_fname
->st
);
1587 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1589 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1591 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1592 adate_ts
= smb_fname
->st
.st_ex_atime
;
1593 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1594 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1596 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1597 dos_filetime_timespec(&create_date_ts
);
1598 dos_filetime_timespec(&mdate_ts
);
1599 dos_filetime_timespec(&adate_ts
);
1600 dos_filetime_timespec(&cdate_ts
);
1603 create_date
= convert_timespec_to_time_t(create_date_ts
);
1604 mdate
= convert_timespec_to_time_t(mdate_ts
);
1605 adate
= convert_timespec_to_time_t(adate_ts
);
1607 /* align the record */
1608 SMB_ASSERT(align
>= 1);
1610 off
= (int)PTR_DIFF(pdata
, base_data
);
1611 pad
= (off
+ (align
-1)) & ~(align
-1);
1614 if (pad
&& pad
> space_remaining
) {
1615 *out_of_space
= true;
1616 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1617 "for padding (wanted %u, had %d)\n",
1620 return false; /* Not finished - just out of space */
1624 /* initialize padding to 0 */
1626 memset(pdata
, 0, pad
);
1628 space_remaining
-= pad
;
1630 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1640 switch (info_level
) {
1641 case SMB_FIND_INFO_STANDARD
:
1642 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1643 if(requires_resume_key
) {
1647 srv_put_dos_date2(p
,0,create_date
);
1648 srv_put_dos_date2(p
,4,adate
);
1649 srv_put_dos_date2(p
,8,mdate
);
1650 SIVAL(p
,12,(uint32
)file_size
);
1651 SIVAL(p
,16,(uint32
)allocation_size
);
1655 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1656 p
+= ucs2_align(base_data
, p
, 0);
1658 len
= srvstr_push(base_data
, flags2
, p
,
1659 fname
, PTR_DIFF(end_data
, p
),
1661 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1663 SCVAL(nameptr
, -1, len
- 2);
1665 SCVAL(nameptr
, -1, 0);
1669 SCVAL(nameptr
, -1, len
- 1);
1671 SCVAL(nameptr
, -1, 0);
1677 case SMB_FIND_EA_SIZE
:
1678 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1679 if (requires_resume_key
) {
1683 srv_put_dos_date2(p
,0,create_date
);
1684 srv_put_dos_date2(p
,4,adate
);
1685 srv_put_dos_date2(p
,8,mdate
);
1686 SIVAL(p
,12,(uint32
)file_size
);
1687 SIVAL(p
,16,(uint32
)allocation_size
);
1690 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1692 SIVAL(p
,22,ea_size
); /* Extended attributes */
1696 len
= srvstr_push(base_data
, flags2
,
1697 p
, fname
, PTR_DIFF(end_data
, p
),
1698 STR_TERMINATE
| STR_NOALIGN
);
1699 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1712 SCVAL(nameptr
,0,len
);
1714 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1717 case SMB_FIND_EA_LIST
:
1719 struct ea_list
*file_list
= NULL
;
1723 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1727 if (requires_resume_key
) {
1731 srv_put_dos_date2(p
,0,create_date
);
1732 srv_put_dos_date2(p
,4,adate
);
1733 srv_put_dos_date2(p
,8,mdate
);
1734 SIVAL(p
,12,(uint32
)file_size
);
1735 SIVAL(p
,16,(uint32
)allocation_size
);
1737 p
+= 22; /* p now points to the EA area. */
1739 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1741 &ea_len
, &file_list
);
1742 if (!NT_STATUS_IS_OK(status
)) {
1745 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1747 /* We need to determine if this entry will fit in the space available. */
1748 /* Max string size is 255 bytes. */
1749 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1750 *out_of_space
= true;
1751 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1752 "(wanted %u, had %d)\n",
1753 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1755 return False
; /* Not finished - just out of space */
1758 /* Push the ea_data followed by the name. */
1759 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1761 len
= srvstr_push(base_data
, flags2
,
1762 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1763 STR_TERMINATE
| STR_NOALIGN
);
1764 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1777 SCVAL(nameptr
,0,len
);
1779 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1783 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1784 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1785 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1787 SIVAL(p
,0,reskey
); p
+= 4;
1788 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1789 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1790 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1791 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1792 SOFF_T(p
,0,file_size
); p
+= 8;
1793 SOFF_T(p
,0,allocation_size
); p
+= 8;
1794 SIVAL(p
,0,mode
); p
+= 4;
1795 q
= p
; p
+= 4; /* q is placeholder for name length. */
1797 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1799 SIVAL(p
,0,ea_size
); /* Extended attributes */
1802 /* Clear the short name buffer. This is
1803 * IMPORTANT as not doing so will trigger
1804 * a Win2k client bug. JRA.
1806 if (!was_8_3
&& check_mangled_names
) {
1807 char mangled_name
[13]; /* mangled 8.3 name. */
1808 if (!name_to_8_3(fname
,mangled_name
,True
,
1810 /* Error - mangle failed ! */
1811 memset(mangled_name
,'\0',12);
1813 mangled_name
[12] = 0;
1814 len
= srvstr_push(base_data
, flags2
,
1815 p
+2, mangled_name
, 24,
1816 STR_UPPER
|STR_UNICODE
);
1818 memset(p
+ 2 + len
,'\0',24 - len
);
1825 len
= srvstr_push(base_data
, flags2
, p
,
1826 fname
, PTR_DIFF(end_data
, p
),
1827 STR_TERMINATE_ASCII
);
1831 len
= PTR_DIFF(p
, pdata
);
1832 pad
= (len
+ (align
-1)) & ~(align
-1);
1834 * offset to the next entry, the caller
1835 * will overwrite it for the last entry
1836 * that's why we always include the padding
1840 * set padding to zero
1843 memset(p
, 0, pad
- len
);
1850 case SMB_FIND_FILE_DIRECTORY_INFO
:
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1853 SIVAL(p
,0,reskey
); p
+= 4;
1854 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1855 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1856 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1857 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1858 SOFF_T(p
,0,file_size
); p
+= 8;
1859 SOFF_T(p
,0,allocation_size
); p
+= 8;
1860 SIVAL(p
,0,mode
); p
+= 4;
1861 len
= srvstr_push(base_data
, flags2
,
1862 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1863 STR_TERMINATE_ASCII
);
1867 len
= PTR_DIFF(p
, pdata
);
1868 pad
= (len
+ (align
-1)) & ~(align
-1);
1870 * offset to the next entry, the caller
1871 * will overwrite it for the last entry
1872 * that's why we always include the padding
1876 * set padding to zero
1879 memset(p
, 0, pad
- len
);
1886 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1887 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1889 SIVAL(p
,0,reskey
); p
+= 4;
1890 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1891 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1892 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1893 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1894 SOFF_T(p
,0,file_size
); p
+= 8;
1895 SOFF_T(p
,0,allocation_size
); p
+= 8;
1896 SIVAL(p
,0,mode
); p
+= 4;
1897 q
= p
; p
+= 4; /* q is placeholder for name length. */
1899 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1901 SIVAL(p
,0,ea_size
); /* Extended attributes */
1904 len
= srvstr_push(base_data
, flags2
, p
,
1905 fname
, PTR_DIFF(end_data
, p
),
1906 STR_TERMINATE_ASCII
);
1910 len
= PTR_DIFF(p
, pdata
);
1911 pad
= (len
+ (align
-1)) & ~(align
-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1919 * set padding to zero
1922 memset(p
, 0, pad
- len
);
1929 case SMB_FIND_FILE_NAMES_INFO
:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1932 SIVAL(p
,0,reskey
); p
+= 4;
1934 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1935 acl on a dir (tridge) */
1936 len
= srvstr_push(base_data
, flags2
, p
,
1937 fname
, PTR_DIFF(end_data
, p
),
1938 STR_TERMINATE_ASCII
);
1942 len
= PTR_DIFF(p
, pdata
);
1943 pad
= (len
+ (align
-1)) & ~(align
-1);
1945 * offset to the next entry, the caller
1946 * will overwrite it for the last entry
1947 * that's why we always include the padding
1951 * set padding to zero
1954 memset(p
, 0, pad
- len
);
1961 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1962 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1964 SIVAL(p
,0,reskey
); p
+= 4;
1965 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1966 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1967 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1968 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1969 SOFF_T(p
,0,file_size
); p
+= 8;
1970 SOFF_T(p
,0,allocation_size
); p
+= 8;
1971 SIVAL(p
,0,mode
); p
+= 4;
1972 q
= p
; p
+= 4; /* q is placeholder for name length. */
1974 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1976 SIVAL(p
,0,ea_size
); /* Extended attributes */
1979 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1980 SBVAL(p
,0,file_index
); p
+= 8;
1981 len
= srvstr_push(base_data
, flags2
, p
,
1982 fname
, PTR_DIFF(end_data
, p
),
1983 STR_TERMINATE_ASCII
);
1987 len
= PTR_DIFF(p
, pdata
);
1988 pad
= (len
+ (align
-1)) & ~(align
-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1996 * set padding to zero
1999 memset(p
, 0, pad
- len
);
2006 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2008 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2010 SIVAL(p
,0,reskey
); p
+= 4;
2011 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2012 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2013 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2014 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2015 SOFF_T(p
,0,file_size
); p
+= 8;
2016 SOFF_T(p
,0,allocation_size
); p
+= 8;
2017 SIVAL(p
,0,mode
); p
+= 4;
2018 q
= p
; p
+= 4; /* q is placeholder for name length */
2020 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2022 SIVAL(p
,0,ea_size
); /* Extended attributes */
2025 /* Clear the short name buffer. This is
2026 * IMPORTANT as not doing so will trigger
2027 * a Win2k client bug. JRA.
2029 if (!was_8_3
&& check_mangled_names
) {
2030 char mangled_name
[13]; /* mangled 8.3 name. */
2031 if (!name_to_8_3(fname
,mangled_name
,True
,
2033 /* Error - mangle failed ! */
2034 memset(mangled_name
,'\0',12);
2036 mangled_name
[12] = 0;
2037 len
= srvstr_push(base_data
, flags2
,
2038 p
+2, mangled_name
, 24,
2039 STR_UPPER
|STR_UNICODE
);
2042 memset(p
+ 2 + len
,'\0',24 - len
);
2049 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2050 SBVAL(p
,0,file_index
); p
+= 8;
2051 len
= srvstr_push(base_data
, flags2
, p
,
2052 fname
, PTR_DIFF(end_data
, p
),
2053 STR_TERMINATE_ASCII
);
2057 len
= PTR_DIFF(p
, pdata
);
2058 pad
= (len
+ (align
-1)) & ~(align
-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2066 * set padding to zero
2069 memset(p
, 0, pad
- len
);
2076 /* CIFS UNIX Extension. */
2078 case SMB_FIND_FILE_UNIX
:
2079 case SMB_FIND_FILE_UNIX_INFO2
:
2081 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2083 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2085 if (info_level
== SMB_FIND_FILE_UNIX
) {
2086 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2087 p
= store_file_unix_basic(conn
, p
,
2088 NULL
, &smb_fname
->st
);
2089 len
= srvstr_push(base_data
, flags2
, p
,
2090 fname
, PTR_DIFF(end_data
, p
),
2093 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2094 p
= store_file_unix_basic_info2(conn
, p
,
2095 NULL
, &smb_fname
->st
);
2098 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2099 PTR_DIFF(end_data
, p
), 0);
2100 SIVAL(nameptr
, 0, len
);
2105 len
= PTR_DIFF(p
, pdata
);
2106 pad
= (len
+ (align
-1)) & ~(align
-1);
2108 * offset to the next entry, the caller
2109 * will overwrite it for the last entry
2110 * that's why we always include the padding
2114 * set padding to zero
2117 memset(p
, 0, pad
- len
);
2122 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2130 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2131 *out_of_space
= true;
2132 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2133 "(wanted %u, had %d)\n",
2134 (unsigned int)PTR_DIFF(p
,pdata
),
2136 return false; /* Not finished - just out of space */
2139 /* Setup the last entry pointer, as an offset from base_data */
2140 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2141 /* Advance the data pointer to the next slot */
2147 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2148 connection_struct
*conn
,
2149 struct dptr_struct
*dirptr
,
2151 const char *path_mask
,
2154 int requires_resume_key
,
2162 int space_remaining
,
2164 bool *got_exact_match
,
2165 int *_last_entry_off
,
2166 struct ea_list
*name_list
)
2169 const char *mask
= NULL
;
2170 long prev_dirpos
= 0;
2173 struct smb_filename
*smb_fname
= NULL
;
2174 struct smbd_dirptr_lanman2_state state
;
2176 uint64_t last_entry_off
= 0;
2180 state
.info_level
= info_level
;
2181 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2182 state
.has_wild
= dptr_has_wild(dirptr
);
2183 state
.got_exact_match
= false;
2185 *out_of_space
= false;
2186 *got_exact_match
= false;
2188 p
= strrchr_m(path_mask
,'/');
2199 ok
= smbd_dirptr_get_entry(ctx
,
2205 smbd_dirptr_lanman2_match_fn
,
2206 smbd_dirptr_lanman2_mode_fn
,
2216 *got_exact_match
= state
.got_exact_match
;
2218 ok
= smbd_marshall_dir_entry(ctx
,
2223 state
.check_mangled_names
,
2224 requires_resume_key
,
2237 TALLOC_FREE(smb_fname
);
2238 if (*out_of_space
) {
2239 dptr_SeekDir(dirptr
, prev_dirpos
);
2246 *_last_entry_off
= last_entry_off
;
2250 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2251 connection_struct
*conn
,
2252 struct dptr_struct
*dirptr
,
2254 const char *path_mask
,
2257 bool requires_resume_key
,
2263 int space_remaining
,
2265 bool *got_exact_match
,
2266 int *last_entry_off
,
2267 struct ea_list
*name_list
)
2270 const bool do_pad
= true;
2272 if (info_level
>= 1 && info_level
<= 3) {
2273 /* No alignment on earlier info levels. */
2277 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2278 path_mask
, dirtype
, info_level
,
2279 requires_resume_key
, dont_descend
, ask_sharemode
,
2281 ppdata
, base_data
, end_data
,
2283 out_of_space
, got_exact_match
,
2284 last_entry_off
, name_list
);
2287 /****************************************************************************
2288 Reply to a TRANS2_FINDFIRST.
2289 ****************************************************************************/
2291 static void call_trans2findfirst(connection_struct
*conn
,
2292 struct smb_request
*req
,
2293 char **pparams
, int total_params
,
2294 char **ppdata
, int total_data
,
2295 unsigned int max_data_bytes
)
2297 /* We must be careful here that we don't return more than the
2298 allowed number of data bytes. If this means returning fewer than
2299 maxentries then so be it. We assume that the redirector has
2300 enough room for the fixed number of parameter bytes it has
2302 struct smb_filename
*smb_dname
= NULL
;
2303 char *params
= *pparams
;
2304 char *pdata
= *ppdata
;
2308 uint16 findfirst_flags
;
2309 bool close_after_first
;
2311 bool requires_resume_key
;
2313 char *directory
= NULL
;
2316 int last_entry_off
=0;
2320 bool finished
= False
;
2321 bool dont_descend
= False
;
2322 bool out_of_space
= False
;
2323 int space_remaining
;
2324 bool mask_contains_wcard
= False
;
2325 struct ea_list
*ea_list
= NULL
;
2326 NTSTATUS ntstatus
= NT_STATUS_OK
;
2327 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2328 TALLOC_CTX
*ctx
= talloc_tos();
2329 struct dptr_struct
*dirptr
= NULL
;
2330 struct smbd_server_connection
*sconn
= req
->sconn
;
2331 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2332 bool backup_priv
= false;
2334 if (total_params
< 13) {
2335 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2339 dirtype
= SVAL(params
,0);
2340 maxentries
= SVAL(params
,2);
2341 findfirst_flags
= SVAL(params
,4);
2342 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2343 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2344 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2345 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2346 security_token_has_privilege(get_current_nttok(conn
),
2349 info_level
= SVAL(params
,6);
2351 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2352 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2353 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2355 info_level
, max_data_bytes
));
2358 /* W2K3 seems to treat zero as 1. */
2362 switch (info_level
) {
2363 case SMB_FIND_INFO_STANDARD
:
2364 case SMB_FIND_EA_SIZE
:
2365 case SMB_FIND_EA_LIST
:
2366 case SMB_FIND_FILE_DIRECTORY_INFO
:
2367 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2368 case SMB_FIND_FILE_NAMES_INFO
:
2369 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2370 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2371 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2373 case SMB_FIND_FILE_UNIX
:
2374 case SMB_FIND_FILE_UNIX_INFO2
:
2375 /* Always use filesystem for UNIX mtime query. */
2376 ask_sharemode
= false;
2377 if (!lp_unix_extensions()) {
2378 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2381 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2384 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2388 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2389 params
+12, total_params
- 12,
2390 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2391 if (!NT_STATUS_IS_OK(ntstatus
)) {
2392 reply_nterror(req
, ntstatus
);
2398 ntstatus
= filename_convert_with_privilege(ctx
,
2403 &mask_contains_wcard
,
2406 ntstatus
= filename_convert(ctx
, conn
,
2407 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2410 &mask_contains_wcard
,
2414 if (!NT_STATUS_IS_OK(ntstatus
)) {
2415 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2416 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2417 ERRSRV
, ERRbadpath
);
2420 reply_nterror(req
, ntstatus
);
2424 mask
= smb_dname
->original_lcomp
;
2426 directory
= smb_dname
->base_name
;
2428 p
= strrchr_m(directory
,'/');
2430 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2431 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2432 mask
= talloc_strdup(ctx
,"*");
2434 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2437 mask_contains_wcard
= True
;
2443 if (p
== NULL
|| p
== directory
) {
2444 /* Ensure we don't have a directory name of "". */
2445 directory
= talloc_strdup(talloc_tos(), ".");
2447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2452 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2454 if (info_level
== SMB_FIND_EA_LIST
) {
2457 if (total_data
< 4) {
2458 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2462 ea_size
= IVAL(pdata
,0);
2463 if (ea_size
!= total_data
) {
2464 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2465 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2466 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2470 if (!lp_ea_support(SNUM(conn
))) {
2471 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2475 /* Pull out the list of names. */
2476 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2478 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2483 *ppdata
= (char *)SMB_REALLOC(
2484 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2485 if(*ppdata
== NULL
) {
2486 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2490 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2492 /* Realloc the params space */
2493 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2494 if (*pparams
== NULL
) {
2495 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2500 /* Save the wildcard match and attribs we are using on this directory -
2501 needed as lanman2 assumes these are being saved between calls */
2503 ntstatus
= dptr_create(conn
,
2511 mask_contains_wcard
,
2515 if (!NT_STATUS_IS_OK(ntstatus
)) {
2516 reply_nterror(req
, ntstatus
);
2521 /* Remember this in case we have
2522 to do a findnext. */
2523 dptr_set_priv(dirptr
);
2526 dptr_num
= dptr_dnum(dirptr
);
2527 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2529 /* Initialize per TRANS2_FIND_FIRST operation data */
2530 dptr_init_search_op(dirptr
);
2532 /* We don't need to check for VOL here as this is returned by
2533 a different TRANS2 call. */
2535 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2536 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2537 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2538 dont_descend
= True
;
2541 space_remaining
= max_data_bytes
;
2542 out_of_space
= False
;
2544 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2545 bool got_exact_match
= False
;
2547 /* this is a heuristic to avoid seeking the dirptr except when
2548 absolutely necessary. It allows for a filename of about 40 chars */
2549 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2550 out_of_space
= True
;
2553 finished
= !get_lanman2_dir_entry(ctx
,
2557 mask
,dirtype
,info_level
,
2558 requires_resume_key
,dont_descend
,
2561 space_remaining
, &out_of_space
,
2563 &last_entry_off
, ea_list
);
2566 if (finished
&& out_of_space
)
2569 if (!finished
&& !out_of_space
)
2573 * As an optimisation if we know we aren't looking
2574 * for a wildcard name (ie. the name matches the wildcard exactly)
2575 * then we can finish on any (first) match.
2576 * This speeds up large directory searches. JRA.
2582 /* Ensure space_remaining never goes -ve. */
2583 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2584 space_remaining
= 0;
2585 out_of_space
= true;
2587 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2591 /* Check if we can close the dirptr */
2592 if(close_after_first
|| (finished
&& close_if_end
)) {
2593 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2594 dptr_close(sconn
, &dptr_num
);
2598 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2599 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2600 * the protocol level is less than NT1. Tested with smbclient. JRA.
2601 * This should fix the OS/2 client bug #2335.
2604 if(numentries
== 0) {
2605 dptr_close(sconn
, &dptr_num
);
2606 if (get_Protocol() < PROTOCOL_NT1
) {
2607 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2610 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2611 ERRDOS
, ERRbadfile
);
2616 /* At this point pdata points to numentries directory entries. */
2618 /* Set up the return parameter block */
2619 SSVAL(params
,0,dptr_num
);
2620 SSVAL(params
,2,numentries
);
2621 SSVAL(params
,4,finished
);
2622 SSVAL(params
,6,0); /* Never an EA error */
2623 SSVAL(params
,8,last_entry_off
);
2625 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2628 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2629 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2631 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2635 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2636 smb_fn_name(req
->cmd
),
2637 mask
, directory
, dirtype
, numentries
) );
2640 * Force a name mangle here to ensure that the
2641 * mask as an 8.3 name is top of the mangled cache.
2642 * The reasons for this are subtle. Don't remove
2643 * this code unless you know what you are doing
2644 * (see PR#13758). JRA.
2647 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2648 char mangled_name
[13];
2649 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2657 TALLOC_FREE(smb_dname
);
2661 /****************************************************************************
2662 Reply to a TRANS2_FINDNEXT.
2663 ****************************************************************************/
2665 static void call_trans2findnext(connection_struct
*conn
,
2666 struct smb_request
*req
,
2667 char **pparams
, int total_params
,
2668 char **ppdata
, int total_data
,
2669 unsigned int max_data_bytes
)
2671 /* We must be careful here that we don't return more than the
2672 allowed number of data bytes. If this means returning fewer than
2673 maxentries then so be it. We assume that the redirector has
2674 enough room for the fixed number of parameter bytes it has
2676 char *params
= *pparams
;
2677 char *pdata
= *ppdata
;
2683 uint16 findnext_flags
;
2684 bool close_after_request
;
2686 bool requires_resume_key
;
2688 bool mask_contains_wcard
= False
;
2689 char *resume_name
= NULL
;
2690 const char *mask
= NULL
;
2691 const char *directory
= NULL
;
2695 int i
, last_entry_off
=0;
2696 bool finished
= False
;
2697 bool dont_descend
= False
;
2698 bool out_of_space
= False
;
2699 int space_remaining
;
2700 struct ea_list
*ea_list
= NULL
;
2701 NTSTATUS ntstatus
= NT_STATUS_OK
;
2702 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2703 TALLOC_CTX
*ctx
= talloc_tos();
2704 struct dptr_struct
*dirptr
;
2705 struct smbd_server_connection
*sconn
= req
->sconn
;
2706 bool backup_priv
= false;
2708 if (total_params
< 13) {
2709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2713 dptr_num
= SVAL(params
,0);
2714 maxentries
= SVAL(params
,2);
2715 info_level
= SVAL(params
,4);
2716 resume_key
= IVAL(params
,6);
2717 findnext_flags
= SVAL(params
,10);
2718 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2719 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2720 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2721 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2723 if (!continue_bit
) {
2724 /* We only need resume_name if continue_bit is zero. */
2725 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2727 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2728 &mask_contains_wcard
);
2729 if (!NT_STATUS_IS_OK(ntstatus
)) {
2730 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2731 complain (it thinks we're asking for the directory above the shared
2732 path or an invalid name). Catch this as the resume name is only compared, never used in
2733 a file access. JRA. */
2734 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2735 &resume_name
, params
+12,
2739 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2740 reply_nterror(req
, ntstatus
);
2746 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2747 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2748 resume_key = %d resume name = %s continue=%d level = %d\n",
2749 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2750 requires_resume_key
, resume_key
,
2751 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2754 /* W2K3 seems to treat zero as 1. */
2758 switch (info_level
) {
2759 case SMB_FIND_INFO_STANDARD
:
2760 case SMB_FIND_EA_SIZE
:
2761 case SMB_FIND_EA_LIST
:
2762 case SMB_FIND_FILE_DIRECTORY_INFO
:
2763 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2764 case SMB_FIND_FILE_NAMES_INFO
:
2765 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2766 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2767 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2769 case SMB_FIND_FILE_UNIX
:
2770 case SMB_FIND_FILE_UNIX_INFO2
:
2771 /* Always use filesystem for UNIX mtime query. */
2772 ask_sharemode
= false;
2773 if (!lp_unix_extensions()) {
2774 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2779 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2783 if (info_level
== SMB_FIND_EA_LIST
) {
2786 if (total_data
< 4) {
2787 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2791 ea_size
= IVAL(pdata
,0);
2792 if (ea_size
!= total_data
) {
2793 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2794 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2795 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2799 if (!lp_ea_support(SNUM(conn
))) {
2800 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2804 /* Pull out the list of names. */
2805 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2807 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2812 *ppdata
= (char *)SMB_REALLOC(
2813 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2814 if(*ppdata
== NULL
) {
2815 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2820 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2822 /* Realloc the params space */
2823 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2824 if(*pparams
== NULL
) {
2825 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2831 /* Check that the dptr is valid */
2832 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2833 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2837 directory
= dptr_path(sconn
, dptr_num
);
2839 /* Get the wildcard mask from the dptr */
2840 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2841 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2842 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2846 /* Get the attr mask from the dptr */
2847 dirtype
= dptr_attr(sconn
, dptr_num
);
2849 backup_priv
= dptr_get_priv(dirptr
);
2851 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2852 "backup_priv = %d\n",
2853 dptr_num
, mask
, dirtype
,
2855 dptr_TellDir(dirptr
),
2858 /* Initialize per TRANS2_FIND_NEXT operation data */
2859 dptr_init_search_op(dirptr
);
2861 /* We don't need to check for VOL here as this is returned by
2862 a different TRANS2 call. */
2864 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2865 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2866 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2867 dont_descend
= True
;
2870 space_remaining
= max_data_bytes
;
2871 out_of_space
= False
;
2878 * Seek to the correct position. We no longer use the resume key but
2879 * depend on the last file name instead.
2882 if(!continue_bit
&& resume_name
&& *resume_name
) {
2885 long current_pos
= 0;
2887 * Remember, name_to_8_3 is called by
2888 * get_lanman2_dir_entry(), so the resume name
2889 * could be mangled. Ensure we check the unmangled name.
2892 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2893 char *new_resume_name
= NULL
;
2894 mangle_lookup_name_from_8_3(ctx
,
2898 if (new_resume_name
) {
2899 resume_name
= new_resume_name
;
2904 * Fix for NT redirector problem triggered by resume key indexes
2905 * changing between directory scans. We now return a resume key of 0
2906 * and instead look for the filename to continue from (also given
2907 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2908 * findfirst/findnext (as is usual) then the directory pointer
2909 * should already be at the correct place.
2912 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2913 } /* end if resume_name && !continue_bit */
2915 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2916 bool got_exact_match
= False
;
2918 /* this is a heuristic to avoid seeking the dirptr except when
2919 absolutely necessary. It allows for a filename of about 40 chars */
2920 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2921 out_of_space
= True
;
2924 finished
= !get_lanman2_dir_entry(ctx
,
2928 mask
,dirtype
,info_level
,
2929 requires_resume_key
,dont_descend
,
2932 space_remaining
, &out_of_space
,
2934 &last_entry_off
, ea_list
);
2937 if (finished
&& out_of_space
)
2940 if (!finished
&& !out_of_space
)
2944 * As an optimisation if we know we aren't looking
2945 * for a wildcard name (ie. the name matches the wildcard exactly)
2946 * then we can finish on any (first) match.
2947 * This speeds up large directory searches. JRA.
2953 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2956 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2957 smb_fn_name(req
->cmd
),
2958 mask
, directory
, dirtype
, numentries
) );
2960 /* Check if we can close the dirptr */
2961 if(close_after_request
|| (finished
&& close_if_end
)) {
2962 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2963 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2970 /* Set up the return parameter block */
2971 SSVAL(params
,0,numentries
);
2972 SSVAL(params
,2,finished
);
2973 SSVAL(params
,4,0); /* Never an EA error */
2974 SSVAL(params
,6,last_entry_off
);
2976 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2982 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2984 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2988 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2990 SMB_ASSERT(extended_info
!= NULL
);
2992 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2993 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2994 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2995 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2996 #ifdef SAMBA_VERSION_REVISION
2997 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2999 extended_info
->samba_subversion
= 0;
3000 #ifdef SAMBA_VERSION_RC_RELEASE
3001 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3003 #ifdef SAMBA_VERSION_PRE_RELEASE
3004 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3007 #ifdef SAMBA_VERSION_VENDOR_PATCH
3008 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3010 extended_info
->samba_gitcommitdate
= 0;
3011 #ifdef SAMBA_VERSION_COMMIT_TIME
3012 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3015 memset(extended_info
->samba_version_string
, 0,
3016 sizeof(extended_info
->samba_version_string
));
3018 snprintf (extended_info
->samba_version_string
,
3019 sizeof(extended_info
->samba_version_string
),
3020 "%s", samba_version_string());
3023 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3024 TALLOC_CTX
*mem_ctx
,
3025 uint16_t info_level
,
3027 unsigned int max_data_bytes
,
3028 struct smb_filename
*fname
,
3032 char *pdata
, *end_data
;
3033 int data_len
= 0, len
;
3034 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3035 int snum
= SNUM(conn
);
3036 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3037 char *filename
= NULL
;
3038 uint32 additional_flags
= 0;
3039 struct smb_filename smb_fname
;
3042 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3045 filename
= fname
->base_name
;
3049 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3050 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3051 "info level (0x%x) on IPC$.\n",
3052 (unsigned int)info_level
));
3053 return NT_STATUS_ACCESS_DENIED
;
3057 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3059 ZERO_STRUCT(smb_fname
);
3060 smb_fname
.base_name
= discard_const_p(char, filename
);
3062 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3063 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3064 return map_nt_error_from_unix(errno
);
3069 *ppdata
= (char *)SMB_REALLOC(
3070 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3071 if (*ppdata
== NULL
) {
3072 return NT_STATUS_NO_MEMORY
;
3076 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3077 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3079 switch (info_level
) {
3080 case SMB_INFO_ALLOCATION
:
3082 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3084 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno
);
3088 block_size
= lp_block_size(snum
);
3089 if (bsize
< block_size
) {
3090 uint64_t factor
= block_size
/bsize
;
3095 if (bsize
> block_size
) {
3096 uint64_t factor
= bsize
/block_size
;
3101 bytes_per_sector
= 512;
3102 sectors_per_unit
= bsize
/bytes_per_sector
;
3104 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3105 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3106 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3108 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3109 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3110 SIVAL(pdata
,l1_cUnit
,dsize
);
3111 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3112 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3116 case SMB_INFO_VOLUME
:
3117 /* Return volume name */
3119 * Add volume serial number - hash of a combination of
3120 * the called hostname and the service name.
3122 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3124 * Win2k3 and previous mess this up by sending a name length
3125 * one byte short. I believe only older clients (OS/2 Win9x) use
3126 * this call so try fixing this by adding a terminating null to
3127 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3131 pdata
+l2_vol_szVolLabel
, vname
,
3132 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3133 STR_NOALIGN
|STR_TERMINATE
);
3134 SCVAL(pdata
,l2_vol_cch
,len
);
3135 data_len
= l2_vol_szVolLabel
+ len
;
3136 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3137 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3141 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3142 case SMB_FS_ATTRIBUTE_INFORMATION
:
3144 additional_flags
= 0;
3145 #if defined(HAVE_SYS_QUOTAS)
3146 additional_flags
|= FILE_VOLUME_QUOTAS
;
3149 if(lp_nt_acl_support(SNUM(conn
))) {
3150 additional_flags
|= FILE_PERSISTENT_ACLS
;
3153 /* Capabilities are filled in at connection time through STATVFS call */
3154 additional_flags
|= conn
->fs_capabilities
;
3155 additional_flags
|= lp_parm_int(conn
->params
->service
,
3156 "share", "fake_fscaps",
3159 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3160 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3161 additional_flags
); /* FS ATTRIBUTES */
3163 SIVAL(pdata
,4,255); /* Max filename component length */
3164 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3165 and will think we can't do long filenames */
3166 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3167 PTR_DIFF(end_data
, pdata
+12),
3170 data_len
= 12 + len
;
3173 case SMB_QUERY_FS_LABEL_INFO
:
3174 case SMB_FS_LABEL_INFORMATION
:
3175 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3176 PTR_DIFF(end_data
, pdata
+4), 0);
3181 case SMB_QUERY_FS_VOLUME_INFO
:
3182 case SMB_FS_VOLUME_INFORMATION
:
3185 * Add volume serial number - hash of a combination of
3186 * the called hostname and the service name.
3188 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3189 (str_checksum(get_local_machine_name())<<16));
3191 /* Max label len is 32 characters. */
3192 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3193 PTR_DIFF(end_data
, pdata
+18),
3195 SIVAL(pdata
,12,len
);
3198 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3199 (int)strlen(vname
),vname
,
3200 lp_servicename(talloc_tos(), snum
)));
3203 case SMB_QUERY_FS_SIZE_INFO
:
3204 case SMB_FS_SIZE_INFORMATION
:
3206 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3208 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3209 return map_nt_error_from_unix(errno
);
3211 block_size
= lp_block_size(snum
);
3212 if (bsize
< block_size
) {
3213 uint64_t factor
= block_size
/bsize
;
3218 if (bsize
> block_size
) {
3219 uint64_t factor
= bsize
/block_size
;
3224 bytes_per_sector
= 512;
3225 sectors_per_unit
= bsize
/bytes_per_sector
;
3226 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3227 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3228 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3229 SBIG_UINT(pdata
,0,dsize
);
3230 SBIG_UINT(pdata
,8,dfree
);
3231 SIVAL(pdata
,16,sectors_per_unit
);
3232 SIVAL(pdata
,20,bytes_per_sector
);
3236 case SMB_FS_FULL_SIZE_INFORMATION
:
3238 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3240 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3241 return map_nt_error_from_unix(errno
);
3243 block_size
= lp_block_size(snum
);
3244 if (bsize
< block_size
) {
3245 uint64_t factor
= block_size
/bsize
;
3250 if (bsize
> block_size
) {
3251 uint64_t factor
= bsize
/block_size
;
3256 bytes_per_sector
= 512;
3257 sectors_per_unit
= bsize
/bytes_per_sector
;
3258 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3259 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3260 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3261 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3262 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3263 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3264 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3265 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3269 case SMB_QUERY_FS_DEVICE_INFO
:
3270 case SMB_FS_DEVICE_INFORMATION
:
3272 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3274 if (!CAN_WRITE(conn
)) {
3275 characteristics
|= FILE_READ_ONLY_DEVICE
;
3278 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3279 SIVAL(pdata
,4,characteristics
);
3283 #ifdef HAVE_SYS_QUOTAS
3284 case SMB_FS_QUOTA_INFORMATION
:
3286 * what we have to send --metze:
3288 * Unknown1: 24 NULL bytes
3289 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3290 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3291 * Quota Flags: 2 byte :
3292 * Unknown3: 6 NULL bytes
3296 * details for Quota Flags:
3298 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3299 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3300 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3301 * 0x0001 Enable Quotas: enable quota for this fs
3305 /* we need to fake up a fsp here,
3306 * because its not send in this call
3309 SMB_NTQUOTA_STRUCT quotas
;
3312 ZERO_STRUCT(quotas
);
3315 fsp
.fnum
= FNUM_FIELD_INVALID
;
3318 if (get_current_uid(conn
) != 0) {
3319 DEBUG(0,("set_user_quota: access_denied "
3320 "service [%s] user [%s]\n",
3321 lp_servicename(talloc_tos(), SNUM(conn
)),
3322 conn
->session_info
->unix_info
->unix_name
));
3323 return NT_STATUS_ACCESS_DENIED
;
3326 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3327 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3328 return map_nt_error_from_unix(errno
);
3333 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3334 lp_servicename(talloc_tos(), SNUM(conn
))));
3336 /* Unknown1 24 NULL bytes*/
3337 SBIG_UINT(pdata
,0,(uint64_t)0);
3338 SBIG_UINT(pdata
,8,(uint64_t)0);
3339 SBIG_UINT(pdata
,16,(uint64_t)0);
3341 /* Default Soft Quota 8 bytes */
3342 SBIG_UINT(pdata
,24,quotas
.softlim
);
3344 /* Default Hard Quota 8 bytes */
3345 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3347 /* Quota flag 2 bytes */
3348 SSVAL(pdata
,40,quotas
.qflags
);
3350 /* Unknown3 6 NULL bytes */
3356 #endif /* HAVE_SYS_QUOTAS */
3357 case SMB_FS_OBJECTID_INFORMATION
:
3359 unsigned char objid
[16];
3360 struct smb_extended_info extended_info
;
3361 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3362 samba_extended_info_version (&extended_info
);
3363 SIVAL(pdata
,16,extended_info
.samba_magic
);
3364 SIVAL(pdata
,20,extended_info
.samba_version
);
3365 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3366 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3367 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3373 * Query the version and capabilities of the CIFS UNIX extensions
3377 case SMB_QUERY_CIFS_UNIX_INFO
:
3379 bool large_write
= lp_min_receive_file_size() &&
3380 !srv_is_signing_active(conn
->sconn
);
3381 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3382 int encrypt_caps
= 0;
3384 if (!lp_unix_extensions()) {
3385 return NT_STATUS_INVALID_LEVEL
;
3388 switch (conn
->encrypt_level
) {
3389 case SMB_SIGNING_OFF
:
3392 case SMB_SIGNING_IF_REQUIRED
:
3393 case SMB_SIGNING_DEFAULT
:
3394 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3396 case SMB_SIGNING_REQUIRED
:
3397 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3398 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3399 large_write
= false;
3405 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3406 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3408 /* We have POSIX ACLs, pathname, encryption,
3409 * large read/write, and locking capability. */
3411 SBIG_UINT(pdata
,4,((uint64_t)(
3412 CIFS_UNIX_POSIX_ACLS_CAP
|
3413 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3414 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3415 CIFS_UNIX_EXTATTR_CAP
|
3416 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3418 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3420 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3424 case SMB_QUERY_POSIX_FS_INFO
:
3427 vfs_statvfs_struct svfs
;
3429 if (!lp_unix_extensions()) {
3430 return NT_STATUS_INVALID_LEVEL
;
3433 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3437 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3438 SIVAL(pdata
,4,svfs
.BlockSize
);
3439 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3440 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3441 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3442 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3443 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3444 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3445 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3447 } else if (rc
== EOPNOTSUPP
) {
3448 return NT_STATUS_INVALID_LEVEL
;
3449 #endif /* EOPNOTSUPP */
3451 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3452 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3457 case SMB_QUERY_POSIX_WHOAMI
:
3463 if (!lp_unix_extensions()) {
3464 return NT_STATUS_INVALID_LEVEL
;
3467 if (max_data_bytes
< 40) {
3468 return NT_STATUS_BUFFER_TOO_SMALL
;
3471 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3472 flags
|= SMB_WHOAMI_GUEST
;
3475 /* NOTE: 8 bytes for UID/GID, irrespective of native
3476 * platform size. This matches
3477 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3479 data_len
= 4 /* flags */
3486 + 4 /* pad/reserved */
3487 + (conn
->session_info
->unix_token
->ngroups
* 8)
3489 + (conn
->session_info
->security_token
->num_sids
*
3493 SIVAL(pdata
, 0, flags
);
3494 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3496 (uint64_t)conn
->session_info
->unix_token
->uid
);
3497 SBIG_UINT(pdata
, 16,
3498 (uint64_t)conn
->session_info
->unix_token
->gid
);
3501 if (data_len
>= max_data_bytes
) {
3502 /* Potential overflow, skip the GIDs and SIDs. */
3504 SIVAL(pdata
, 24, 0); /* num_groups */
3505 SIVAL(pdata
, 28, 0); /* num_sids */
3506 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3507 SIVAL(pdata
, 36, 0); /* reserved */
3513 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3514 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3516 /* We walk the SID list twice, but this call is fairly
3517 * infrequent, and I don't expect that it's performance
3518 * sensitive -- jpeach
3520 for (i
= 0, sid_bytes
= 0;
3521 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3522 sid_bytes
+= ndr_size_dom_sid(
3523 &conn
->session_info
->security_token
->sids
[i
],
3527 /* SID list byte count */
3528 SIVAL(pdata
, 32, sid_bytes
);
3530 /* 4 bytes pad/reserved - must be zero */
3531 SIVAL(pdata
, 36, 0);
3535 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3536 SBIG_UINT(pdata
, data_len
,
3537 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3543 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3544 int sid_len
= ndr_size_dom_sid(
3545 &conn
->session_info
->security_token
->sids
[i
],
3548 sid_linearize(pdata
+ data_len
, sid_len
,
3549 &conn
->session_info
->security_token
->sids
[i
]);
3550 data_len
+= sid_len
;
3556 case SMB_MAC_QUERY_FS_INFO
:
3558 * Thursby MAC extension... ONLY on NTFS filesystems
3559 * once we do streams then we don't need this
3561 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3563 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3568 return NT_STATUS_INVALID_LEVEL
;
3571 *ret_data_len
= data_len
;
3572 return NT_STATUS_OK
;
3575 /****************************************************************************
3576 Reply to a TRANS2_QFSINFO (query filesystem info).
3577 ****************************************************************************/
3579 static void call_trans2qfsinfo(connection_struct
*conn
,
3580 struct smb_request
*req
,
3581 char **pparams
, int total_params
,
3582 char **ppdata
, int total_data
,
3583 unsigned int max_data_bytes
)
3585 char *params
= *pparams
;
3586 uint16_t info_level
;
3590 if (total_params
< 2) {
3591 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3595 info_level
= SVAL(params
,0);
3597 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3598 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3599 DEBUG(0,("call_trans2qfsinfo: encryption required "
3600 "and info level 0x%x sent.\n",
3601 (unsigned int)info_level
));
3602 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3607 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3609 status
= smbd_do_qfsinfo(conn
, req
,
3615 if (!NT_STATUS_IS_OK(status
)) {
3616 reply_nterror(req
, status
);
3620 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3623 DEBUG( 4, ( "%s info_level = %d\n",
3624 smb_fn_name(req
->cmd
), info_level
) );
3629 /****************************************************************************
3630 Reply to a TRANS2_SETFSINFO (set filesystem info).
3631 ****************************************************************************/
3633 static void call_trans2setfsinfo(connection_struct
*conn
,
3634 struct smb_request
*req
,
3635 char **pparams
, int total_params
,
3636 char **ppdata
, int total_data
,
3637 unsigned int max_data_bytes
)
3639 struct smbd_server_connection
*sconn
= req
->sconn
;
3640 char *pdata
= *ppdata
;
3641 char *params
= *pparams
;
3644 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3645 lp_servicename(talloc_tos(), SNUM(conn
))));
3648 if (total_params
< 4) {
3649 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3651 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3655 info_level
= SVAL(params
,2);
3658 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3659 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3660 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3661 "info level (0x%x) on IPC$.\n",
3662 (unsigned int)info_level
));
3663 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3668 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3669 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3670 DEBUG(0,("call_trans2setfsinfo: encryption required "
3671 "and info level 0x%x sent.\n",
3672 (unsigned int)info_level
));
3673 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3678 switch(info_level
) {
3679 case SMB_SET_CIFS_UNIX_INFO
:
3680 if (!lp_unix_extensions()) {
3681 DEBUG(2,("call_trans2setfsinfo: "
3682 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3683 "unix extensions off\n"));
3685 NT_STATUS_INVALID_LEVEL
);
3689 /* There should be 12 bytes of capabilities set. */
3690 if (total_data
< 12) {
3693 NT_STATUS_INVALID_PARAMETER
);
3696 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3697 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3698 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3699 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3700 /* Just print these values for now. */
3701 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3702 "major = %u, minor = %u cap_low = 0x%x, "
3704 (unsigned int)sconn
->
3705 smb1
.unix_info
.client_major
,
3706 (unsigned int)sconn
->
3707 smb1
.unix_info
.client_minor
,
3708 (unsigned int)sconn
->
3709 smb1
.unix_info
.client_cap_low
,
3710 (unsigned int)sconn
->
3711 smb1
.unix_info
.client_cap_high
));
3713 /* Here is where we must switch to posix pathname processing... */
3714 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3715 lp_set_posix_pathnames();
3716 mangle_change_to_posix();
3719 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3720 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3721 /* Client that knows how to do posix locks,
3722 * but not posix open/mkdir operations. Set a
3723 * default type for read/write checks. */
3725 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3730 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3733 size_t param_len
= 0;
3734 size_t data_len
= total_data
;
3736 if (!lp_unix_extensions()) {
3739 NT_STATUS_INVALID_LEVEL
);
3743 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3746 NT_STATUS_NOT_SUPPORTED
);
3750 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3751 DEBUG( 2,("call_trans2setfsinfo: "
3752 "request transport encryption disabled"
3753 "with 'fork echo handler = yes'\n"));
3756 NT_STATUS_NOT_SUPPORTED
);
3760 DEBUG( 4,("call_trans2setfsinfo: "
3761 "request transport encryption.\n"));
3763 status
= srv_request_encryption_setup(conn
,
3764 (unsigned char **)ppdata
,
3766 (unsigned char **)pparams
,
3769 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3770 !NT_STATUS_IS_OK(status
)) {
3771 reply_nterror(req
, status
);
3775 send_trans2_replies(conn
, req
,
3782 if (NT_STATUS_IS_OK(status
)) {
3783 /* Server-side transport
3784 * encryption is now *on*. */
3785 status
= srv_encryption_start(conn
);
3786 if (!NT_STATUS_IS_OK(status
)) {
3787 char *reason
= talloc_asprintf(talloc_tos(),
3788 "Failure in setting "
3789 "up encrypted transport: %s",
3791 exit_server_cleanly(reason
);
3797 case SMB_FS_QUOTA_INFORMATION
:
3799 files_struct
*fsp
= NULL
;
3800 SMB_NTQUOTA_STRUCT quotas
;
3802 ZERO_STRUCT(quotas
);
3805 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3806 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3807 lp_servicename(talloc_tos(), SNUM(conn
)),
3808 conn
->session_info
->unix_info
->unix_name
));
3809 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3813 /* note: normaly there're 48 bytes,
3814 * but we didn't use the last 6 bytes for now
3817 fsp
= file_fsp(req
, SVAL(params
,0));
3819 if (!check_fsp_ntquota_handle(conn
, req
,
3821 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3823 req
, NT_STATUS_INVALID_HANDLE
);
3827 if (total_data
< 42) {
3828 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3832 NT_STATUS_INVALID_PARAMETER
);
3836 /* unknown_1 24 NULL bytes in pdata*/
3838 /* the soft quotas 8 bytes (uint64_t)*/
3839 quotas
.softlim
= BVAL(pdata
,24);
3841 /* the hard quotas 8 bytes (uint64_t)*/
3842 quotas
.hardlim
= BVAL(pdata
,32);
3844 /* quota_flags 2 bytes **/
3845 quotas
.qflags
= SVAL(pdata
,40);
3847 /* unknown_2 6 NULL bytes follow*/
3849 /* now set the quotas */
3850 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3851 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3852 reply_nterror(req
, map_nt_error_from_unix(errno
));
3859 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3861 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3867 * sending this reply works fine,
3868 * but I'm not sure it's the same
3869 * like windows do...
3872 reply_outbuf(req
, 10, 0);
3875 #if defined(HAVE_POSIX_ACLS)
3876 /****************************************************************************
3877 Utility function to count the number of entries in a POSIX acl.
3878 ****************************************************************************/
3880 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3882 unsigned int ace_count
= 0;
3883 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3884 SMB_ACL_ENTRY_T entry
;
3886 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3888 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3889 entry_id
= SMB_ACL_NEXT_ENTRY
;
3896 /****************************************************************************
3897 Utility function to marshall a POSIX acl into wire format.
3898 ****************************************************************************/
3900 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3902 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3903 SMB_ACL_ENTRY_T entry
;
3905 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3906 SMB_ACL_TAG_T tagtype
;
3907 SMB_ACL_PERMSET_T permset
;
3908 unsigned char perms
= 0;
3909 unsigned int own_grp
;
3912 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3913 entry_id
= SMB_ACL_NEXT_ENTRY
;
3916 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3917 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3921 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3922 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3926 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3927 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3928 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3930 SCVAL(pdata
,1,perms
);
3933 case SMB_ACL_USER_OBJ
:
3934 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3935 own_grp
= (unsigned int)pst
->st_ex_uid
;
3936 SIVAL(pdata
,2,own_grp
);
3941 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3943 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3946 own_grp
= (unsigned int)*puid
;
3947 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3948 SIVAL(pdata
,2,own_grp
);
3952 case SMB_ACL_GROUP_OBJ
:
3953 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3954 own_grp
= (unsigned int)pst
->st_ex_gid
;
3955 SIVAL(pdata
,2,own_grp
);
3960 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3962 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3965 own_grp
= (unsigned int)*pgid
;
3966 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3967 SIVAL(pdata
,2,own_grp
);
3972 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3973 SIVAL(pdata
,2,0xFFFFFFFF);
3974 SIVAL(pdata
,6,0xFFFFFFFF);
3977 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3978 SIVAL(pdata
,2,0xFFFFFFFF);
3979 SIVAL(pdata
,6,0xFFFFFFFF);
3982 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3985 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3992 /****************************************************************************
3993 Store the FILE_UNIX_BASIC info.
3994 ****************************************************************************/
3996 static char *store_file_unix_basic(connection_struct
*conn
,
3999 const SMB_STRUCT_STAT
*psbuf
)
4001 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4004 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4005 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4007 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4010 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4013 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4014 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4015 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4018 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4022 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4026 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4029 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4030 devno
= psbuf
->st_ex_rdev
;
4032 devno
= psbuf
->st_ex_dev
;
4035 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4039 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4043 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4046 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4050 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4057 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4058 * the chflags(2) (or equivalent) flags.
4060 * XXX: this really should be behind the VFS interface. To do this, we would
4061 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4062 * Each VFS module could then implement its own mapping as appropriate for the
4063 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4065 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4069 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4073 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4077 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4081 { UF_HIDDEN
, EXT_HIDDEN
},
4084 /* Do not remove. We need to guarantee that this array has at least one
4085 * entry to build on HP-UX.
4091 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4092 uint32
*smb_fflags
, uint32
*smb_fmask
)
4096 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4097 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4098 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4099 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4104 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4105 const uint32 smb_fflags
,
4106 const uint32 smb_fmask
,
4109 uint32 max_fmask
= 0;
4112 *stat_fflags
= psbuf
->st_ex_flags
;
4114 /* For each flags requested in smb_fmask, check the state of the
4115 * corresponding flag in smb_fflags and set or clear the matching
4119 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4120 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4121 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4122 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4123 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4125 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4130 /* If smb_fmask is asking to set any bits that are not supported by
4131 * our flag mappings, we should fail.
4133 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4141 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4142 * of file flags and birth (create) time.
4144 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4147 const SMB_STRUCT_STAT
*psbuf
)
4149 uint32 file_flags
= 0;
4150 uint32 flags_mask
= 0;
4152 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4154 /* Create (birth) time 64 bit */
4155 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4158 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4159 SIVAL(pdata
, 0, file_flags
); /* flags */
4160 SIVAL(pdata
, 4, flags_mask
); /* mask */
4166 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4167 const struct stream_struct
*streams
,
4169 unsigned int max_data_bytes
,
4170 unsigned int *data_size
)
4173 unsigned int ofs
= 0;
4175 for (i
= 0; i
< num_streams
; i
++) {
4176 unsigned int next_offset
;
4178 smb_ucs2_t
*namebuf
;
4180 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4181 streams
[i
].name
, &namelen
) ||
4184 return NT_STATUS_INVALID_PARAMETER
;
4188 * name_buf is now null-terminated, we need to marshall as not
4195 * We cannot overflow ...
4197 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4198 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4200 TALLOC_FREE(namebuf
);
4201 return STATUS_BUFFER_OVERFLOW
;
4204 SIVAL(data
, ofs
+4, namelen
);
4205 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4206 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4207 memcpy(data
+ofs
+24, namebuf
, namelen
);
4208 TALLOC_FREE(namebuf
);
4210 next_offset
= ofs
+ 24 + namelen
;
4212 if (i
== num_streams
-1) {
4213 SIVAL(data
, ofs
, 0);
4216 unsigned int align
= ndr_align_size(next_offset
, 8);
4218 if ((next_offset
+ align
) > max_data_bytes
) {
4219 DEBUG(10, ("refusing to overflow align "
4220 "reply at stream %u\n",
4222 TALLOC_FREE(namebuf
);
4223 return STATUS_BUFFER_OVERFLOW
;
4226 memset(data
+next_offset
, 0, align
);
4227 next_offset
+= align
;
4229 SIVAL(data
, ofs
, next_offset
- ofs
);
4236 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4240 return NT_STATUS_OK
;
4243 /****************************************************************************
4244 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4245 ****************************************************************************/
4247 static void call_trans2qpipeinfo(connection_struct
*conn
,
4248 struct smb_request
*req
,
4249 unsigned int tran_call
,
4250 char **pparams
, int total_params
,
4251 char **ppdata
, int total_data
,
4252 unsigned int max_data_bytes
)
4254 char *params
= *pparams
;
4255 char *pdata
= *ppdata
;
4256 unsigned int data_size
= 0;
4257 unsigned int param_size
= 2;
4262 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4266 if (total_params
< 4) {
4267 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4271 fsp
= file_fsp(req
, SVAL(params
,0));
4272 if (!fsp_is_np(fsp
)) {
4273 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4277 info_level
= SVAL(params
,2);
4279 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4280 if (*pparams
== NULL
) {
4281 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4286 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4287 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4288 if (*ppdata
== NULL
) {
4289 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4294 switch (info_level
) {
4295 case SMB_FILE_STANDARD_INFORMATION
:
4297 SOFF_T(pdata
,0,4096LL);
4304 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4308 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4314 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4315 TALLOC_CTX
*mem_ctx
,
4316 uint16_t info_level
,
4318 struct smb_filename
*smb_fname
,
4319 bool delete_pending
,
4320 struct timespec write_time_ts
,
4321 struct ea_list
*ea_list
,
4322 int lock_data_count
,
4325 unsigned int max_data_bytes
,
4327 unsigned int *pdata_size
)
4329 char *pdata
= *ppdata
;
4330 char *dstart
, *dend
;
4331 unsigned int data_size
;
4332 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4333 time_t create_time
, mtime
, atime
, c_time
;
4334 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4341 uint64_t file_size
= 0;
4343 uint64_t allocation_size
= 0;
4344 uint64_t file_index
= 0;
4345 uint32_t access_mask
= 0;
4347 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4348 return NT_STATUS_INVALID_LEVEL
;
4351 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4352 smb_fname_str_dbg(smb_fname
),
4354 info_level
, max_data_bytes
));
4356 mode
= dos_mode(conn
, smb_fname
);
4357 nlink
= psbuf
->st_ex_nlink
;
4359 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4363 if ((nlink
> 0) && delete_pending
) {
4367 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4368 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4369 if (*ppdata
== NULL
) {
4370 return NT_STATUS_NO_MEMORY
;
4374 dend
= dstart
+ data_size
- 1;
4376 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4377 update_stat_ex_mtime(psbuf
, write_time_ts
);
4380 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4381 mtime_ts
= psbuf
->st_ex_mtime
;
4382 atime_ts
= psbuf
->st_ex_atime
;
4383 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4385 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4386 dos_filetime_timespec(&create_time_ts
);
4387 dos_filetime_timespec(&mtime_ts
);
4388 dos_filetime_timespec(&atime_ts
);
4389 dos_filetime_timespec(&ctime_ts
);
4392 create_time
= convert_timespec_to_time_t(create_time_ts
);
4393 mtime
= convert_timespec_to_time_t(mtime_ts
);
4394 atime
= convert_timespec_to_time_t(atime_ts
);
4395 c_time
= convert_timespec_to_time_t(ctime_ts
);
4397 p
= strrchr_m(smb_fname
->base_name
,'/');
4399 base_name
= smb_fname
->base_name
;
4403 /* NT expects the name to be in an exact form of the *full*
4404 filename. See the trans2 torture test */
4405 if (ISDOT(base_name
)) {
4406 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4408 return NT_STATUS_NO_MEMORY
;
4411 dos_fname
= talloc_asprintf(mem_ctx
,
4413 smb_fname
->base_name
);
4415 return NT_STATUS_NO_MEMORY
;
4417 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4418 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4419 smb_fname
->stream_name
);
4421 return NT_STATUS_NO_MEMORY
;
4425 string_replace(dos_fname
, '/', '\\');
4428 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4431 /* Do we have this path open ? */
4433 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4434 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4435 if (fsp1
&& fsp1
->initial_allocation_size
) {
4436 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4440 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4441 file_size
= get_file_size_stat(psbuf
);
4445 pos
= fsp
->fh
->position_information
;
4449 access_mask
= fsp
->access_mask
;
4451 /* GENERIC_EXECUTE mapping from Windows */
4452 access_mask
= 0x12019F;
4455 /* This should be an index number - looks like
4458 I think this causes us to fail the IFSKIT
4459 BasicFileInformationTest. -tpot */
4460 file_index
= get_FileIndex(conn
, psbuf
);
4462 switch (info_level
) {
4463 case SMB_INFO_STANDARD
:
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4466 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4467 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4468 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4469 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4470 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4471 SSVAL(pdata
,l1_attrFile
,mode
);
4474 case SMB_INFO_QUERY_EA_SIZE
:
4476 unsigned int ea_size
=
4477 estimate_ea_size(conn
, fsp
,
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4481 srv_put_dos_date2(pdata
,0,create_time
);
4482 srv_put_dos_date2(pdata
,4,atime
);
4483 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4484 SIVAL(pdata
,12,(uint32
)file_size
);
4485 SIVAL(pdata
,16,(uint32
)allocation_size
);
4486 SSVAL(pdata
,20,mode
);
4487 SIVAL(pdata
,22,ea_size
);
4491 case SMB_INFO_IS_NAME_VALID
:
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4494 /* os/2 needs this ? really ?*/
4495 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4497 /* This is only reached for qpathinfo */
4501 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4503 size_t total_ea_len
= 0;
4504 struct ea_list
*ea_file_list
= NULL
;
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4508 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4510 &total_ea_len
, &ea_file_list
);
4511 if (!NT_STATUS_IS_OK(status
)) {
4515 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4517 if (!ea_list
|| (total_ea_len
> data_size
)) {
4519 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4523 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4527 case SMB_INFO_QUERY_ALL_EAS
:
4529 /* We have data_size bytes to put EA's into. */
4530 size_t total_ea_len
= 0;
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4533 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4535 &total_ea_len
, &ea_list
);
4536 if (!NT_STATUS_IS_OK(status
)) {
4540 if (!ea_list
|| (total_ea_len
> data_size
)) {
4542 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4546 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4550 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4552 /* This is FileFullEaInformation - 0xF which maps to
4553 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4555 /* We have data_size bytes to put EA's into. */
4556 size_t total_ea_len
= 0;
4557 struct ea_list
*ea_file_list
= NULL
;
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4561 /*TODO: add filtering and index handling */
4564 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4566 &total_ea_len
, &ea_file_list
);
4567 if (!NT_STATUS_IS_OK(status
)) {
4570 if (!ea_file_list
) {
4571 return NT_STATUS_NO_EAS_ON_FILE
;
4574 status
= fill_ea_chained_buffer(mem_ctx
,
4578 conn
, ea_file_list
);
4579 if (!NT_STATUS_IS_OK(status
)) {
4585 case SMB_FILE_BASIC_INFORMATION
:
4586 case SMB_QUERY_FILE_BASIC_INFO
:
4588 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4590 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4596 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4597 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4598 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4599 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4600 SIVAL(pdata
,32,mode
);
4602 DEBUG(5,("SMB_QFBI - "));
4603 DEBUG(5,("create: %s ", ctime(&create_time
)));
4604 DEBUG(5,("access: %s ", ctime(&atime
)));
4605 DEBUG(5,("write: %s ", ctime(&mtime
)));
4606 DEBUG(5,("change: %s ", ctime(&c_time
)));
4607 DEBUG(5,("mode: %x\n", mode
));
4610 case SMB_FILE_STANDARD_INFORMATION
:
4611 case SMB_QUERY_FILE_STANDARD_INFO
:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4615 SOFF_T(pdata
,0,allocation_size
);
4616 SOFF_T(pdata
,8,file_size
);
4617 SIVAL(pdata
,16,nlink
);
4618 SCVAL(pdata
,20,delete_pending
?1:0);
4619 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4620 SSVAL(pdata
,22,0); /* Padding. */
4623 case SMB_FILE_EA_INFORMATION
:
4624 case SMB_QUERY_FILE_EA_INFO
:
4626 unsigned int ea_size
=
4627 estimate_ea_size(conn
, fsp
, smb_fname
);
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4630 SIVAL(pdata
,0,ea_size
);
4634 /* Get the 8.3 name - used if NT SMB was negotiated. */
4635 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4636 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4639 char mangled_name
[13];
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4641 if (!name_to_8_3(base_name
,mangled_name
,
4642 True
,conn
->params
)) {
4643 return NT_STATUS_NO_MEMORY
;
4645 len
= srvstr_push(dstart
, flags2
,
4646 pdata
+4, mangled_name
,
4647 PTR_DIFF(dend
, pdata
+4),
4649 data_size
= 4 + len
;
4654 case SMB_QUERY_FILE_NAME_INFO
:
4658 this must be *exactly* right for ACLs on mapped drives to work
4660 len
= srvstr_push(dstart
, flags2
,
4662 PTR_DIFF(dend
, pdata
+4),
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4665 data_size
= 4 + len
;
4670 case SMB_FILE_ALLOCATION_INFORMATION
:
4671 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4672 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4674 SOFF_T(pdata
,0,allocation_size
);
4677 case SMB_FILE_END_OF_FILE_INFORMATION
:
4678 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4681 SOFF_T(pdata
,0,file_size
);
4684 case SMB_QUERY_FILE_ALL_INFO
:
4685 case SMB_FILE_ALL_INFORMATION
:
4688 unsigned int ea_size
=
4689 estimate_ea_size(conn
, fsp
, smb_fname
);
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4691 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4692 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4693 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4694 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4695 SIVAL(pdata
,32,mode
);
4696 SIVAL(pdata
,36,0); /* padding. */
4698 SOFF_T(pdata
,0,allocation_size
);
4699 SOFF_T(pdata
,8,file_size
);
4700 SIVAL(pdata
,16,nlink
);
4701 SCVAL(pdata
,20,delete_pending
);
4702 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4705 SIVAL(pdata
,0,ea_size
);
4706 pdata
+= 4; /* EA info */
4707 len
= srvstr_push(dstart
, flags2
,
4709 PTR_DIFF(dend
, pdata
+4),
4713 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4717 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4720 unsigned int ea_size
=
4721 estimate_ea_size(conn
, fsp
, smb_fname
);
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4723 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4724 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4725 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4726 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4727 SIVAL(pdata
, 0x20, mode
);
4728 SIVAL(pdata
, 0x24, 0); /* padding. */
4729 SBVAL(pdata
, 0x28, allocation_size
);
4730 SBVAL(pdata
, 0x30, file_size
);
4731 SIVAL(pdata
, 0x38, nlink
);
4732 SCVAL(pdata
, 0x3C, delete_pending
);
4733 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4734 SSVAL(pdata
, 0x3E, 0); /* padding */
4735 SBVAL(pdata
, 0x40, file_index
);
4736 SIVAL(pdata
, 0x48, ea_size
);
4737 SIVAL(pdata
, 0x4C, access_mask
);
4738 SBVAL(pdata
, 0x50, pos
);
4739 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4740 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4744 len
= srvstr_push(dstart
, flags2
,
4746 PTR_DIFF(dend
, pdata
+4),
4750 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4753 case SMB_FILE_INTERNAL_INFORMATION
:
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4756 SBVAL(pdata
, 0, file_index
);
4760 case SMB_FILE_ACCESS_INFORMATION
:
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4762 SIVAL(pdata
, 0, access_mask
);
4766 case SMB_FILE_NAME_INFORMATION
:
4767 /* Pathname with leading '\'. */
4770 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4772 SIVAL(pdata
,0,byte_len
);
4773 data_size
= 4 + byte_len
;
4777 case SMB_FILE_DISPOSITION_INFORMATION
:
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4780 SCVAL(pdata
,0,delete_pending
);
4783 case SMB_FILE_POSITION_INFORMATION
:
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4786 SOFF_T(pdata
,0,pos
);
4789 case SMB_FILE_MODE_INFORMATION
:
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4791 SIVAL(pdata
,0,mode
);
4795 case SMB_FILE_ALIGNMENT_INFORMATION
:
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4797 SIVAL(pdata
,0,0); /* No alignment needed. */
4802 * NT4 server just returns "invalid query" to this - if we try
4803 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4806 /* The first statement above is false - verified using Thursby
4807 * client against NT4 -- gcolley.
4809 case SMB_QUERY_FILE_STREAM_INFO
:
4810 case SMB_FILE_STREAM_INFORMATION
: {
4811 unsigned int num_streams
= 0;
4812 struct stream_struct
*streams
= NULL
;
4814 DEBUG(10,("smbd_do_qfilepathinfo: "
4815 "SMB_FILE_STREAM_INFORMATION\n"));
4817 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4818 return NT_STATUS_INVALID_PARAMETER
;
4821 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4822 talloc_tos(), &num_streams
, &streams
);
4824 if (!NT_STATUS_IS_OK(status
)) {
4825 DEBUG(10, ("could not get stream info: %s\n",
4826 nt_errstr(status
)));
4830 status
= marshall_stream_info(num_streams
, streams
,
4831 pdata
, max_data_bytes
,
4834 if (!NT_STATUS_IS_OK(status
)) {
4835 DEBUG(10, ("marshall_stream_info failed: %s\n",
4836 nt_errstr(status
)));
4837 TALLOC_FREE(streams
);
4841 TALLOC_FREE(streams
);
4845 case SMB_QUERY_COMPRESSION_INFO
:
4846 case SMB_FILE_COMPRESSION_INFORMATION
:
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4848 SOFF_T(pdata
,0,file_size
);
4849 SIVAL(pdata
,8,0); /* ??? */
4850 SIVAL(pdata
,12,0); /* ??? */
4854 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4856 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4857 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4858 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4859 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4860 SOFF_T(pdata
,32,allocation_size
);
4861 SOFF_T(pdata
,40,file_size
);
4862 SIVAL(pdata
,48,mode
);
4863 SIVAL(pdata
,52,0); /* ??? */
4867 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4868 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4869 SIVAL(pdata
,0,mode
);
4875 * CIFS UNIX Extensions.
4878 case SMB_QUERY_FILE_UNIX_BASIC
:
4880 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4881 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4883 DEBUG(4,("smbd_do_qfilepathinfo: "
4884 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4885 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4889 case SMB_QUERY_FILE_UNIX_INFO2
:
4891 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4892 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4896 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4898 for (i
=0; i
<100; i
++)
4899 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4905 case SMB_QUERY_FILE_UNIX_LINK
:
4908 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4911 return NT_STATUS_NO_MEMORY
;
4914 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4916 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4917 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4920 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4922 len
= SMB_VFS_READLINK(conn
,
4923 smb_fname
->base_name
,
4926 return map_nt_error_from_unix(errno
);
4929 len
= srvstr_push(dstart
, flags2
,
4931 PTR_DIFF(dend
, pdata
),
4934 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4939 #if defined(HAVE_POSIX_ACLS)
4940 case SMB_QUERY_POSIX_ACL
:
4942 SMB_ACL_T file_acl
= NULL
;
4943 SMB_ACL_T def_acl
= NULL
;
4944 uint16 num_file_acls
= 0;
4945 uint16 num_def_acls
= 0;
4947 if (fsp
&& fsp
->fh
->fd
!= -1) {
4948 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
4952 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4953 smb_fname
->base_name
,
4954 SMB_ACL_TYPE_ACCESS
,
4958 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4959 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4960 "not implemented on "
4961 "filesystem containing %s\n",
4962 smb_fname
->base_name
));
4963 return NT_STATUS_NOT_IMPLEMENTED
;
4966 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4967 if (fsp
&& fsp
->is_directory
) {
4969 SMB_VFS_SYS_ACL_GET_FILE(
4971 fsp
->fsp_name
->base_name
,
4972 SMB_ACL_TYPE_DEFAULT
,
4976 SMB_VFS_SYS_ACL_GET_FILE(
4978 smb_fname
->base_name
,
4979 SMB_ACL_TYPE_DEFAULT
,
4982 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4985 num_file_acls
= count_acl_entries(conn
, file_acl
);
4986 num_def_acls
= count_acl_entries(conn
, def_acl
);
4988 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4989 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4991 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4992 SMB_POSIX_ACL_HEADER_SIZE
) ));
4994 TALLOC_FREE(file_acl
);
4997 TALLOC_FREE(def_acl
);
4999 return NT_STATUS_BUFFER_TOO_SMALL
;
5002 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5003 SSVAL(pdata
,2,num_file_acls
);
5004 SSVAL(pdata
,4,num_def_acls
);
5005 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5007 TALLOC_FREE(file_acl
);
5010 TALLOC_FREE(def_acl
);
5012 return NT_STATUS_INTERNAL_ERROR
;
5014 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5016 TALLOC_FREE(file_acl
);
5019 TALLOC_FREE(def_acl
);
5021 return NT_STATUS_INTERNAL_ERROR
;
5025 TALLOC_FREE(file_acl
);
5028 TALLOC_FREE(def_acl
);
5030 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5036 case SMB_QUERY_POSIX_LOCK
:
5041 enum brl_type lock_type
;
5043 /* We need an open file with a real fd for this. */
5044 if (!fsp
|| fsp
->fh
->fd
== -1) {
5045 return NT_STATUS_INVALID_LEVEL
;
5048 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5049 return NT_STATUS_INVALID_PARAMETER
;
5052 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5053 case POSIX_LOCK_TYPE_READ
:
5054 lock_type
= READ_LOCK
;
5056 case POSIX_LOCK_TYPE_WRITE
:
5057 lock_type
= WRITE_LOCK
;
5059 case POSIX_LOCK_TYPE_UNLOCK
:
5061 /* There's no point in asking for an unlock... */
5062 return NT_STATUS_INVALID_PARAMETER
;
5065 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5066 #if defined(HAVE_LONGLONG)
5067 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5068 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5069 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5070 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5071 #else /* HAVE_LONGLONG */
5072 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5073 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5074 #endif /* HAVE_LONGLONG */
5076 status
= query_lock(fsp
,
5083 if (ERROR_WAS_LOCK_DENIED(status
)) {
5084 /* Here we need to report who has it locked... */
5085 data_size
= POSIX_LOCK_DATA_SIZE
;
5087 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5088 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5089 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5090 #if defined(HAVE_LONGLONG)
5091 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5092 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5093 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5094 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5095 #else /* HAVE_LONGLONG */
5096 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5097 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5098 #endif /* HAVE_LONGLONG */
5100 } else if (NT_STATUS_IS_OK(status
)) {
5101 /* For success we just return a copy of what we sent
5102 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5103 data_size
= POSIX_LOCK_DATA_SIZE
;
5104 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5105 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5113 return NT_STATUS_INVALID_LEVEL
;
5116 *pdata_size
= data_size
;
5117 return NT_STATUS_OK
;
5120 /****************************************************************************
5121 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5122 file name or file id).
5123 ****************************************************************************/
5125 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5126 struct smb_request
*req
,
5127 unsigned int tran_call
,
5128 char **pparams
, int total_params
,
5129 char **ppdata
, int total_data
,
5130 unsigned int max_data_bytes
)
5132 char *params
= *pparams
;
5133 char *pdata
= *ppdata
;
5135 unsigned int data_size
= 0;
5136 unsigned int param_size
= 2;
5137 struct smb_filename
*smb_fname
= NULL
;
5138 bool delete_pending
= False
;
5139 struct timespec write_time_ts
;
5140 files_struct
*fsp
= NULL
;
5141 struct file_id fileid
;
5142 struct ea_list
*ea_list
= NULL
;
5143 int lock_data_count
= 0;
5144 char *lock_data
= NULL
;
5145 NTSTATUS status
= NT_STATUS_OK
;
5148 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5152 ZERO_STRUCT(write_time_ts
);
5154 if (tran_call
== TRANSACT2_QFILEINFO
) {
5155 if (total_params
< 4) {
5156 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5161 call_trans2qpipeinfo(conn
, req
, tran_call
,
5162 pparams
, total_params
,
5168 fsp
= file_fsp(req
, SVAL(params
,0));
5169 info_level
= SVAL(params
,2);
5171 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5173 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5174 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5178 /* Initial check for valid fsp ptr. */
5179 if (!check_fsp_open(conn
, req
, fsp
)) {
5183 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5185 if (!NT_STATUS_IS_OK(status
)) {
5186 reply_nterror(req
, status
);
5190 if(fsp
->fake_file_handle
) {
5192 * This is actually for the QUOTA_FAKE_FILE --metze
5195 /* We know this name is ok, it's already passed the checks. */
5197 } else if(fsp
->fh
->fd
== -1) {
5199 * This is actually a QFILEINFO on a directory
5200 * handle (returned from an NT SMB). NT5.0 seems
5201 * to do this call. JRA.
5204 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5205 /* Always do lstat for UNIX calls. */
5206 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5207 DEBUG(3,("call_trans2qfilepathinfo: "
5208 "SMB_VFS_LSTAT of %s failed "
5210 smb_fname_str_dbg(smb_fname
),
5213 map_nt_error_from_unix(errno
));
5216 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5217 DEBUG(3,("call_trans2qfilepathinfo: "
5218 "SMB_VFS_STAT of %s failed (%s)\n",
5219 smb_fname_str_dbg(smb_fname
),
5222 map_nt_error_from_unix(errno
));
5226 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5227 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5230 * Original code - this is an open file.
5232 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5233 DEBUG(3, ("fstat of %s failed (%s)\n",
5234 fsp_fnum_dbg(fsp
), strerror(errno
)));
5236 map_nt_error_from_unix(errno
));
5239 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5240 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5246 uint32_t ucf_flags
= 0;
5249 if (total_params
< 7) {
5250 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5254 info_level
= SVAL(params
,0);
5256 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5258 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5259 if (!lp_unix_extensions()) {
5260 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5263 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5264 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5265 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5266 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5270 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5272 STR_TERMINATE
, &status
);
5273 if (!NT_STATUS_IS_OK(status
)) {
5274 reply_nterror(req
, status
);
5278 status
= filename_convert(req
,
5280 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5285 if (!NT_STATUS_IS_OK(status
)) {
5286 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5287 reply_botherror(req
,
5288 NT_STATUS_PATH_NOT_COVERED
,
5289 ERRSRV
, ERRbadpath
);
5292 reply_nterror(req
, status
);
5296 /* If this is a stream, check if there is a delete_pending. */
5297 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5298 && is_ntfs_stream_smb_fname(smb_fname
)) {
5299 struct smb_filename
*smb_fname_base
= NULL
;
5301 /* Create an smb_filename with stream_name == NULL. */
5303 create_synthetic_smb_fname(talloc_tos(),
5304 smb_fname
->base_name
,
5307 if (!NT_STATUS_IS_OK(status
)) {
5308 reply_nterror(req
, status
);
5312 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5313 /* Always do lstat for UNIX calls. */
5314 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5315 DEBUG(3,("call_trans2qfilepathinfo: "
5316 "SMB_VFS_LSTAT of %s failed "
5318 smb_fname_str_dbg(smb_fname_base
),
5320 TALLOC_FREE(smb_fname_base
);
5322 map_nt_error_from_unix(errno
));
5326 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5327 DEBUG(3,("call_trans2qfilepathinfo: "
5328 "fileinfo of %s failed "
5330 smb_fname_str_dbg(smb_fname_base
),
5332 TALLOC_FREE(smb_fname_base
);
5334 map_nt_error_from_unix(errno
));
5339 status
= file_name_hash(conn
,
5340 smb_fname_str_dbg(smb_fname_base
),
5342 if (!NT_STATUS_IS_OK(status
)) {
5343 TALLOC_FREE(smb_fname_base
);
5344 reply_nterror(req
, status
);
5348 fileid
= vfs_file_id_from_sbuf(conn
,
5349 &smb_fname_base
->st
);
5350 TALLOC_FREE(smb_fname_base
);
5351 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5352 if (delete_pending
) {
5353 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5358 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5359 /* Always do lstat for UNIX calls. */
5360 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5361 DEBUG(3,("call_trans2qfilepathinfo: "
5362 "SMB_VFS_LSTAT of %s failed (%s)\n",
5363 smb_fname_str_dbg(smb_fname
),
5366 map_nt_error_from_unix(errno
));
5371 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5372 DEBUG(3,("call_trans2qfilepathinfo: "
5373 "SMB_VFS_STAT of %s failed (%s)\n",
5374 smb_fname_str_dbg(smb_fname
),
5377 map_nt_error_from_unix(errno
));
5382 status
= file_name_hash(conn
,
5383 smb_fname_str_dbg(smb_fname
),
5385 if (!NT_STATUS_IS_OK(status
)) {
5386 reply_nterror(req
, status
);
5390 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5391 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5392 if (delete_pending
) {
5393 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5398 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5399 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5401 info_level
,tran_call
,total_data
));
5403 /* Pull out any data sent here before we realloc. */
5404 switch (info_level
) {
5405 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5407 /* Pull any EA list from the data portion. */
5410 if (total_data
< 4) {
5412 req
, NT_STATUS_INVALID_PARAMETER
);
5415 ea_size
= IVAL(pdata
,0);
5417 if (total_data
> 0 && ea_size
!= total_data
) {
5418 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5419 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5421 req
, NT_STATUS_INVALID_PARAMETER
);
5425 if (!lp_ea_support(SNUM(conn
))) {
5426 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5430 /* Pull out the list of names. */
5431 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5434 req
, NT_STATUS_INVALID_PARAMETER
);
5440 case SMB_QUERY_POSIX_LOCK
:
5442 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5443 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5447 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5449 req
, NT_STATUS_INVALID_PARAMETER
);
5453 /* Copy the lock range data. */
5454 lock_data
= (char *)talloc_memdup(
5455 req
, pdata
, total_data
);
5457 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5460 lock_data_count
= total_data
;
5466 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5467 if (*pparams
== NULL
) {
5468 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5475 * draft-leach-cifs-v1-spec-02.txt
5476 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5479 * The requested information is placed in the Data portion of the
5480 * transaction response. For the information levels greater than 0x100,
5481 * the transaction response has 1 parameter word which should be
5482 * ignored by the client.
5484 * However Windows only follows this rule for the IS_NAME_VALID call.
5486 switch (info_level
) {
5487 case SMB_INFO_IS_NAME_VALID
:
5492 if ((info_level
& 0xFF00) == 0xFF00) {
5494 * We use levels that start with 0xFF00
5495 * internally to represent SMB2 specific levels
5497 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5501 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5503 delete_pending
, write_time_ts
,
5505 lock_data_count
, lock_data
,
5506 req
->flags2
, max_data_bytes
,
5507 ppdata
, &data_size
);
5508 if (!NT_STATUS_IS_OK(status
)) {
5509 reply_nterror(req
, status
);
5513 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5519 /****************************************************************************
5520 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5522 ****************************************************************************/
5524 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5525 connection_struct
*conn
,
5526 struct smb_request
*req
,
5527 bool overwrite_if_exists
,
5528 const struct smb_filename
*smb_fname_old
,
5529 struct smb_filename
*smb_fname_new
)
5531 NTSTATUS status
= NT_STATUS_OK
;
5533 /* source must already exist. */
5534 if (!VALID_STAT(smb_fname_old
->st
)) {
5535 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5538 if (VALID_STAT(smb_fname_new
->st
)) {
5539 if (overwrite_if_exists
) {
5540 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5541 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5543 status
= unlink_internals(conn
,
5545 FILE_ATTRIBUTE_NORMAL
,
5548 if (!NT_STATUS_IS_OK(status
)) {
5552 /* Disallow if newname already exists. */
5553 return NT_STATUS_OBJECT_NAME_COLLISION
;
5557 /* No links from a directory. */
5558 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5559 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5562 /* Setting a hardlink to/from a stream isn't currently supported. */
5563 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5564 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5565 return NT_STATUS_INVALID_PARAMETER
;
5568 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5569 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5571 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5572 smb_fname_new
->base_name
) != 0) {
5573 status
= map_nt_error_from_unix(errno
);
5574 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5575 nt_errstr(status
), smb_fname_old
->base_name
,
5576 smb_fname_new
->base_name
));
5581 /****************************************************************************
5582 Deal with setting the time from any of the setfilepathinfo functions.
5583 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5584 calling this function.
5585 ****************************************************************************/
5587 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5589 const struct smb_filename
*smb_fname
,
5590 struct smb_file_time
*ft
,
5591 bool setting_write_time
)
5593 struct smb_filename smb_fname_base
;
5595 FILE_NOTIFY_CHANGE_LAST_ACCESS
5596 |FILE_NOTIFY_CHANGE_LAST_WRITE
5597 |FILE_NOTIFY_CHANGE_CREATION
;
5599 if (!VALID_STAT(smb_fname
->st
)) {
5600 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5603 /* get some defaults (no modifications) if any info is zero or -1. */
5604 if (null_timespec(ft
->create_time
)) {
5605 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5608 if (null_timespec(ft
->atime
)) {
5609 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5612 if (null_timespec(ft
->mtime
)) {
5613 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5616 if (!setting_write_time
) {
5617 /* ft->mtime comes from change time, not write time. */
5618 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5621 /* Ensure the resolution is the correct for
5622 * what we can store on this filesystem. */
5624 round_timespec(conn
->ts_res
, &ft
->create_time
);
5625 round_timespec(conn
->ts_res
, &ft
->ctime
);
5626 round_timespec(conn
->ts_res
, &ft
->atime
);
5627 round_timespec(conn
->ts_res
, &ft
->mtime
);
5629 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5630 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5631 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5632 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5633 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5634 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5635 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5636 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5638 if (setting_write_time
) {
5640 * This was a Windows setfileinfo on an open file.
5641 * NT does this a lot. We also need to
5642 * set the time here, as it can be read by
5643 * FindFirst/FindNext and with the patch for bug #2045
5644 * in smbd/fileio.c it ensures that this timestamp is
5645 * kept sticky even after a write. We save the request
5646 * away and will set it on file close and after a write. JRA.
5649 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5650 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5653 if (fsp
->base_fsp
) {
5654 set_sticky_write_time_fsp(fsp
->base_fsp
,
5657 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5660 set_sticky_write_time_path(
5661 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5666 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5668 /* Always call ntimes on the base, even if a stream was passed in. */
5669 smb_fname_base
= *smb_fname
;
5670 smb_fname_base
.stream_name
= NULL
;
5672 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5673 return map_nt_error_from_unix(errno
);
5676 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5677 smb_fname
->base_name
);
5678 return NT_STATUS_OK
;
5681 /****************************************************************************
5682 Deal with setting the dosmode from any of the setfilepathinfo functions.
5683 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5684 done before calling this function.
5685 ****************************************************************************/
5687 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5688 const struct smb_filename
*smb_fname
,
5691 struct smb_filename
*smb_fname_base
= NULL
;
5694 if (!VALID_STAT(smb_fname
->st
)) {
5695 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5698 /* Always operate on the base_name, even if a stream was passed in. */
5699 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5700 NULL
, &smb_fname
->st
,
5702 if (!NT_STATUS_IS_OK(status
)) {
5707 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5708 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5710 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5714 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5716 /* check the mode isn't different, before changing it */
5717 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5718 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5719 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5720 (unsigned int)dosmode
));
5722 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5724 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5726 smb_fname_str_dbg(smb_fname_base
),
5728 status
= map_nt_error_from_unix(errno
);
5732 status
= NT_STATUS_OK
;
5734 TALLOC_FREE(smb_fname_base
);
5738 /****************************************************************************
5739 Deal with setting the size from any of the setfilepathinfo functions.
5740 ****************************************************************************/
5742 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5743 struct smb_request
*req
,
5745 const struct smb_filename
*smb_fname
,
5746 const SMB_STRUCT_STAT
*psbuf
,
5748 bool fail_after_createfile
)
5750 NTSTATUS status
= NT_STATUS_OK
;
5751 struct smb_filename
*smb_fname_tmp
= NULL
;
5752 files_struct
*new_fsp
= NULL
;
5754 if (!VALID_STAT(*psbuf
)) {
5755 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5758 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5760 if (size
== get_file_size_stat(psbuf
)) {
5761 return NT_STATUS_OK
;
5764 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5765 smb_fname_str_dbg(smb_fname
), (double)size
));
5767 if (fsp
&& fsp
->fh
->fd
!= -1) {
5768 /* Handle based call. */
5769 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5770 return NT_STATUS_ACCESS_DENIED
;
5773 if (vfs_set_filelen(fsp
, size
) == -1) {
5774 return map_nt_error_from_unix(errno
);
5776 trigger_write_time_update_immediate(fsp
);
5777 return NT_STATUS_OK
;
5780 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5781 if (!NT_STATUS_IS_OK(status
)) {
5785 smb_fname_tmp
->st
= *psbuf
;
5787 status
= SMB_VFS_CREATE_FILE(
5790 0, /* root_dir_fid */
5791 smb_fname_tmp
, /* fname */
5792 FILE_WRITE_DATA
, /* access_mask */
5793 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5795 FILE_OPEN
, /* create_disposition*/
5796 0, /* create_options */
5797 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5798 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5799 0, /* allocation_size */
5800 0, /* private_flags */
5803 &new_fsp
, /* result */
5806 TALLOC_FREE(smb_fname_tmp
);
5808 if (!NT_STATUS_IS_OK(status
)) {
5809 /* NB. We check for open_was_deferred in the caller. */
5813 /* See RAW-SFILEINFO-END-OF-FILE */
5814 if (fail_after_createfile
) {
5815 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5816 return NT_STATUS_INVALID_LEVEL
;
5819 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5820 status
= map_nt_error_from_unix(errno
);
5821 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5825 trigger_write_time_update_immediate(new_fsp
);
5826 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5827 return NT_STATUS_OK
;
5830 /****************************************************************************
5831 Deal with SMB_INFO_SET_EA.
5832 ****************************************************************************/
5834 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5838 const struct smb_filename
*smb_fname
)
5840 struct ea_list
*ea_list
= NULL
;
5841 TALLOC_CTX
*ctx
= NULL
;
5842 NTSTATUS status
= NT_STATUS_OK
;
5844 if (total_data
< 10) {
5846 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5847 length. They seem to have no effect. Bug #3212. JRA */
5849 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5850 /* We're done. We only get EA info in this call. */
5851 return NT_STATUS_OK
;
5854 return NT_STATUS_INVALID_PARAMETER
;
5857 if (IVAL(pdata
,0) > total_data
) {
5858 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5859 IVAL(pdata
,0), (unsigned int)total_data
));
5860 return NT_STATUS_INVALID_PARAMETER
;
5864 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5866 return NT_STATUS_INVALID_PARAMETER
;
5869 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5874 /****************************************************************************
5875 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5876 ****************************************************************************/
5878 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5883 struct ea_list
*ea_list
= NULL
;
5887 return NT_STATUS_INVALID_HANDLE
;
5890 if (!lp_ea_support(SNUM(conn
))) {
5891 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5892 "EA's not supported.\n",
5893 (unsigned int)total_data
));
5894 return NT_STATUS_EAS_NOT_SUPPORTED
;
5897 if (total_data
< 10) {
5898 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5900 (unsigned int)total_data
));
5901 return NT_STATUS_INVALID_PARAMETER
;
5904 ea_list
= read_nttrans_ea_list(talloc_tos(),
5909 return NT_STATUS_INVALID_PARAMETER
;
5912 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5914 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5915 smb_fname_str_dbg(fsp
->fsp_name
),
5916 nt_errstr(status
) ));
5922 /****************************************************************************
5923 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5924 ****************************************************************************/
5926 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5930 struct smb_filename
*smb_fname
)
5932 NTSTATUS status
= NT_STATUS_OK
;
5933 bool delete_on_close
;
5936 if (total_data
< 1) {
5937 return NT_STATUS_INVALID_PARAMETER
;
5941 return NT_STATUS_INVALID_HANDLE
;
5944 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5945 dosmode
= dos_mode(conn
, smb_fname
);
5947 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5948 "delete_on_close = %u\n",
5949 smb_fname_str_dbg(smb_fname
),
5950 (unsigned int)dosmode
,
5951 (unsigned int)delete_on_close
));
5953 if (delete_on_close
) {
5954 status
= can_set_delete_on_close(fsp
, dosmode
);
5955 if (!NT_STATUS_IS_OK(status
)) {
5960 /* The set is across all open files on this dev/inode pair. */
5961 if (!set_delete_on_close(fsp
, delete_on_close
,
5962 conn
->session_info
->security_token
,
5963 conn
->session_info
->unix_token
)) {
5964 return NT_STATUS_ACCESS_DENIED
;
5966 return NT_STATUS_OK
;
5969 /****************************************************************************
5970 Deal with SMB_FILE_POSITION_INFORMATION.
5971 ****************************************************************************/
5973 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5978 uint64_t position_information
;
5980 if (total_data
< 8) {
5981 return NT_STATUS_INVALID_PARAMETER
;
5985 /* Ignore on pathname based set. */
5986 return NT_STATUS_OK
;
5989 position_information
= (uint64_t)IVAL(pdata
,0);
5990 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5992 DEBUG(10,("smb_file_position_information: Set file position "
5993 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5994 (double)position_information
));
5995 fsp
->fh
->position_information
= position_information
;
5996 return NT_STATUS_OK
;
5999 /****************************************************************************
6000 Deal with SMB_FILE_MODE_INFORMATION.
6001 ****************************************************************************/
6003 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6009 if (total_data
< 4) {
6010 return NT_STATUS_INVALID_PARAMETER
;
6012 mode
= IVAL(pdata
,0);
6013 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6014 return NT_STATUS_INVALID_PARAMETER
;
6016 return NT_STATUS_OK
;
6019 /****************************************************************************
6020 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6021 ****************************************************************************/
6023 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6024 struct smb_request
*req
,
6027 const struct smb_filename
*smb_fname
)
6029 char *link_target
= NULL
;
6030 const char *newname
= smb_fname
->base_name
;
6031 TALLOC_CTX
*ctx
= talloc_tos();
6033 /* Set a symbolic link. */
6034 /* Don't allow this if follow links is false. */
6036 if (total_data
== 0) {
6037 return NT_STATUS_INVALID_PARAMETER
;
6040 if (!lp_symlinks(SNUM(conn
))) {
6041 return NT_STATUS_ACCESS_DENIED
;
6044 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6045 total_data
, STR_TERMINATE
);
6048 return NT_STATUS_INVALID_PARAMETER
;
6051 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6052 newname
, link_target
));
6054 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6055 return map_nt_error_from_unix(errno
);
6058 return NT_STATUS_OK
;
6061 /****************************************************************************
6062 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6063 ****************************************************************************/
6065 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6066 struct smb_request
*req
,
6067 const char *pdata
, int total_data
,
6068 struct smb_filename
*smb_fname_new
)
6070 char *oldname
= NULL
;
6071 struct smb_filename
*smb_fname_old
= NULL
;
6072 TALLOC_CTX
*ctx
= talloc_tos();
6073 NTSTATUS status
= NT_STATUS_OK
;
6075 /* Set a hard link. */
6076 if (total_data
== 0) {
6077 return NT_STATUS_INVALID_PARAMETER
;
6080 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6081 total_data
, STR_TERMINATE
, &status
);
6082 if (!NT_STATUS_IS_OK(status
)) {
6086 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6087 smb_fname_str_dbg(smb_fname_new
), oldname
));
6089 status
= filename_convert(ctx
,
6091 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6096 if (!NT_STATUS_IS_OK(status
)) {
6100 return hardlink_internals(ctx
, conn
, req
, false,
6101 smb_fname_old
, smb_fname_new
);
6104 /****************************************************************************
6105 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6106 ****************************************************************************/
6108 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6109 struct smb_request
*req
,
6113 struct smb_filename
*smb_fname_src
)
6117 char *newname
= NULL
;
6118 struct smb_filename
*smb_fname_dst
= NULL
;
6119 NTSTATUS status
= NT_STATUS_OK
;
6120 TALLOC_CTX
*ctx
= talloc_tos();
6123 return NT_STATUS_INVALID_HANDLE
;
6126 if (total_data
< 20) {
6127 return NT_STATUS_INVALID_PARAMETER
;
6130 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6131 len
= IVAL(pdata
,16);
6133 if (len
> (total_data
- 20) || (len
== 0)) {
6134 return NT_STATUS_INVALID_PARAMETER
;
6137 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6138 &pdata
[20], len
, STR_TERMINATE
,
6140 if (!NT_STATUS_IS_OK(status
)) {
6144 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6147 status
= filename_convert(ctx
,
6149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6154 if (!NT_STATUS_IS_OK(status
)) {
6158 if (fsp
->base_fsp
) {
6159 /* newname must be a stream name. */
6160 if (newname
[0] != ':') {
6161 return NT_STATUS_NOT_SUPPORTED
;
6164 /* Create an smb_fname to call rename_internals_fsp() with. */
6165 status
= create_synthetic_smb_fname(talloc_tos(),
6166 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6168 if (!NT_STATUS_IS_OK(status
)) {
6173 * Set the original last component, since
6174 * rename_internals_fsp() requires it.
6176 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6178 if (smb_fname_dst
->original_lcomp
== NULL
) {
6179 status
= NT_STATUS_NO_MEMORY
;
6185 DEBUG(10,("smb2_file_rename_information: "
6186 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6187 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6188 smb_fname_str_dbg(smb_fname_dst
)));
6189 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6190 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6194 TALLOC_FREE(smb_fname_dst
);
6198 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6199 struct smb_request
*req
,
6203 struct smb_filename
*smb_fname_src
)
6207 char *newname
= NULL
;
6208 struct smb_filename
*smb_fname_dst
= NULL
;
6209 NTSTATUS status
= NT_STATUS_OK
;
6210 TALLOC_CTX
*ctx
= talloc_tos();
6213 return NT_STATUS_INVALID_HANDLE
;
6216 if (total_data
< 20) {
6217 return NT_STATUS_INVALID_PARAMETER
;
6220 overwrite
= (CVAL(pdata
,0) ? true : false);
6221 len
= IVAL(pdata
,16);
6223 if (len
> (total_data
- 20) || (len
== 0)) {
6224 return NT_STATUS_INVALID_PARAMETER
;
6227 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6228 &pdata
[20], len
, STR_TERMINATE
,
6230 if (!NT_STATUS_IS_OK(status
)) {
6234 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6237 status
= filename_convert(ctx
,
6239 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6244 if (!NT_STATUS_IS_OK(status
)) {
6248 if (fsp
->base_fsp
) {
6249 /* No stream names. */
6250 return NT_STATUS_NOT_SUPPORTED
;
6253 DEBUG(10,("smb_file_link_information: "
6254 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6255 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6256 smb_fname_str_dbg(smb_fname_dst
)));
6257 status
= hardlink_internals(ctx
,
6264 TALLOC_FREE(smb_fname_dst
);
6268 /****************************************************************************
6269 Deal with SMB_FILE_RENAME_INFORMATION.
6270 ****************************************************************************/
6272 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6273 struct smb_request
*req
,
6277 struct smb_filename
*smb_fname_src
)
6282 char *newname
= NULL
;
6283 struct smb_filename
*smb_fname_dst
= NULL
;
6284 bool dest_has_wcard
= False
;
6285 NTSTATUS status
= NT_STATUS_OK
;
6287 TALLOC_CTX
*ctx
= talloc_tos();
6289 if (total_data
< 13) {
6290 return NT_STATUS_INVALID_PARAMETER
;
6293 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6294 root_fid
= IVAL(pdata
,4);
6295 len
= IVAL(pdata
,8);
6297 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6298 return NT_STATUS_INVALID_PARAMETER
;
6301 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6304 if (!NT_STATUS_IS_OK(status
)) {
6308 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6311 status
= resolve_dfspath_wcard(ctx
, conn
,
6312 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6315 !conn
->sconn
->using_smb2
,
6318 if (!NT_STATUS_IS_OK(status
)) {
6322 /* Check the new name has no '/' characters. */
6323 if (strchr_m(newname
, '/')) {
6324 return NT_STATUS_NOT_SUPPORTED
;
6327 if (fsp
&& fsp
->base_fsp
) {
6328 /* newname must be a stream name. */
6329 if (newname
[0] != ':') {
6330 return NT_STATUS_NOT_SUPPORTED
;
6333 /* Create an smb_fname to call rename_internals_fsp() with. */
6334 status
= create_synthetic_smb_fname(talloc_tos(),
6335 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6337 if (!NT_STATUS_IS_OK(status
)) {
6342 * Set the original last component, since
6343 * rename_internals_fsp() requires it.
6345 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6347 if (smb_fname_dst
->original_lcomp
== NULL
) {
6348 status
= NT_STATUS_NO_MEMORY
;
6354 * Build up an smb_fname_dst based on the filename passed in.
6355 * We basically just strip off the last component, and put on
6356 * the newname instead.
6358 char *base_name
= NULL
;
6360 /* newname must *not* be a stream name. */
6361 if (newname
[0] == ':') {
6362 return NT_STATUS_NOT_SUPPORTED
;
6366 * Strip off the last component (filename) of the path passed
6369 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6371 return NT_STATUS_NO_MEMORY
;
6373 p
= strrchr_m(base_name
, '/');
6377 base_name
= talloc_strdup(ctx
, "");
6379 return NT_STATUS_NO_MEMORY
;
6382 /* Append the new name. */
6383 base_name
= talloc_asprintf_append(base_name
,
6387 return NT_STATUS_NO_MEMORY
;
6390 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6393 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6396 /* If an error we expect this to be
6397 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6399 if (!NT_STATUS_IS_OK(status
)) {
6400 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6404 /* Create an smb_fname to call rename_internals_fsp() */
6405 status
= create_synthetic_smb_fname(ctx
,
6409 if (!NT_STATUS_IS_OK(status
)) {
6416 DEBUG(10,("smb_file_rename_information: "
6417 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6418 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6419 smb_fname_str_dbg(smb_fname_dst
)));
6420 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6423 DEBUG(10,("smb_file_rename_information: "
6424 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6425 smb_fname_str_dbg(smb_fname_src
),
6426 smb_fname_str_dbg(smb_fname_dst
)));
6427 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6428 smb_fname_dst
, 0, overwrite
, false,
6430 FILE_WRITE_ATTRIBUTES
);
6433 TALLOC_FREE(smb_fname_dst
);
6437 /****************************************************************************
6438 Deal with SMB_SET_POSIX_ACL.
6439 ****************************************************************************/
6441 #if defined(HAVE_POSIX_ACLS)
6442 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6446 const struct smb_filename
*smb_fname
)
6448 uint16 posix_acl_version
;
6449 uint16 num_file_acls
;
6450 uint16 num_def_acls
;
6451 bool valid_file_acls
= True
;
6452 bool valid_def_acls
= True
;
6454 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6455 return NT_STATUS_INVALID_PARAMETER
;
6457 posix_acl_version
= SVAL(pdata
,0);
6458 num_file_acls
= SVAL(pdata
,2);
6459 num_def_acls
= SVAL(pdata
,4);
6461 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6462 valid_file_acls
= False
;
6466 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6467 valid_def_acls
= False
;
6471 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6472 return NT_STATUS_INVALID_PARAMETER
;
6475 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6476 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6477 return NT_STATUS_INVALID_PARAMETER
;
6480 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6481 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6482 (unsigned int)num_file_acls
,
6483 (unsigned int)num_def_acls
));
6485 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6486 smb_fname
->base_name
, num_file_acls
,
6487 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6488 return map_nt_error_from_unix(errno
);
6491 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6492 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6493 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6494 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6495 return map_nt_error_from_unix(errno
);
6497 return NT_STATUS_OK
;
6501 /****************************************************************************
6502 Deal with SMB_SET_POSIX_LOCK.
6503 ****************************************************************************/
6505 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6506 struct smb_request
*req
,
6514 bool blocking_lock
= False
;
6515 enum brl_type lock_type
;
6517 NTSTATUS status
= NT_STATUS_OK
;
6519 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6520 return NT_STATUS_INVALID_HANDLE
;
6523 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6524 return NT_STATUS_INVALID_PARAMETER
;
6527 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6528 case POSIX_LOCK_TYPE_READ
:
6529 lock_type
= READ_LOCK
;
6531 case POSIX_LOCK_TYPE_WRITE
:
6532 /* Return the right POSIX-mappable error code for files opened read-only. */
6533 if (!fsp
->can_write
) {
6534 return NT_STATUS_INVALID_HANDLE
;
6536 lock_type
= WRITE_LOCK
;
6538 case POSIX_LOCK_TYPE_UNLOCK
:
6539 lock_type
= UNLOCK_LOCK
;
6542 return NT_STATUS_INVALID_PARAMETER
;
6545 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6546 blocking_lock
= False
;
6547 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6548 blocking_lock
= True
;
6550 return NT_STATUS_INVALID_PARAMETER
;
6553 if (!lp_blocking_locks(SNUM(conn
))) {
6554 blocking_lock
= False
;
6557 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6558 #if defined(HAVE_LONGLONG)
6559 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6560 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6561 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6562 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6563 #else /* HAVE_LONGLONG */
6564 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6565 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6566 #endif /* HAVE_LONGLONG */
6568 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6569 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6571 (unsigned int)lock_type
,
6572 (unsigned long long)smblctx
,
6576 if (lock_type
== UNLOCK_LOCK
) {
6577 status
= do_unlock(req
->sconn
->msg_ctx
,
6584 uint64_t block_smblctx
;
6586 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6598 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6600 * A blocking lock was requested. Package up
6601 * this smb into a queued request and push it
6602 * onto the blocking lock queue.
6604 if(push_blocking_lock_request(br_lck
,
6607 -1, /* infinite timeout. */
6615 TALLOC_FREE(br_lck
);
6619 TALLOC_FREE(br_lck
);
6625 /****************************************************************************
6626 Deal with SMB_SET_FILE_BASIC_INFO.
6627 ****************************************************************************/
6629 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6633 const struct smb_filename
*smb_fname
)
6635 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6636 struct smb_file_time ft
;
6638 NTSTATUS status
= NT_STATUS_OK
;
6642 if (total_data
< 36) {
6643 return NT_STATUS_INVALID_PARAMETER
;
6646 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6647 if (!NT_STATUS_IS_OK(status
)) {
6651 /* Set the attributes */
6652 dosmode
= IVAL(pdata
,32);
6653 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6654 if (!NT_STATUS_IS_OK(status
)) {
6659 ft
.create_time
= interpret_long_date(pdata
);
6662 ft
.atime
= interpret_long_date(pdata
+8);
6665 ft
.mtime
= interpret_long_date(pdata
+16);
6668 ft
.ctime
= interpret_long_date(pdata
+24);
6670 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6671 smb_fname_str_dbg(smb_fname
)));
6673 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6677 /****************************************************************************
6678 Deal with SMB_INFO_STANDARD.
6679 ****************************************************************************/
6681 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6685 const struct smb_filename
*smb_fname
)
6688 struct smb_file_time ft
;
6692 if (total_data
< 12) {
6693 return NT_STATUS_INVALID_PARAMETER
;
6697 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6699 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6701 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6703 DEBUG(10,("smb_set_info_standard: file %s\n",
6704 smb_fname_str_dbg(smb_fname
)));
6706 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6707 if (!NT_STATUS_IS_OK(status
)) {
6711 return smb_set_file_time(conn
,
6718 /****************************************************************************
6719 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6720 ****************************************************************************/
6722 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6723 struct smb_request
*req
,
6727 struct smb_filename
*smb_fname
)
6729 uint64_t allocation_size
= 0;
6730 NTSTATUS status
= NT_STATUS_OK
;
6731 files_struct
*new_fsp
= NULL
;
6733 if (!VALID_STAT(smb_fname
->st
)) {
6734 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6737 if (total_data
< 8) {
6738 return NT_STATUS_INVALID_PARAMETER
;
6741 allocation_size
= (uint64_t)IVAL(pdata
,0);
6742 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6743 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6744 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6745 (double)allocation_size
));
6747 if (allocation_size
) {
6748 allocation_size
= smb_roundup(conn
, allocation_size
);
6751 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6752 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6753 (double)allocation_size
));
6755 if (fsp
&& fsp
->fh
->fd
!= -1) {
6756 /* Open file handle. */
6757 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6758 return NT_STATUS_ACCESS_DENIED
;
6761 /* Only change if needed. */
6762 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6763 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6764 return map_nt_error_from_unix(errno
);
6767 /* But always update the time. */
6769 * This is equivalent to a write. Ensure it's seen immediately
6770 * if there are no pending writes.
6772 trigger_write_time_update_immediate(fsp
);
6773 return NT_STATUS_OK
;
6776 /* Pathname or stat or directory file. */
6777 status
= SMB_VFS_CREATE_FILE(
6780 0, /* root_dir_fid */
6781 smb_fname
, /* fname */
6782 FILE_WRITE_DATA
, /* access_mask */
6783 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6785 FILE_OPEN
, /* create_disposition*/
6786 0, /* create_options */
6787 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6788 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6789 0, /* allocation_size */
6790 0, /* private_flags */
6793 &new_fsp
, /* result */
6796 if (!NT_STATUS_IS_OK(status
)) {
6797 /* NB. We check for open_was_deferred in the caller. */
6801 /* Only change if needed. */
6802 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6803 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6804 status
= map_nt_error_from_unix(errno
);
6805 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6810 /* Changing the allocation size should set the last mod time. */
6812 * This is equivalent to a write. Ensure it's seen immediately
6813 * if there are no pending writes.
6815 trigger_write_time_update_immediate(new_fsp
);
6817 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6818 return NT_STATUS_OK
;
6821 /****************************************************************************
6822 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6823 ****************************************************************************/
6825 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6826 struct smb_request
*req
,
6830 const struct smb_filename
*smb_fname
,
6831 bool fail_after_createfile
)
6835 if (total_data
< 8) {
6836 return NT_STATUS_INVALID_PARAMETER
;
6839 size
= IVAL(pdata
,0);
6840 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6841 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6842 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6845 return smb_set_file_size(conn
, req
,
6850 fail_after_createfile
);
6853 /****************************************************************************
6854 Allow a UNIX info mknod.
6855 ****************************************************************************/
6857 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6860 const struct smb_filename
*smb_fname
)
6862 uint32 file_type
= IVAL(pdata
,56);
6863 #if defined(HAVE_MAKEDEV)
6864 uint32 dev_major
= IVAL(pdata
,60);
6865 uint32 dev_minor
= IVAL(pdata
,68);
6867 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6868 uint32 raw_unixmode
= IVAL(pdata
,84);
6872 if (total_data
< 100) {
6873 return NT_STATUS_INVALID_PARAMETER
;
6876 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6877 PERM_NEW_FILE
, &unixmode
);
6878 if (!NT_STATUS_IS_OK(status
)) {
6882 #if defined(HAVE_MAKEDEV)
6883 dev
= makedev(dev_major
, dev_minor
);
6886 switch (file_type
) {
6887 #if defined(S_IFIFO)
6888 case UNIX_TYPE_FIFO
:
6889 unixmode
|= S_IFIFO
;
6892 #if defined(S_IFSOCK)
6893 case UNIX_TYPE_SOCKET
:
6894 unixmode
|= S_IFSOCK
;
6897 #if defined(S_IFCHR)
6898 case UNIX_TYPE_CHARDEV
:
6899 unixmode
|= S_IFCHR
;
6902 #if defined(S_IFBLK)
6903 case UNIX_TYPE_BLKDEV
:
6904 unixmode
|= S_IFBLK
;
6908 return NT_STATUS_INVALID_PARAMETER
;
6911 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6912 "%.0f mode 0%o for file %s\n", (double)dev
,
6913 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6915 /* Ok - do the mknod. */
6916 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6917 return map_nt_error_from_unix(errno
);
6920 /* If any of the other "set" calls fail we
6921 * don't want to end up with a half-constructed mknod.
6924 if (lp_inherit_perms(SNUM(conn
))) {
6926 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6928 return NT_STATUS_NO_MEMORY
;
6930 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6932 TALLOC_FREE(parent
);
6935 return NT_STATUS_OK
;
6938 /****************************************************************************
6939 Deal with SMB_SET_FILE_UNIX_BASIC.
6940 ****************************************************************************/
6942 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6943 struct smb_request
*req
,
6947 const struct smb_filename
*smb_fname
)
6949 struct smb_file_time ft
;
6950 uint32 raw_unixmode
;
6953 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6954 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6955 NTSTATUS status
= NT_STATUS_OK
;
6956 bool delete_on_fail
= False
;
6957 enum perm_type ptype
;
6958 files_struct
*all_fsps
= NULL
;
6959 bool modify_mtime
= true;
6961 struct smb_filename
*smb_fname_tmp
= NULL
;
6962 SMB_STRUCT_STAT sbuf
;
6966 if (total_data
< 100) {
6967 return NT_STATUS_INVALID_PARAMETER
;
6970 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6971 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6972 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6973 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6976 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6977 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6978 set_owner
= (uid_t
)IVAL(pdata
,40);
6979 set_grp
= (gid_t
)IVAL(pdata
,48);
6980 raw_unixmode
= IVAL(pdata
,84);
6982 if (VALID_STAT(smb_fname
->st
)) {
6983 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6984 ptype
= PERM_EXISTING_DIR
;
6986 ptype
= PERM_EXISTING_FILE
;
6989 ptype
= PERM_NEW_FILE
;
6992 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6994 if (!NT_STATUS_IS_OK(status
)) {
6998 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6999 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7000 smb_fname_str_dbg(smb_fname
), (double)size
,
7001 (unsigned int)set_owner
, (unsigned int)set_grp
,
7002 (int)raw_unixmode
));
7004 sbuf
= smb_fname
->st
;
7006 if (!VALID_STAT(sbuf
)) {
7008 * The only valid use of this is to create character and block
7009 * devices, and named pipes. This is deprecated (IMHO) and
7010 * a new info level should be used for mknod. JRA.
7013 status
= smb_unix_mknod(conn
,
7017 if (!NT_STATUS_IS_OK(status
)) {
7021 status
= copy_smb_filename(talloc_tos(), smb_fname
,
7023 if (!NT_STATUS_IS_OK(status
)) {
7027 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7028 status
= map_nt_error_from_unix(errno
);
7029 TALLOC_FREE(smb_fname_tmp
);
7030 SMB_VFS_UNLINK(conn
, smb_fname
);
7034 sbuf
= smb_fname_tmp
->st
;
7035 smb_fname
= smb_fname_tmp
;
7037 /* Ensure we don't try and change anything else. */
7038 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7039 size
= get_file_size_stat(&sbuf
);
7040 ft
.atime
= sbuf
.st_ex_atime
;
7041 ft
.mtime
= sbuf
.st_ex_mtime
;
7043 * We continue here as we might want to change the
7046 delete_on_fail
= True
;
7050 /* Horrible backwards compatibility hack as an old server bug
7051 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7055 size
= get_file_size_stat(&sbuf
);
7060 * Deal with the UNIX specific mode set.
7063 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7064 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7065 "setting mode 0%o for file %s\n",
7066 (unsigned int)unixmode
,
7067 smb_fname_str_dbg(smb_fname
)));
7068 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7069 return map_nt_error_from_unix(errno
);
7074 * Deal with the UNIX specific uid set.
7077 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7078 (sbuf
.st_ex_uid
!= set_owner
)) {
7081 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7082 "changing owner %u for path %s\n",
7083 (unsigned int)set_owner
,
7084 smb_fname_str_dbg(smb_fname
)));
7086 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7087 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7088 set_owner
, (gid_t
)-1);
7090 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7091 set_owner
, (gid_t
)-1);
7095 status
= map_nt_error_from_unix(errno
);
7096 if (delete_on_fail
) {
7097 SMB_VFS_UNLINK(conn
, smb_fname
);
7104 * Deal with the UNIX specific gid set.
7107 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7108 (sbuf
.st_ex_gid
!= set_grp
)) {
7109 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7110 "changing group %u for file %s\n",
7111 (unsigned int)set_owner
,
7112 smb_fname_str_dbg(smb_fname
)));
7113 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7115 status
= map_nt_error_from_unix(errno
);
7116 if (delete_on_fail
) {
7117 SMB_VFS_UNLINK(conn
, smb_fname
);
7123 /* Deal with any size changes. */
7125 status
= smb_set_file_size(conn
, req
,
7131 if (!NT_STATUS_IS_OK(status
)) {
7135 /* Deal with any time changes. */
7136 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7137 /* No change, don't cancel anything. */
7141 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7142 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7143 all_fsps
= file_find_di_next(all_fsps
)) {
7145 * We're setting the time explicitly for UNIX.
7146 * Cancel any pending changes over all handles.
7148 all_fsps
->update_write_time_on_close
= false;
7149 TALLOC_FREE(all_fsps
->update_write_time_event
);
7153 * Override the "setting_write_time"
7154 * parameter here as it almost does what
7155 * we need. Just remember if we modified
7156 * mtime and send the notify ourselves.
7158 if (null_timespec(ft
.mtime
)) {
7159 modify_mtime
= false;
7162 status
= smb_set_file_time(conn
,
7168 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7169 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7174 /****************************************************************************
7175 Deal with SMB_SET_FILE_UNIX_INFO2.
7176 ****************************************************************************/
7178 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7179 struct smb_request
*req
,
7183 const struct smb_filename
*smb_fname
)
7189 if (total_data
< 116) {
7190 return NT_STATUS_INVALID_PARAMETER
;
7193 /* Start by setting all the fields that are common between UNIX_BASIC
7196 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7198 if (!NT_STATUS_IS_OK(status
)) {
7202 smb_fflags
= IVAL(pdata
, 108);
7203 smb_fmask
= IVAL(pdata
, 112);
7205 /* NB: We should only attempt to alter the file flags if the client
7206 * sends a non-zero mask.
7208 if (smb_fmask
!= 0) {
7209 int stat_fflags
= 0;
7211 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7212 smb_fmask
, &stat_fflags
)) {
7213 /* Client asked to alter a flag we don't understand. */
7214 return NT_STATUS_INVALID_PARAMETER
;
7217 if (fsp
&& fsp
->fh
->fd
!= -1) {
7218 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7219 return NT_STATUS_NOT_SUPPORTED
;
7221 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7222 stat_fflags
) != 0) {
7223 return map_nt_error_from_unix(errno
);
7228 /* XXX: need to add support for changing the create_time here. You
7229 * can do this for paths on Darwin with setattrlist(2). The right way
7230 * to hook this up is probably by extending the VFS utimes interface.
7233 return NT_STATUS_OK
;
7236 /****************************************************************************
7237 Create a directory with POSIX semantics.
7238 ****************************************************************************/
7240 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7241 struct smb_request
*req
,
7244 struct smb_filename
*smb_fname
,
7245 int *pdata_return_size
)
7247 NTSTATUS status
= NT_STATUS_OK
;
7248 uint32 raw_unixmode
= 0;
7249 uint32 mod_unixmode
= 0;
7250 mode_t unixmode
= (mode_t
)0;
7251 files_struct
*fsp
= NULL
;
7252 uint16 info_level_return
= 0;
7254 char *pdata
= *ppdata
;
7256 if (total_data
< 18) {
7257 return NT_STATUS_INVALID_PARAMETER
;
7260 raw_unixmode
= IVAL(pdata
,8);
7261 /* Next 4 bytes are not yet defined. */
7263 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7264 PERM_NEW_DIR
, &unixmode
);
7265 if (!NT_STATUS_IS_OK(status
)) {
7269 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7271 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7272 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7274 status
= SMB_VFS_CREATE_FILE(
7277 0, /* root_dir_fid */
7278 smb_fname
, /* fname */
7279 FILE_READ_ATTRIBUTES
, /* access_mask */
7280 FILE_SHARE_NONE
, /* share_access */
7281 FILE_CREATE
, /* create_disposition*/
7282 FILE_DIRECTORY_FILE
, /* create_options */
7283 mod_unixmode
, /* file_attributes */
7284 0, /* oplock_request */
7285 0, /* allocation_size */
7286 0, /* private_flags */
7292 if (NT_STATUS_IS_OK(status
)) {
7293 close_file(req
, fsp
, NORMAL_CLOSE
);
7296 info_level_return
= SVAL(pdata
,16);
7298 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7299 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7300 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7301 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7303 *pdata_return_size
= 12;
7306 /* Realloc the data size */
7307 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7308 if (*ppdata
== NULL
) {
7309 *pdata_return_size
= 0;
7310 return NT_STATUS_NO_MEMORY
;
7314 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7315 SSVAL(pdata
,2,0); /* No fnum. */
7316 SIVAL(pdata
,4,info
); /* Was directory created. */
7318 switch (info_level_return
) {
7319 case SMB_QUERY_FILE_UNIX_BASIC
:
7320 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7321 SSVAL(pdata
,10,0); /* Padding. */
7322 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7325 case SMB_QUERY_FILE_UNIX_INFO2
:
7326 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7327 SSVAL(pdata
,10,0); /* Padding. */
7328 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7332 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7333 SSVAL(pdata
,10,0); /* Padding. */
7340 /****************************************************************************
7341 Open/Create a file with POSIX semantics.
7342 ****************************************************************************/
7344 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7345 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7347 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7348 struct smb_request
*req
,
7351 struct smb_filename
*smb_fname
,
7352 int *pdata_return_size
)
7354 bool extended_oplock_granted
= False
;
7355 char *pdata
= *ppdata
;
7357 uint32 wire_open_mode
= 0;
7358 uint32 raw_unixmode
= 0;
7359 uint32 mod_unixmode
= 0;
7360 uint32 create_disp
= 0;
7361 uint32 access_mask
= 0;
7362 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7363 NTSTATUS status
= NT_STATUS_OK
;
7364 mode_t unixmode
= (mode_t
)0;
7365 files_struct
*fsp
= NULL
;
7366 int oplock_request
= 0;
7368 uint16 info_level_return
= 0;
7370 if (total_data
< 18) {
7371 return NT_STATUS_INVALID_PARAMETER
;
7374 flags
= IVAL(pdata
,0);
7375 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7376 if (oplock_request
) {
7377 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7380 wire_open_mode
= IVAL(pdata
,4);
7382 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7383 return smb_posix_mkdir(conn
, req
,
7390 switch (wire_open_mode
& SMB_ACCMODE
) {
7392 access_mask
= SMB_O_RDONLY_MAPPING
;
7395 access_mask
= SMB_O_WRONLY_MAPPING
;
7398 access_mask
= (SMB_O_RDONLY_MAPPING
|
7399 SMB_O_WRONLY_MAPPING
);
7402 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7403 (unsigned int)wire_open_mode
));
7404 return NT_STATUS_INVALID_PARAMETER
;
7407 wire_open_mode
&= ~SMB_ACCMODE
;
7409 /* First take care of O_CREAT|O_EXCL interactions. */
7410 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7411 case (SMB_O_CREAT
| SMB_O_EXCL
):
7412 /* File exists fail. File not exist create. */
7413 create_disp
= FILE_CREATE
;
7416 /* File exists open. File not exist create. */
7417 create_disp
= FILE_OPEN_IF
;
7420 /* O_EXCL on its own without O_CREAT is undefined.
7421 We deliberately ignore it as some versions of
7422 Linux CIFSFS can send a bare O_EXCL on the
7423 wire which other filesystems in the kernel
7424 ignore. See bug 9519 for details. */
7429 /* File exists open. File not exist fail. */
7430 create_disp
= FILE_OPEN
;
7433 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7434 (unsigned int)wire_open_mode
));
7435 return NT_STATUS_INVALID_PARAMETER
;
7438 /* Next factor in the effects of O_TRUNC. */
7439 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7441 if (wire_open_mode
& SMB_O_TRUNC
) {
7442 switch (create_disp
) {
7444 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7445 /* Leave create_disp alone as
7446 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7448 /* File exists fail. File not exist create. */
7451 /* SMB_O_CREAT | SMB_O_TRUNC */
7452 /* File exists overwrite. File not exist create. */
7453 create_disp
= FILE_OVERWRITE_IF
;
7457 /* File exists overwrite. File not exist fail. */
7458 create_disp
= FILE_OVERWRITE
;
7461 /* Cannot get here. */
7462 smb_panic("smb_posix_open: logic error");
7463 return NT_STATUS_INVALID_PARAMETER
;
7467 raw_unixmode
= IVAL(pdata
,8);
7468 /* Next 4 bytes are not yet defined. */
7470 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7471 (VALID_STAT(smb_fname
->st
) ?
7472 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7475 if (!NT_STATUS_IS_OK(status
)) {
7479 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7481 if (wire_open_mode
& SMB_O_SYNC
) {
7482 create_options
|= FILE_WRITE_THROUGH
;
7484 if (wire_open_mode
& SMB_O_APPEND
) {
7485 access_mask
|= FILE_APPEND_DATA
;
7487 if (wire_open_mode
& SMB_O_DIRECT
) {
7488 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7491 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7492 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7493 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7494 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7496 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7497 create_options
|= FILE_DIRECTORY_FILE
;
7500 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7501 smb_fname_str_dbg(smb_fname
),
7502 (unsigned int)wire_open_mode
,
7503 (unsigned int)unixmode
));
7505 status
= SMB_VFS_CREATE_FILE(
7508 0, /* root_dir_fid */
7509 smb_fname
, /* fname */
7510 access_mask
, /* access_mask */
7511 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7513 create_disp
, /* create_disposition*/
7514 create_options
, /* create_options */
7515 mod_unixmode
, /* file_attributes */
7516 oplock_request
, /* oplock_request */
7517 0, /* allocation_size */
7518 0, /* private_flags */
7524 if (!NT_STATUS_IS_OK(status
)) {
7528 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7529 extended_oplock_granted
= True
;
7532 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7533 extended_oplock_granted
= True
;
7536 info_level_return
= SVAL(pdata
,16);
7538 /* Allocate the correct return size. */
7540 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7541 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7542 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7543 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7545 *pdata_return_size
= 12;
7548 /* Realloc the data size */
7549 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7550 if (*ppdata
== NULL
) {
7551 close_file(req
, fsp
, ERROR_CLOSE
);
7552 *pdata_return_size
= 0;
7553 return NT_STATUS_NO_MEMORY
;
7557 if (extended_oplock_granted
) {
7558 if (flags
& REQUEST_BATCH_OPLOCK
) {
7559 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7561 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7563 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7564 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7566 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7569 SSVAL(pdata
,2,fsp
->fnum
);
7570 SIVAL(pdata
,4,info
); /* Was file created etc. */
7572 switch (info_level_return
) {
7573 case SMB_QUERY_FILE_UNIX_BASIC
:
7574 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7575 SSVAL(pdata
,10,0); /* padding. */
7576 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7579 case SMB_QUERY_FILE_UNIX_INFO2
:
7580 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7581 SSVAL(pdata
,10,0); /* padding. */
7582 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7586 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7587 SSVAL(pdata
,10,0); /* padding. */
7590 return NT_STATUS_OK
;
7593 /****************************************************************************
7594 Delete a file with POSIX semantics.
7595 ****************************************************************************/
7597 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7598 struct smb_request
*req
,
7601 struct smb_filename
*smb_fname
)
7603 NTSTATUS status
= NT_STATUS_OK
;
7604 files_struct
*fsp
= NULL
;
7608 int create_options
= 0;
7610 struct share_mode_lock
*lck
= NULL
;
7612 if (total_data
< 2) {
7613 return NT_STATUS_INVALID_PARAMETER
;
7616 flags
= SVAL(pdata
,0);
7618 if (!VALID_STAT(smb_fname
->st
)) {
7619 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7622 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7623 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7624 return NT_STATUS_NOT_A_DIRECTORY
;
7627 DEBUG(10,("smb_posix_unlink: %s %s\n",
7628 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7629 smb_fname_str_dbg(smb_fname
)));
7631 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7632 create_options
|= FILE_DIRECTORY_FILE
;
7635 status
= SMB_VFS_CREATE_FILE(
7638 0, /* root_dir_fid */
7639 smb_fname
, /* fname */
7640 DELETE_ACCESS
, /* access_mask */
7641 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7643 FILE_OPEN
, /* create_disposition*/
7644 create_options
, /* create_options */
7645 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7646 0, /* oplock_request */
7647 0, /* allocation_size */
7648 0, /* private_flags */
7654 if (!NT_STATUS_IS_OK(status
)) {
7659 * Don't lie to client. If we can't really delete due to
7660 * non-POSIX opens return SHARING_VIOLATION.
7663 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7665 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7666 "lock for file %s\n", fsp_str_dbg(fsp
)));
7667 close_file(req
, fsp
, NORMAL_CLOSE
);
7668 return NT_STATUS_INVALID_PARAMETER
;
7672 * See if others still have the file open. If this is the case, then
7673 * don't delete. If all opens are POSIX delete we can set the delete
7674 * on close disposition.
7676 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7677 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7678 if (is_valid_share_mode_entry(e
)) {
7679 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7682 if (share_mode_stale_pid(lck
->data
, i
)) {
7685 /* Fail with sharing violation. */
7687 close_file(req
, fsp
, NORMAL_CLOSE
);
7688 return NT_STATUS_SHARING_VIOLATION
;
7693 * Set the delete on close.
7695 status
= smb_set_file_disposition_info(conn
,
7703 if (!NT_STATUS_IS_OK(status
)) {
7704 close_file(req
, fsp
, NORMAL_CLOSE
);
7707 return close_file(req
, fsp
, NORMAL_CLOSE
);
7710 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7711 struct smb_request
*req
,
7712 TALLOC_CTX
*mem_ctx
,
7713 uint16_t info_level
,
7715 struct smb_filename
*smb_fname
,
7716 char **ppdata
, int total_data
,
7719 char *pdata
= *ppdata
;
7720 NTSTATUS status
= NT_STATUS_OK
;
7721 int data_return_size
= 0;
7725 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7726 return NT_STATUS_INVALID_LEVEL
;
7729 if (!CAN_WRITE(conn
)) {
7730 /* Allow POSIX opens. The open path will deny
7731 * any non-readonly opens. */
7732 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7733 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7737 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7738 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7740 info_level
, total_data
));
7742 switch (info_level
) {
7744 case SMB_INFO_STANDARD
:
7746 status
= smb_set_info_standard(conn
,
7754 case SMB_INFO_SET_EA
:
7756 status
= smb_info_set_ea(conn
,
7764 case SMB_SET_FILE_BASIC_INFO
:
7765 case SMB_FILE_BASIC_INFORMATION
:
7767 status
= smb_set_file_basic_info(conn
,
7775 case SMB_FILE_ALLOCATION_INFORMATION
:
7776 case SMB_SET_FILE_ALLOCATION_INFO
:
7778 status
= smb_set_file_allocation_info(conn
, req
,
7786 case SMB_FILE_END_OF_FILE_INFORMATION
:
7787 case SMB_SET_FILE_END_OF_FILE_INFO
:
7790 * XP/Win7 both fail after the createfile with
7791 * SMB_SET_FILE_END_OF_FILE_INFO but not
7792 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7793 * The level is known here, so pass it down
7797 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7799 status
= smb_set_file_end_of_file_info(conn
, req
,
7808 case SMB_FILE_DISPOSITION_INFORMATION
:
7809 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7812 /* JRA - We used to just ignore this on a path ?
7813 * Shouldn't this be invalid level on a pathname
7816 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7817 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7820 status
= smb_set_file_disposition_info(conn
,
7828 case SMB_FILE_POSITION_INFORMATION
:
7830 status
= smb_file_position_information(conn
,
7837 case SMB_FILE_FULL_EA_INFORMATION
:
7839 status
= smb_set_file_full_ea_info(conn
,
7846 /* From tridge Samba4 :
7847 * MODE_INFORMATION in setfileinfo (I have no
7848 * idea what "mode information" on a file is - it takes a value of 0,
7849 * 2, 4 or 6. What could it be?).
7852 case SMB_FILE_MODE_INFORMATION
:
7854 status
= smb_file_mode_information(conn
,
7861 * CIFS UNIX extensions.
7864 case SMB_SET_FILE_UNIX_BASIC
:
7866 status
= smb_set_file_unix_basic(conn
, req
,
7874 case SMB_SET_FILE_UNIX_INFO2
:
7876 status
= smb_set_file_unix_info2(conn
, req
,
7884 case SMB_SET_FILE_UNIX_LINK
:
7887 /* We must have a pathname for this. */
7888 return NT_STATUS_INVALID_LEVEL
;
7890 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7891 total_data
, smb_fname
);
7895 case SMB_SET_FILE_UNIX_HLINK
:
7898 /* We must have a pathname for this. */
7899 return NT_STATUS_INVALID_LEVEL
;
7901 status
= smb_set_file_unix_hlink(conn
, req
,
7907 case SMB_FILE_RENAME_INFORMATION
:
7909 status
= smb_file_rename_information(conn
, req
,
7915 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7917 /* SMB2 rename information. */
7918 status
= smb2_file_rename_information(conn
, req
,
7924 case SMB_FILE_LINK_INFORMATION
:
7926 status
= smb_file_link_information(conn
, req
,
7932 #if defined(HAVE_POSIX_ACLS)
7933 case SMB_SET_POSIX_ACL
:
7935 status
= smb_set_posix_acl(conn
,
7944 case SMB_SET_POSIX_LOCK
:
7947 return NT_STATUS_INVALID_LEVEL
;
7949 status
= smb_set_posix_lock(conn
, req
,
7950 pdata
, total_data
, fsp
);
7954 case SMB_POSIX_PATH_OPEN
:
7957 /* We must have a pathname for this. */
7958 return NT_STATUS_INVALID_LEVEL
;
7961 status
= smb_posix_open(conn
, req
,
7969 case SMB_POSIX_PATH_UNLINK
:
7972 /* We must have a pathname for this. */
7973 return NT_STATUS_INVALID_LEVEL
;
7976 status
= smb_posix_unlink(conn
, req
,
7984 return NT_STATUS_INVALID_LEVEL
;
7987 if (!NT_STATUS_IS_OK(status
)) {
7991 *ret_data_size
= data_return_size
;
7992 return NT_STATUS_OK
;
7995 /****************************************************************************
7996 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7997 ****************************************************************************/
7999 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8000 struct smb_request
*req
,
8001 unsigned int tran_call
,
8002 char **pparams
, int total_params
,
8003 char **ppdata
, int total_data
,
8004 unsigned int max_data_bytes
)
8006 char *params
= *pparams
;
8007 char *pdata
= *ppdata
;
8009 struct smb_filename
*smb_fname
= NULL
;
8010 files_struct
*fsp
= NULL
;
8011 NTSTATUS status
= NT_STATUS_OK
;
8012 int data_return_size
= 0;
8015 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8019 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8020 if (total_params
< 4) {
8021 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8025 fsp
= file_fsp(req
, SVAL(params
,0));
8026 /* Basic check for non-null fsp. */
8027 if (!check_fsp_open(conn
, req
, fsp
)) {
8030 info_level
= SVAL(params
,2);
8032 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
8034 if (!NT_STATUS_IS_OK(status
)) {
8035 reply_nterror(req
, status
);
8039 if(fsp
->fh
->fd
== -1) {
8041 * This is actually a SETFILEINFO on a directory
8042 * handle (returned from an NT SMB). NT5.0 seems
8043 * to do this call. JRA.
8045 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8046 /* Always do lstat for UNIX calls. */
8047 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8048 DEBUG(3,("call_trans2setfilepathinfo: "
8049 "SMB_VFS_LSTAT of %s failed "
8051 smb_fname_str_dbg(smb_fname
),
8053 reply_nterror(req
, map_nt_error_from_unix(errno
));
8057 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8058 DEBUG(3,("call_trans2setfilepathinfo: "
8059 "fileinfo of %s failed (%s)\n",
8060 smb_fname_str_dbg(smb_fname
),
8062 reply_nterror(req
, map_nt_error_from_unix(errno
));
8066 } else if (fsp
->print_file
) {
8068 * Doing a DELETE_ON_CLOSE should cancel a print job.
8070 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8071 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8073 DEBUG(3,("call_trans2setfilepathinfo: "
8074 "Cancelling print job (%s)\n",
8078 send_trans2_replies(conn
, req
, params
, 2,
8084 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8089 * Original code - this is an open file.
8091 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8092 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8093 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8095 reply_nterror(req
, map_nt_error_from_unix(errno
));
8101 uint32_t ucf_flags
= 0;
8104 if (total_params
< 7) {
8105 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8109 info_level
= SVAL(params
,0);
8110 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8111 total_params
- 6, STR_TERMINATE
,
8113 if (!NT_STATUS_IS_OK(status
)) {
8114 reply_nterror(req
, status
);
8118 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8119 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8120 info_level
== SMB_FILE_RENAME_INFORMATION
||
8121 info_level
== SMB_POSIX_PATH_UNLINK
) {
8122 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8125 status
= filename_convert(req
, conn
,
8126 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8131 if (!NT_STATUS_IS_OK(status
)) {
8132 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8133 reply_botherror(req
,
8134 NT_STATUS_PATH_NOT_COVERED
,
8135 ERRSRV
, ERRbadpath
);
8138 reply_nterror(req
, status
);
8142 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8144 * For CIFS UNIX extensions the target name may not exist.
8147 /* Always do lstat for UNIX calls. */
8148 SMB_VFS_LSTAT(conn
, smb_fname
);
8150 } else if (!VALID_STAT(smb_fname
->st
) &&
8151 SMB_VFS_STAT(conn
, smb_fname
)) {
8152 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8154 smb_fname_str_dbg(smb_fname
),
8156 reply_nterror(req
, map_nt_error_from_unix(errno
));
8161 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8162 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8164 info_level
,total_data
));
8166 /* Realloc the parameter size */
8167 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8168 if (*pparams
== NULL
) {
8169 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8176 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8182 if (!NT_STATUS_IS_OK(status
)) {
8183 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8184 /* We have re-scheduled this call. */
8187 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8188 /* We have re-scheduled this call. */
8191 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8192 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8193 ERRSRV
, ERRbadpath
);
8196 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8197 reply_openerror(req
, status
);
8201 reply_nterror(req
, status
);
8205 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8211 /****************************************************************************
8212 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8213 ****************************************************************************/
8215 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8216 char **pparams
, int total_params
,
8217 char **ppdata
, int total_data
,
8218 unsigned int max_data_bytes
)
8220 struct smb_filename
*smb_dname
= NULL
;
8221 char *params
= *pparams
;
8222 char *pdata
= *ppdata
;
8223 char *directory
= NULL
;
8224 NTSTATUS status
= NT_STATUS_OK
;
8225 struct ea_list
*ea_list
= NULL
;
8226 TALLOC_CTX
*ctx
= talloc_tos();
8228 if (!CAN_WRITE(conn
)) {
8229 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8233 if (total_params
< 5) {
8234 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8238 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8239 total_params
- 4, STR_TERMINATE
,
8241 if (!NT_STATUS_IS_OK(status
)) {
8242 reply_nterror(req
, status
);
8246 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8248 status
= filename_convert(ctx
,
8250 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8256 if (!NT_STATUS_IS_OK(status
)) {
8257 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8258 reply_botherror(req
,
8259 NT_STATUS_PATH_NOT_COVERED
,
8260 ERRSRV
, ERRbadpath
);
8263 reply_nterror(req
, status
);
8268 * OS/2 workplace shell seems to send SET_EA requests of "null"
8269 * length (4 bytes containing IVAL 4).
8270 * They seem to have no effect. Bug #3212. JRA.
8273 if (total_data
&& (total_data
!= 4)) {
8274 /* Any data in this call is an EA list. */
8275 if (total_data
< 10) {
8276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8280 if (IVAL(pdata
,0) > total_data
) {
8281 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8282 IVAL(pdata
,0), (unsigned int)total_data
));
8283 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8287 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8294 if (!lp_ea_support(SNUM(conn
))) {
8295 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8299 /* If total_data == 4 Windows doesn't care what values
8300 * are placed in that field, it just ignores them.
8301 * The System i QNTC IBM SMB client puts bad values here,
8302 * so ignore them. */
8304 status
= create_directory(conn
, req
, smb_dname
);
8306 if (!NT_STATUS_IS_OK(status
)) {
8307 reply_nterror(req
, status
);
8311 /* Try and set any given EA. */
8313 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8314 if (!NT_STATUS_IS_OK(status
)) {
8315 reply_nterror(req
, status
);
8320 /* Realloc the parameter and data sizes */
8321 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8322 if(*pparams
== NULL
) {
8323 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8330 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8333 TALLOC_FREE(smb_dname
);
8337 /****************************************************************************
8338 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8339 We don't actually do this - we just send a null response.
8340 ****************************************************************************/
8342 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8343 struct smb_request
*req
,
8344 char **pparams
, int total_params
,
8345 char **ppdata
, int total_data
,
8346 unsigned int max_data_bytes
)
8348 char *params
= *pparams
;
8351 if (total_params
< 6) {
8352 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8356 info_level
= SVAL(params
,4);
8357 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8359 switch (info_level
) {
8364 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8368 /* Realloc the parameter and data sizes */
8369 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8370 if (*pparams
== NULL
) {
8371 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8376 SSVAL(params
,0,fnf_handle
);
8377 SSVAL(params
,2,0); /* No changes */
8378 SSVAL(params
,4,0); /* No EA errors */
8385 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8390 /****************************************************************************
8391 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8392 changes). Currently this does nothing.
8393 ****************************************************************************/
8395 static void call_trans2findnotifynext(connection_struct
*conn
,
8396 struct smb_request
*req
,
8397 char **pparams
, int total_params
,
8398 char **ppdata
, int total_data
,
8399 unsigned int max_data_bytes
)
8401 char *params
= *pparams
;
8403 DEBUG(3,("call_trans2findnotifynext\n"));
8405 /* Realloc the parameter and data sizes */
8406 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8407 if (*pparams
== NULL
) {
8408 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8413 SSVAL(params
,0,0); /* No changes */
8414 SSVAL(params
,2,0); /* No EA errors */
8416 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8421 /****************************************************************************
8422 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8423 ****************************************************************************/
8425 static void call_trans2getdfsreferral(connection_struct
*conn
,
8426 struct smb_request
*req
,
8427 char **pparams
, int total_params
,
8428 char **ppdata
, int total_data
,
8429 unsigned int max_data_bytes
)
8431 char *params
= *pparams
;
8432 char *pathname
= NULL
;
8434 int max_referral_level
;
8435 NTSTATUS status
= NT_STATUS_OK
;
8436 TALLOC_CTX
*ctx
= talloc_tos();
8438 DEBUG(10,("call_trans2getdfsreferral\n"));
8440 if (total_params
< 3) {
8441 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8445 max_referral_level
= SVAL(params
,0);
8447 if(!lp_host_msdfs()) {
8448 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8452 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8453 total_params
- 2, STR_TERMINATE
);
8455 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8458 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8459 ppdata
,&status
)) < 0) {
8460 reply_nterror(req
, status
);
8464 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8465 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8466 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8471 #define LMCAT_SPL 0x53
8472 #define LMFUNC_GETJOBID 0x60
8474 /****************************************************************************
8475 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8476 ****************************************************************************/
8478 static void call_trans2ioctl(connection_struct
*conn
,
8479 struct smb_request
*req
,
8480 char **pparams
, int total_params
,
8481 char **ppdata
, int total_data
,
8482 unsigned int max_data_bytes
)
8484 char *pdata
= *ppdata
;
8485 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8487 /* check for an invalid fid before proceeding */
8490 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8494 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8495 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8496 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8497 if (*ppdata
== NULL
) {
8498 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8503 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8504 CAN ACCEPT THIS IN UNICODE. JRA. */
8507 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8509 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8510 lp_netbios_name(), 15,
8511 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8512 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8513 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8514 STR_ASCII
|STR_TERMINATE
); /* Service name */
8515 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8520 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8521 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8524 /****************************************************************************
8525 Reply to a SMBfindclose (stop trans2 directory search).
8526 ****************************************************************************/
8528 void reply_findclose(struct smb_request
*req
)
8531 struct smbd_server_connection
*sconn
= req
->sconn
;
8533 START_PROFILE(SMBfindclose
);
8536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8537 END_PROFILE(SMBfindclose
);
8541 dptr_num
= SVALS(req
->vwv
+0, 0);
8543 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8545 dptr_close(sconn
, &dptr_num
);
8547 reply_outbuf(req
, 0, 0);
8549 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8551 END_PROFILE(SMBfindclose
);
8555 /****************************************************************************
8556 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8557 ****************************************************************************/
8559 void reply_findnclose(struct smb_request
*req
)
8563 START_PROFILE(SMBfindnclose
);
8566 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8567 END_PROFILE(SMBfindnclose
);
8571 dptr_num
= SVAL(req
->vwv
+0, 0);
8573 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8575 /* We never give out valid handles for a
8576 findnotifyfirst - so any dptr_num is ok here.
8579 reply_outbuf(req
, 0, 0);
8581 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8583 END_PROFILE(SMBfindnclose
);
8587 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8588 struct trans_state
*state
)
8590 if (get_Protocol() >= PROTOCOL_NT1
) {
8591 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8592 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8595 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8596 if (state
->call
!= TRANSACT2_QFSINFO
&&
8597 state
->call
!= TRANSACT2_SETFSINFO
) {
8598 DEBUG(0,("handle_trans2: encryption required "
8600 (unsigned int)state
->call
));
8601 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8606 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8608 /* Now we must call the relevant TRANS2 function */
8609 switch(state
->call
) {
8610 case TRANSACT2_OPEN
:
8612 START_PROFILE(Trans2_open
);
8613 call_trans2open(conn
, req
,
8614 &state
->param
, state
->total_param
,
8615 &state
->data
, state
->total_data
,
8616 state
->max_data_return
);
8617 END_PROFILE(Trans2_open
);
8621 case TRANSACT2_FINDFIRST
:
8623 START_PROFILE(Trans2_findfirst
);
8624 call_trans2findfirst(conn
, req
,
8625 &state
->param
, state
->total_param
,
8626 &state
->data
, state
->total_data
,
8627 state
->max_data_return
);
8628 END_PROFILE(Trans2_findfirst
);
8632 case TRANSACT2_FINDNEXT
:
8634 START_PROFILE(Trans2_findnext
);
8635 call_trans2findnext(conn
, req
,
8636 &state
->param
, state
->total_param
,
8637 &state
->data
, state
->total_data
,
8638 state
->max_data_return
);
8639 END_PROFILE(Trans2_findnext
);
8643 case TRANSACT2_QFSINFO
:
8645 START_PROFILE(Trans2_qfsinfo
);
8646 call_trans2qfsinfo(conn
, req
,
8647 &state
->param
, state
->total_param
,
8648 &state
->data
, state
->total_data
,
8649 state
->max_data_return
);
8650 END_PROFILE(Trans2_qfsinfo
);
8654 case TRANSACT2_SETFSINFO
:
8656 START_PROFILE(Trans2_setfsinfo
);
8657 call_trans2setfsinfo(conn
, req
,
8658 &state
->param
, state
->total_param
,
8659 &state
->data
, state
->total_data
,
8660 state
->max_data_return
);
8661 END_PROFILE(Trans2_setfsinfo
);
8665 case TRANSACT2_QPATHINFO
:
8666 case TRANSACT2_QFILEINFO
:
8668 START_PROFILE(Trans2_qpathinfo
);
8669 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8670 &state
->param
, state
->total_param
,
8671 &state
->data
, state
->total_data
,
8672 state
->max_data_return
);
8673 END_PROFILE(Trans2_qpathinfo
);
8677 case TRANSACT2_SETPATHINFO
:
8678 case TRANSACT2_SETFILEINFO
:
8680 START_PROFILE(Trans2_setpathinfo
);
8681 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8682 &state
->param
, state
->total_param
,
8683 &state
->data
, state
->total_data
,
8684 state
->max_data_return
);
8685 END_PROFILE(Trans2_setpathinfo
);
8689 case TRANSACT2_FINDNOTIFYFIRST
:
8691 START_PROFILE(Trans2_findnotifyfirst
);
8692 call_trans2findnotifyfirst(conn
, req
,
8693 &state
->param
, state
->total_param
,
8694 &state
->data
, state
->total_data
,
8695 state
->max_data_return
);
8696 END_PROFILE(Trans2_findnotifyfirst
);
8700 case TRANSACT2_FINDNOTIFYNEXT
:
8702 START_PROFILE(Trans2_findnotifynext
);
8703 call_trans2findnotifynext(conn
, req
,
8704 &state
->param
, state
->total_param
,
8705 &state
->data
, state
->total_data
,
8706 state
->max_data_return
);
8707 END_PROFILE(Trans2_findnotifynext
);
8711 case TRANSACT2_MKDIR
:
8713 START_PROFILE(Trans2_mkdir
);
8714 call_trans2mkdir(conn
, req
,
8715 &state
->param
, state
->total_param
,
8716 &state
->data
, state
->total_data
,
8717 state
->max_data_return
);
8718 END_PROFILE(Trans2_mkdir
);
8722 case TRANSACT2_GET_DFS_REFERRAL
:
8724 START_PROFILE(Trans2_get_dfs_referral
);
8725 call_trans2getdfsreferral(conn
, req
,
8726 &state
->param
, state
->total_param
,
8727 &state
->data
, state
->total_data
,
8728 state
->max_data_return
);
8729 END_PROFILE(Trans2_get_dfs_referral
);
8733 case TRANSACT2_IOCTL
:
8735 START_PROFILE(Trans2_ioctl
);
8736 call_trans2ioctl(conn
, req
,
8737 &state
->param
, state
->total_param
,
8738 &state
->data
, state
->total_data
,
8739 state
->max_data_return
);
8740 END_PROFILE(Trans2_ioctl
);
8745 /* Error in request */
8746 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8747 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8751 /****************************************************************************
8752 Reply to a SMBtrans2.
8753 ****************************************************************************/
8755 void reply_trans2(struct smb_request
*req
)
8757 connection_struct
*conn
= req
->conn
;
8762 unsigned int tran_call
;
8763 struct trans_state
*state
;
8766 START_PROFILE(SMBtrans2
);
8768 if (req
->wct
< 14) {
8769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8770 END_PROFILE(SMBtrans2
);
8774 dsoff
= SVAL(req
->vwv
+12, 0);
8775 dscnt
= SVAL(req
->vwv
+11, 0);
8776 psoff
= SVAL(req
->vwv
+10, 0);
8777 pscnt
= SVAL(req
->vwv
+9, 0);
8778 tran_call
= SVAL(req
->vwv
+14, 0);
8780 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8781 if (!NT_STATUS_IS_OK(result
)) {
8782 DEBUG(2, ("Got invalid trans2 request: %s\n",
8783 nt_errstr(result
)));
8784 reply_nterror(req
, result
);
8785 END_PROFILE(SMBtrans2
);
8790 switch (tran_call
) {
8791 /* List the allowed trans2 calls on IPC$ */
8792 case TRANSACT2_OPEN
:
8793 case TRANSACT2_GET_DFS_REFERRAL
:
8794 case TRANSACT2_QFILEINFO
:
8795 case TRANSACT2_QFSINFO
:
8796 case TRANSACT2_SETFSINFO
:
8799 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8800 END_PROFILE(SMBtrans2
);
8805 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8806 DEBUG(0, ("talloc failed\n"));
8807 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8808 END_PROFILE(SMBtrans2
);
8812 state
->cmd
= SMBtrans2
;
8814 state
->mid
= req
->mid
;
8815 state
->vuid
= req
->vuid
;
8816 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8817 state
->setup
= NULL
;
8818 state
->total_param
= SVAL(req
->vwv
+0, 0);
8819 state
->param
= NULL
;
8820 state
->total_data
= SVAL(req
->vwv
+1, 0);
8822 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8823 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8824 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8825 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8826 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8828 state
->call
= tran_call
;
8830 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8831 is so as a sanity check */
8832 if (state
->setup_count
!= 1) {
8834 * Need to have rc=0 for ioctl to get job id for OS/2.
8835 * Network printing will fail if function is not successful.
8836 * Similar function in reply.c will be used if protocol
8837 * is LANMAN1.0 instead of LM1.2X002.
8838 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8839 * outbuf doesn't have to be set(only job id is used).
8841 if ( (state
->setup_count
== 4)
8842 && (tran_call
== TRANSACT2_IOCTL
)
8843 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8844 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8845 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8847 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8848 DEBUG(2,("Transaction is %d\n",tran_call
));
8850 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8851 END_PROFILE(SMBtrans2
);
8856 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8859 if (state
->total_data
) {
8861 if (trans_oob(state
->total_data
, 0, dscnt
)
8862 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8866 /* Can't use talloc here, the core routines do realloc on the
8867 * params and data. */
8868 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8869 if (state
->data
== NULL
) {
8870 DEBUG(0,("reply_trans2: data malloc fail for %u "
8871 "bytes !\n", (unsigned int)state
->total_data
));
8873 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8874 END_PROFILE(SMBtrans2
);
8878 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8881 if (state
->total_param
) {
8883 if (trans_oob(state
->total_param
, 0, pscnt
)
8884 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8888 /* Can't use talloc here, the core routines do realloc on the
8889 * params and data. */
8890 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8891 if (state
->param
== NULL
) {
8892 DEBUG(0,("reply_trans: param malloc fail for %u "
8893 "bytes !\n", (unsigned int)state
->total_param
));
8894 SAFE_FREE(state
->data
);
8896 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8897 END_PROFILE(SMBtrans2
);
8901 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8904 state
->received_data
= dscnt
;
8905 state
->received_param
= pscnt
;
8907 if ((state
->received_param
== state
->total_param
) &&
8908 (state
->received_data
== state
->total_data
)) {
8910 handle_trans2(conn
, req
, state
);
8912 SAFE_FREE(state
->data
);
8913 SAFE_FREE(state
->param
);
8915 END_PROFILE(SMBtrans2
);
8919 DLIST_ADD(conn
->pending_trans
, state
);
8921 /* We need to send an interim response then receive the rest
8922 of the parameter/data bytes */
8923 reply_outbuf(req
, 0, 0);
8924 show_msg((char *)req
->outbuf
);
8925 END_PROFILE(SMBtrans2
);
8930 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8931 SAFE_FREE(state
->data
);
8932 SAFE_FREE(state
->param
);
8934 END_PROFILE(SMBtrans2
);
8935 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8939 /****************************************************************************
8940 Reply to a SMBtranss2
8941 ****************************************************************************/
8943 void reply_transs2(struct smb_request
*req
)
8945 connection_struct
*conn
= req
->conn
;
8946 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8947 struct trans_state
*state
;
8949 START_PROFILE(SMBtranss2
);
8951 show_msg((const char *)req
->inbuf
);
8953 /* Windows clients expect all replies to
8954 a transact secondary (SMBtranss2 0x33)
8955 to have a command code of transact
8956 (SMBtrans2 0x32). See bug #8989
8957 and also [MS-CIFS] section 2.2.4.47.2
8960 req
->cmd
= SMBtrans2
;
8963 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8964 END_PROFILE(SMBtranss2
);
8968 for (state
= conn
->pending_trans
; state
!= NULL
;
8969 state
= state
->next
) {
8970 if (state
->mid
== req
->mid
) {
8975 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8976 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8977 END_PROFILE(SMBtranss2
);
8981 /* Revise state->total_param and state->total_data in case they have
8982 changed downwards */
8984 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8985 state
->total_param
= SVAL(req
->vwv
+0, 0);
8986 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8987 state
->total_data
= SVAL(req
->vwv
+1, 0);
8989 pcnt
= SVAL(req
->vwv
+2, 0);
8990 poff
= SVAL(req
->vwv
+3, 0);
8991 pdisp
= SVAL(req
->vwv
+4, 0);
8993 dcnt
= SVAL(req
->vwv
+5, 0);
8994 doff
= SVAL(req
->vwv
+6, 0);
8995 ddisp
= SVAL(req
->vwv
+7, 0);
8997 state
->received_param
+= pcnt
;
8998 state
->received_data
+= dcnt
;
9000 if ((state
->received_data
> state
->total_data
) ||
9001 (state
->received_param
> state
->total_param
))
9005 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9006 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9009 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9013 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9014 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9017 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9020 if ((state
->received_param
< state
->total_param
) ||
9021 (state
->received_data
< state
->total_data
)) {
9022 END_PROFILE(SMBtranss2
);
9026 handle_trans2(conn
, req
, state
);
9028 DLIST_REMOVE(conn
->pending_trans
, state
);
9029 SAFE_FREE(state
->data
);
9030 SAFE_FREE(state
->param
);
9033 END_PROFILE(SMBtranss2
);
9038 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9039 DLIST_REMOVE(conn
->pending_trans
, state
);
9040 SAFE_FREE(state
->data
);
9041 SAFE_FREE(state
->param
);
9043 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9044 END_PROFILE(SMBtranss2
);