2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct *conn,
54 const SMB_STRUCT_STAT *psbuf);
56 static char *store_file_unix_basic_info2(connection_struct *conn,
59 const SMB_STRUCT_STAT *psbuf);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS refuse_symlink(connection_struct *conn,
66 const files_struct *fsp,
67 const struct smb_filename *smb_fname)
70 const SMB_STRUCT_STAT *pst = NULL;
73 pst = &fsp->fsp_name->st;
78 if (!VALID_STAT(*pst)) {
79 int ret = vfs_stat_smb_basename(conn,
82 if (ret == -1 && errno != ENOENT) {
83 return map_nt_error_from_unix(errno);
84 } else if (ret == -1) {
85 /* it's not a symlink.. */
91 if (S_ISLNK(pst->st_ex_mode)) {
92 return NT_STATUS_ACCESS_DENIED;
97 NTSTATUS check_access_fsp(const struct files_struct *fsp,
100 if (!(fsp->access_mask & access_mask)) {
101 return NT_STATUS_ACCESS_DENIED;
106 #if defined(HAVE_POSIX_ACLS)
107 /****************************************************************************
108 Utility function to open a fsp for a POSIX handle operation.
109 ****************************************************************************/
111 static NTSTATUS get_posix_fsp(connection_struct *conn,
112 struct smb_request *req,
113 const struct smb_filename *smb_fname,
114 uint32_t access_mask,
115 files_struct **ret_fsp)
118 struct smb_filename *smb_fname_tmp = NULL;
119 uint32_t create_disposition = FILE_OPEN;
120 uint32_t share_access = FILE_SHARE_READ|
123 struct smb2_create_blobs *posx = NULL;
126 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
127 * but set reasonable defaults.
129 uint32_t file_attributes = 0664;
130 uint32_t oplock = NO_OPLOCK;
131 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
133 /* File or directory must exist. */
134 if (!VALID_STAT(smb_fname->st)) {
135 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
137 /* Cannot be a symlink. */
138 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
139 return NT_STATUS_ACCESS_DENIED;
141 /* Set options correctly for directory open. */
142 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
144 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
145 * directories, but set reasonable defaults.
147 file_attributes = 0775;
148 create_options = FILE_DIRECTORY_FILE;
151 /* Createfile uses a non-const smb_fname. */
152 smb_fname_tmp = cp_smb_filename(talloc_tos(),
154 if (smb_fname_tmp == NULL) {
155 status = NT_STATUS_NO_MEMORY;
159 status = make_smb2_posix_create_ctx(
160 talloc_tos(), &posx, file_attributes);
161 if (!NT_STATUS_IS_OK(status)) {
162 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
167 status = SMB_VFS_CREATE_FILE(
170 smb_fname_tmp, /* fname */
171 access_mask, /* access_mask */
172 share_access, /* share_access */
173 create_disposition,/* create_disposition*/
174 create_options, /* create_options */
175 file_attributes,/* file_attributes */
176 oplock, /* oplock_request */
178 0, /* allocation_size */
179 0, /* private_flags */
182 ret_fsp, /* result */
184 posx, /* in_context */
185 NULL); /* out_context */
189 TALLOC_FREE(smb_fname_tmp);
194 /********************************************************************
195 Roundup a value to the nearest allocation roundup size boundary.
196 Only do this for Windows clients.
197 ********************************************************************/
199 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
201 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
203 /* Only roundup for Windows clients. */
204 enum remote_arch_types ra_type = get_remote_arch();
205 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
206 val = SMB_ROUNDUP(val,rval);
211 /****************************************************************************
212 Utility functions for dealing with extended attributes.
213 ****************************************************************************/
215 /****************************************************************************
216 Refuse to allow clients to overwrite our private xattrs.
217 ****************************************************************************/
219 bool samba_private_attr_name(const char *unix_ea_name)
221 static const char * const prohibited_ea_names[] = {
222 SAMBA_POSIX_INHERITANCE_EA_NAME,
223 SAMBA_XATTR_DOS_ATTRIB,
231 for (i = 0; prohibited_ea_names[i]; i++) {
232 if (strequal( prohibited_ea_names[i], unix_ea_name))
235 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
236 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
242 /****************************************************************************
243 Get one EA value. Fill in a struct ea_struct.
244 ****************************************************************************/
246 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
247 connection_struct *conn,
249 const struct smb_filename *smb_fname,
251 struct ea_struct *pea)
253 /* Get the value of this xattr. Max size is 64k. */
254 size_t attr_size = 256;
260 val = talloc_realloc(mem_ctx, val, char, attr_size);
262 return NT_STATUS_NO_MEMORY;
265 if (fsp && !fsp->fsp_flags.is_pathref && fsp_get_io_fd(fsp) != -1) {
266 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
268 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
269 ea_name, val, attr_size);
272 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
278 return map_nt_error_from_unix(errno);
281 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
282 dump_data(10, (uint8_t *)val, sizeret);
285 if (strnequal(ea_name, "user.", 5)) {
286 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
288 pea->name = talloc_strdup(mem_ctx, ea_name);
290 if (pea->name == NULL) {
292 return NT_STATUS_NO_MEMORY;
294 pea->value.data = (unsigned char *)val;
295 pea->value.length = (size_t)sizeret;
299 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
300 connection_struct *conn,
302 const struct smb_filename *smb_fname,
307 /* Get a list of all xattrs. Max namesize is 64k. */
308 size_t ea_namelist_size = 1024;
309 char *ea_namelist = smallbuf;
310 char *to_free = NULL;
315 ssize_t sizeret = -1;
323 status = refuse_symlink(conn, fsp, smb_fname);
324 if (!NT_STATUS_IS_OK(status)) {
326 * Just return no EA's on a symlink.
331 if (fsp && !fsp->fsp_flags.is_pathref && fsp_get_io_fd(fsp) != -1) {
332 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
335 sizeret = SMB_VFS_LISTXATTR(conn,
341 if ((sizeret == -1) && (errno == ERANGE)) {
342 ea_namelist_size = 65536;
343 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
344 if (ea_namelist == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 to_free = ea_namelist;
350 !fsp->fsp_flags.is_pathref &&
351 fsp_get_io_fd(fsp) != -1)
353 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
356 sizeret = SMB_VFS_LISTXATTR(conn,
364 status = map_nt_error_from_unix(errno);
365 TALLOC_FREE(to_free);
369 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
372 TALLOC_FREE(to_free);
377 * Ensure the result is 0-terminated
380 if (ea_namelist[sizeret-1] != '\0') {
381 TALLOC_FREE(to_free);
382 return NT_STATUS_INTERNAL_ERROR;
390 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
394 *pnum_names = num_names;
396 if (pnames == NULL) {
397 TALLOC_FREE(to_free);
401 names = talloc_array(mem_ctx, char *, num_names);
403 DEBUG(0, ("talloc failed\n"));
404 TALLOC_FREE(to_free);
405 return NT_STATUS_NO_MEMORY;
408 if (ea_namelist == smallbuf) {
409 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
410 if (ea_namelist == NULL) {
412 return NT_STATUS_NO_MEMORY;
415 talloc_steal(names, ea_namelist);
417 ea_namelist = talloc_realloc(names, ea_namelist, char,
419 if (ea_namelist == NULL) {
421 return NT_STATUS_NO_MEMORY;
427 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
428 names[num_names++] = p;
436 /****************************************************************************
437 Return a linked list of the total EA's. Plus the total size
438 ****************************************************************************/
440 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
441 connection_struct *conn,
443 const struct smb_filename *smb_fname,
444 size_t *pea_total_len,
445 struct ea_list **ea_list)
447 /* Get a list of all xattrs. Max namesize is 64k. */
450 struct ea_list *ea_list_head = NULL;
451 bool posix_pathnames = false;
457 if (!lp_ea_support(SNUM(conn))) {
463 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
465 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
468 status = get_ea_names_from_file(talloc_tos(),
475 if (!NT_STATUS_IS_OK(status)) {
479 if (num_names == 0) {
483 for (i=0; i<num_names; i++) {
484 struct ea_list *listp;
487 if (strnequal(names[i], "system.", 7)
488 || samba_private_attr_name(names[i]))
492 * Filter out any underlying POSIX EA names
493 * that a Windows client can't handle.
495 if (!posix_pathnames &&
496 is_invalid_windows_ea_name(names[i])) {
500 listp = talloc(mem_ctx, struct ea_list);
502 return NT_STATUS_NO_MEMORY;
505 status = get_ea_value(listp,
512 if (!NT_STATUS_IS_OK(status)) {
517 if (listp->ea.value.length == 0) {
519 * We can never return a zero length EA.
520 * Windows reports the EA's as corrupted.
526 push_ascii_fstring(dos_ea_name, listp->ea.name);
529 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
532 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
533 (unsigned int)listp->ea.value.length));
535 DLIST_ADD_END(ea_list_head, listp);
539 /* Add on 4 for total length. */
540 if (*pea_total_len) {
544 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
545 (unsigned int)*pea_total_len));
547 *ea_list = ea_list_head;
551 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
552 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
557 if (!lp_ea_support(SNUM(conn))) {
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 return NT_STATUS_INVALID_PARAMETER;
565 return get_ea_list_from_file_path(mem_ctx,
573 /****************************************************************************
574 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
576 ****************************************************************************/
578 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
579 connection_struct *conn, struct ea_list *ea_list)
581 unsigned int ret_data_size = 4;
584 SMB_ASSERT(total_data_size >= 4);
586 if (!lp_ea_support(SNUM(conn))) {
591 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
594 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
595 dos_namelen = strlen(dos_ea_name);
596 if (dos_namelen > 255 || dos_namelen == 0) {
599 if (ea_list->ea.value.length > 65535) {
602 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
606 /* We know we have room. */
607 SCVAL(p,0,ea_list->ea.flags);
608 SCVAL(p,1,dos_namelen);
609 SSVAL(p,2,ea_list->ea.value.length);
610 strlcpy(p+4, dos_ea_name, dos_namelen+1);
611 if (ea_list->ea.value.length > 0) {
612 memcpy(p + 4 + dos_namelen + 1,
613 ea_list->ea.value.data,
614 ea_list->ea.value.length);
617 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
618 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
621 ret_data_size = PTR_DIFF(p, pdata);
622 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
623 SIVAL(pdata,0,ret_data_size);
624 return ret_data_size;
627 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
629 unsigned int total_data_size,
630 unsigned int *ret_data_size,
631 connection_struct *conn,
632 struct ea_list *ea_list)
634 uint8_t *p = (uint8_t *)pdata;
635 uint8_t *last_start = NULL;
636 bool do_store_data = (pdata != NULL);
640 if (!lp_ea_support(SNUM(conn))) {
641 return NT_STATUS_NO_EAS_ON_FILE;
644 for (; ea_list; ea_list = ea_list->next) {
650 if (last_start != NULL && do_store_data) {
651 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
655 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
656 dos_namelen = strlen(dos_ea_name);
657 if (dos_namelen > 255 || dos_namelen == 0) {
658 return NT_STATUS_INTERNAL_ERROR;
660 if (ea_list->ea.value.length > 65535) {
661 return NT_STATUS_INTERNAL_ERROR;
664 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
667 pad = (4 - (this_size % 4)) % 4;
672 if (this_size > total_data_size) {
673 return NT_STATUS_INFO_LENGTH_MISMATCH;
676 /* We know we have room. */
677 SIVAL(p, 0x00, 0); /* next offset */
678 SCVAL(p, 0x04, ea_list->ea.flags);
679 SCVAL(p, 0x05, dos_namelen);
680 SSVAL(p, 0x06, ea_list->ea.value.length);
681 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
682 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
684 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
688 total_data_size -= this_size;
694 *ret_data_size = PTR_DIFF(p, pdata);
695 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
699 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
701 size_t total_ea_len = 0;
703 struct ea_list *ea_list = NULL;
705 if (!lp_ea_support(SNUM(conn))) {
708 mem_ctx = talloc_stackframe();
710 /* If this is a stream fsp, then we need to instead find the
711 * estimated ea len from the main file, not the stream
712 * (streams cannot have EAs), but the estimate isn't just 0 in
714 if (is_ntfs_stream_smb_fname(smb_fname)) {
717 (void)get_ea_list_from_file_path(mem_ctx,
723 if(conn->sconn->using_smb2) {
725 unsigned int ret_data_size;
727 * We're going to be using fill_ea_chained_buffer() to
728 * marshall EA's - this size is significantly larger
729 * than the SMB1 buffer. Re-calculate the size without
732 status = fill_ea_chained_buffer(mem_ctx,
738 if (!NT_STATUS_IS_OK(status)) {
741 total_ea_len = ret_data_size;
743 TALLOC_FREE(mem_ctx);
747 /****************************************************************************
748 Ensure the EA name is case insensitive by matching any existing EA name.
749 ****************************************************************************/
751 static void canonicalize_ea_name(connection_struct *conn,
753 const struct smb_filename *smb_fname,
754 fstring unix_ea_name)
757 TALLOC_CTX *mem_ctx = talloc_tos();
758 struct ea_list *ea_list;
759 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
765 if (!NT_STATUS_IS_OK(status)) {
769 for (; ea_list; ea_list = ea_list->next) {
770 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
771 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
772 &unix_ea_name[5], ea_list->ea.name));
773 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
779 /****************************************************************************
780 Set or delete an extended attribute.
781 ****************************************************************************/
783 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
784 const struct smb_filename *smb_fname, struct ea_list *ea_list)
787 bool posix_pathnames = false;
789 if (!lp_ea_support(SNUM(conn))) {
790 return NT_STATUS_EAS_NOT_SUPPORTED;
795 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
797 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
800 status = refuse_symlink(conn, fsp, smb_fname);
801 if (!NT_STATUS_IS_OK(status)) {
806 status = check_access_fsp(fsp, FILE_WRITE_EA);
808 status = smbd_check_access_rights(conn,
814 if (!NT_STATUS_IS_OK(status)) {
818 /* Setting EAs on streams isn't supported. */
819 if (is_ntfs_stream_smb_fname(smb_fname)) {
820 return NT_STATUS_INVALID_PARAMETER;
824 * Filter out invalid Windows EA names - before
825 * we set *any* of them.
828 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
829 return STATUS_INVALID_EA_NAME;
832 for (;ea_list; ea_list = ea_list->next) {
834 fstring unix_ea_name;
836 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
837 fstrcat(unix_ea_name, ea_list->ea.name);
839 canonicalize_ea_name(conn,
844 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
846 if (samba_private_attr_name(unix_ea_name)) {
847 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
848 return NT_STATUS_ACCESS_DENIED;
851 if (ea_list->ea.value.length == 0) {
852 /* Remove the attribute. */
854 !fsp->fsp_flags.is_pathref &&
855 fsp_get_io_fd(fsp) != -1)
857 DEBUG(10,("set_ea: deleting ea name %s on "
858 "file %s by file descriptor.\n",
859 unix_ea_name, fsp_str_dbg(fsp)));
860 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
862 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
863 unix_ea_name, smb_fname->base_name));
864 ret = SMB_VFS_REMOVEXATTR(conn,
869 /* Removing a non existent attribute always succeeds. */
870 if (ret == -1 && errno == ENOATTR) {
871 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
878 !fsp->fsp_flags.is_pathref &&
879 fsp_get_io_fd(fsp) != -1)
881 DEBUG(10,("set_ea: setting ea name %s on file "
882 "%s by file descriptor.\n",
883 unix_ea_name, fsp_str_dbg(fsp)));
884 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
885 ea_list->ea.value.data, ea_list->ea.value.length, 0);
887 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
888 unix_ea_name, smb_fname->base_name));
889 ret = SMB_VFS_SETXATTR(conn,
892 ea_list->ea.value.data,
893 ea_list->ea.value.length,
900 if (errno == ENOTSUP) {
901 return NT_STATUS_EAS_NOT_SUPPORTED;
904 return map_nt_error_from_unix(errno);
910 /****************************************************************************
911 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
912 ****************************************************************************/
914 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
916 struct ea_list *ea_list_head = NULL;
917 size_t converted_size, offset = 0;
919 while (offset + 2 < data_size) {
920 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
921 unsigned int namelen = CVAL(pdata,offset);
923 offset++; /* Go past the namelen byte. */
925 /* integer wrap paranioa. */
926 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
927 (offset > data_size) || (namelen > data_size) ||
928 (offset + namelen >= data_size)) {
931 /* Ensure the name is null terminated. */
932 if (pdata[offset + namelen] != '\0') {
935 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
937 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
938 "failed: %s", strerror(errno)));
944 offset += (namelen + 1); /* Go past the name + terminating zero. */
945 DLIST_ADD_END(ea_list_head, eal);
946 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
952 /****************************************************************************
953 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
954 ****************************************************************************/
956 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
958 struct ea_list *ea_list_head = NULL;
960 size_t bytes_used = 0;
962 while (offset < data_size) {
963 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
969 DLIST_ADD_END(ea_list_head, eal);
970 offset += bytes_used;
976 /****************************************************************************
977 Count the total EA size needed.
978 ****************************************************************************/
980 static size_t ea_list_size(struct ea_list *ealist)
983 struct ea_list *listp;
986 for (listp = ealist; listp; listp = listp->next) {
987 push_ascii_fstring(dos_ea_name, listp->ea.name);
988 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
990 /* Add on 4 for total length. */
998 /****************************************************************************
999 Return a union of EA's from a file list and a list of names.
1000 The TALLOC context for the two lists *MUST* be identical as we steal
1001 memory from one list to add to another. JRA.
1002 ****************************************************************************/
1004 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1006 struct ea_list *nlistp, *flistp;
1008 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1009 for (flistp = file_list; flistp; flistp = flistp->next) {
1010 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1016 /* Copy the data from this entry. */
1017 nlistp->ea.flags = flistp->ea.flags;
1018 nlistp->ea.value = flistp->ea.value;
1021 nlistp->ea.flags = 0;
1022 ZERO_STRUCT(nlistp->ea.value);
1026 *total_ea_len = ea_list_size(name_list);
1030 /****************************************************************************
1031 Send the required number of replies back.
1032 We assume all fields other than the data fields are
1033 set correctly for the type of call.
1034 HACK ! Always assumes smb_setup field is zero.
1035 ****************************************************************************/
1037 void send_trans2_replies(connection_struct *conn,
1038 struct smb_request *req,
1046 /* As we are using a protocol > LANMAN1 then the max_send
1047 variable must have been set in the sessetupX call.
1048 This takes precedence over the max_xmit field in the
1049 global struct. These different max_xmit variables should
1050 be merged as this is now too confusing */
1052 int data_to_send = datasize;
1053 int params_to_send = paramsize;
1055 const char *pp = params;
1056 const char *pd = pdata;
1057 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1058 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1059 int data_alignment_offset = 0;
1060 bool overflow = False;
1061 struct smbXsrv_connection *xconn = req->xconn;
1062 int max_send = xconn->smb1.sessions.max_send;
1064 /* Modify the data_to_send and datasize and set the error if
1065 we're trying to send more than max_data_bytes. We still send
1066 the part of the packet(s) that fit. Strange, but needed
1069 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1070 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1071 max_data_bytes, datasize ));
1072 datasize = data_to_send = max_data_bytes;
1076 /* If there genuinely are no parameters or data to send just send the empty packet */
1078 if(params_to_send == 0 && data_to_send == 0) {
1079 reply_outbuf(req, 10, 0);
1080 if (NT_STATUS_V(status)) {
1083 ntstatus_to_dos(status, &eclass, &ecode);
1084 error_packet_set((char *)req->outbuf,
1085 eclass, ecode, status,
1088 show_msg((char *)req->outbuf);
1089 if (!srv_send_smb(xconn,
1090 (char *)req->outbuf,
1091 true, req->seqnum+1,
1092 IS_CONN_ENCRYPTED(conn),
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req->outbuf);
1100 /* When sending params and data ensure that both are nicely aligned */
1101 /* Only do this alignment when there is also data to send - else
1102 can cause NT redirector problems. */
1104 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1105 data_alignment_offset = 4 - (params_to_send % 4);
1107 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1108 /* The alignment_offset is to align the param bytes on an even byte
1109 boundary. NT 4.0 Beta needs this to work correctly. */
1111 useable_space = max_send - (smb_size
1114 + data_alignment_offset);
1116 if (useable_space < 0) {
1117 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1118 "= %d!!!", useable_space));
1119 exit_server_cleanly("send_trans2_replies: Not enough space");
1122 while (params_to_send || data_to_send) {
1123 /* Calculate whether we will totally or partially fill this packet */
1125 total_sent_thistime = params_to_send + data_to_send;
1127 /* We can never send more than useable_space */
1129 * Note that 'useable_space' does not include the alignment offsets,
1130 * but we must include the alignment offsets in the calculation of
1131 * the length of the data we send over the wire, as the alignment offsets
1132 * are sent here. Fix from Marc_Jacobsen@hp.com.
1135 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1137 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1138 + data_alignment_offset);
1140 /* Set total params and data to be sent */
1141 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1142 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1144 /* Calculate how many parameters and data we can fit into
1145 * this packet. Parameters get precedence
1148 params_sent_thistime = MIN(params_to_send,useable_space);
1149 data_sent_thistime = useable_space - params_sent_thistime;
1150 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1152 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1154 /* smb_proff is the offset from the start of the SMB header to the
1155 parameter bytes, however the first 4 bytes of outbuf are
1156 the Netbios over TCP header. Thus use smb_base() to subtract
1157 them from the calculation */
1159 SSVAL(req->outbuf,smb_proff,
1160 ((smb_buf(req->outbuf)+alignment_offset)
1161 - smb_base(req->outbuf)));
1163 if(params_sent_thistime == 0)
1164 SSVAL(req->outbuf,smb_prdisp,0);
1166 /* Absolute displacement of param bytes sent in this packet */
1167 SSVAL(req->outbuf,smb_prdisp,pp - params);
1169 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1170 if(data_sent_thistime == 0) {
1171 SSVAL(req->outbuf,smb_droff,0);
1172 SSVAL(req->outbuf,smb_drdisp, 0);
1174 /* The offset of the data bytes is the offset of the
1175 parameter bytes plus the number of parameters being sent this time */
1176 SSVAL(req->outbuf, smb_droff,
1177 ((smb_buf(req->outbuf)+alignment_offset)
1178 - smb_base(req->outbuf))
1179 + params_sent_thistime + data_alignment_offset);
1180 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1183 /* Initialize the padding for alignment */
1185 if (alignment_offset != 0) {
1186 memset(smb_buf(req->outbuf), 0, alignment_offset);
1189 /* Copy the param bytes into the packet */
1191 if(params_sent_thistime) {
1192 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1193 params_sent_thistime);
1196 /* Copy in the data bytes */
1197 if(data_sent_thistime) {
1198 if (data_alignment_offset != 0) {
1199 memset((smb_buf(req->outbuf)+alignment_offset+
1200 params_sent_thistime), 0,
1201 data_alignment_offset);
1203 memcpy(smb_buf(req->outbuf)+alignment_offset
1204 +params_sent_thistime+data_alignment_offset,
1205 pd,data_sent_thistime);
1208 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1209 params_sent_thistime, data_sent_thistime, useable_space));
1210 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1211 params_to_send, data_to_send, paramsize, datasize));
1214 error_packet_set((char *)req->outbuf,
1215 ERRDOS,ERRbufferoverflow,
1216 STATUS_BUFFER_OVERFLOW,
1218 } else if (NT_STATUS_V(status)) {
1221 ntstatus_to_dos(status, &eclass, &ecode);
1222 error_packet_set((char *)req->outbuf,
1223 eclass, ecode, status,
1227 /* Send the packet */
1228 show_msg((char *)req->outbuf);
1229 if (!srv_send_smb(xconn,
1230 (char *)req->outbuf,
1231 true, req->seqnum+1,
1232 IS_CONN_ENCRYPTED(conn),
1234 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1236 TALLOC_FREE(req->outbuf);
1238 pp += params_sent_thistime;
1239 pd += data_sent_thistime;
1241 params_to_send -= params_sent_thistime;
1242 data_to_send -= data_sent_thistime;
1245 if(params_to_send < 0 || data_to_send < 0) {
1246 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1247 params_to_send, data_to_send));
1255 /****************************************************************************
1256 Reply to a TRANSACT2_OPEN.
1257 ****************************************************************************/
1259 static void call_trans2open(connection_struct *conn,
1260 struct smb_request *req,
1261 char **pparams, int total_params,
1262 char **ppdata, int total_data,
1263 unsigned int max_data_bytes)
1265 struct smb_filename *smb_fname = NULL;
1266 char *params = *pparams;
1267 char *pdata = *ppdata;
1270 bool oplock_request;
1272 bool return_additional_info;
1281 int fattr=0,mtime=0;
1282 SMB_INO_T inode = 0;
1285 struct ea_list *ea_list = NULL;
1288 uint32_t access_mask;
1289 uint32_t share_mode;
1290 uint32_t create_disposition;
1291 uint32_t create_options = 0;
1292 uint32_t private_flags = 0;
1293 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1294 TALLOC_CTX *ctx = talloc_tos();
1297 * Ensure we have enough parameters to perform the operation.
1300 if (total_params < 29) {
1301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1305 flags = SVAL(params, 0);
1306 deny_mode = SVAL(params, 2);
1307 open_attr = SVAL(params,6);
1308 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1309 if (oplock_request) {
1310 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1314 return_additional_info = BITSETW(params,0);
1315 open_sattr = SVAL(params, 4);
1316 open_time = make_unix_date3(params+8);
1318 open_ofun = SVAL(params,12);
1319 open_size = IVAL(params,14);
1320 pname = ¶ms[28];
1323 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1327 if (req->posix_pathnames) {
1328 srvstr_get_path_posix(ctx,
1337 srvstr_get_path(ctx,
1346 if (!NT_STATUS_IS_OK(status)) {
1347 reply_nterror(req, status);
1351 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1352 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1353 (unsigned int)open_ofun, open_size));
1355 status = filename_convert(ctx,
1361 if (!NT_STATUS_IS_OK(status)) {
1362 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1363 reply_botherror(req,
1364 NT_STATUS_PATH_NOT_COVERED,
1365 ERRSRV, ERRbadpath);
1368 reply_nterror(req, status);
1372 if (open_ofun == 0) {
1373 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1377 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1379 &access_mask, &share_mode,
1380 &create_disposition,
1383 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1387 /* Any data in this call is an EA list. */
1388 if (total_data && (total_data != 4)) {
1389 if (total_data < 10) {
1390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1394 if (IVAL(pdata,0) > total_data) {
1395 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1396 IVAL(pdata,0), (unsigned int)total_data));
1397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1401 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1408 if (!lp_ea_support(SNUM(conn))) {
1409 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1413 if (!req->posix_pathnames &&
1414 ea_list_has_invalid_name(ea_list)) {
1416 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1417 if(*pparams == NULL ) {
1418 reply_nterror(req, NT_STATUS_NO_MEMORY);
1422 memset(params, '\0', param_len);
1423 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1424 params, param_len, NULL, 0, max_data_bytes);
1429 status = SMB_VFS_CREATE_FILE(
1432 smb_fname, /* fname */
1433 access_mask, /* access_mask */
1434 share_mode, /* share_access */
1435 create_disposition, /* create_disposition*/
1436 create_options, /* create_options */
1437 open_attr, /* file_attributes */
1438 oplock_request, /* oplock_request */
1440 open_size, /* allocation_size */
1443 ea_list, /* ea_list */
1445 &smb_action, /* psbuf */
1446 NULL, NULL); /* create context */
1448 if (!NT_STATUS_IS_OK(status)) {
1449 if (open_was_deferred(req->xconn, req->mid)) {
1450 /* We have re-scheduled this call. */
1454 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1455 reply_openerror(req, status);
1459 fsp = fcb_or_dos_open(
1466 bool ok = defer_smb1_sharing_violation(req);
1470 reply_openerror(req, status);
1474 smb_action = FILE_WAS_OPENED;
1477 size = get_file_size_stat(&smb_fname->st);
1478 fattr = dos_mode(conn, smb_fname);
1479 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1480 inode = smb_fname->st.st_ex_ino;
1481 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1482 close_file(req, fsp, ERROR_CLOSE);
1483 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1487 /* Realloc the size of parameters and data we will return */
1488 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1489 if(*pparams == NULL ) {
1490 reply_nterror(req, NT_STATUS_NO_MEMORY);
1495 SSVAL(params,0,fsp->fnum);
1496 SSVAL(params,2,fattr);
1497 srv_put_dos_date2(params,4, mtime);
1498 SIVAL(params,8, (uint32_t)size);
1499 SSVAL(params,12,deny_mode);
1500 SSVAL(params,14,0); /* open_type - file or directory. */
1501 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1503 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1504 smb_action |= EXTENDED_OPLOCK_GRANTED;
1507 SSVAL(params,18,smb_action);
1510 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1512 SIVAL(params,20,inode);
1513 SSVAL(params,24,0); /* Padding. */
1515 uint32_t ea_size = estimate_ea_size(conn, fsp,
1517 SIVAL(params, 26, ea_size);
1519 SIVAL(params, 26, 0);
1522 /* Send the required number of replies */
1523 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1525 TALLOC_FREE(smb_fname);
1528 /*********************************************************
1529 Routine to check if a given string matches exactly.
1530 as a special case a mask of "." does NOT match. That
1531 is required for correct wildcard semantics
1532 Case can be significant or not.
1533 **********************************************************/
1535 static bool exact_match(bool has_wild,
1536 bool case_sensitive,
1540 if (mask[0] == '.' && mask[1] == 0) {
1548 if (case_sensitive) {
1549 return strcmp(str,mask)==0;
1551 return strcasecmp_m(str,mask) == 0;
1555 /****************************************************************************
1556 Return the filetype for UNIX extensions.
1557 ****************************************************************************/
1559 static uint32_t unix_filetype(mode_t mode)
1562 return UNIX_TYPE_FILE;
1563 else if(S_ISDIR(mode))
1564 return UNIX_TYPE_DIR;
1566 else if(S_ISLNK(mode))
1567 return UNIX_TYPE_SYMLINK;
1570 else if(S_ISCHR(mode))
1571 return UNIX_TYPE_CHARDEV;
1574 else if(S_ISBLK(mode))
1575 return UNIX_TYPE_BLKDEV;
1578 else if(S_ISFIFO(mode))
1579 return UNIX_TYPE_FIFO;
1582 else if(S_ISSOCK(mode))
1583 return UNIX_TYPE_SOCKET;
1586 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1587 return UNIX_TYPE_UNKNOWN;
1590 /****************************************************************************
1591 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1592 ****************************************************************************/
1594 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1595 const SMB_STRUCT_STAT *psbuf,
1597 enum perm_type ptype,
1602 if (perms == SMB_MODE_NO_CHANGE) {
1603 if (!VALID_STAT(*psbuf)) {
1604 return NT_STATUS_INVALID_PARAMETER;
1606 *ret_perms = psbuf->st_ex_mode;
1607 return NT_STATUS_OK;
1611 ret = wire_perms_to_unix(perms);
1613 if (ptype == PERM_NEW_FILE) {
1615 * "create mask"/"force create mode" are
1616 * only applied to new files, not existing ones.
1618 ret &= lp_create_mask(SNUM(conn));
1619 /* Add in force bits */
1620 ret |= lp_force_create_mode(SNUM(conn));
1621 } else if (ptype == PERM_NEW_DIR) {
1623 * "directory mask"/"force directory mode" are
1624 * only applied to new directories, not existing ones.
1626 ret &= lp_directory_mask(SNUM(conn));
1627 /* Add in force bits */
1628 ret |= lp_force_directory_mode(SNUM(conn));
1632 return NT_STATUS_OK;
1635 /****************************************************************************
1636 Needed to show the msdfs symlinks as directories. Modifies psbuf
1637 to be a directory if it's a msdfs link.
1638 ****************************************************************************/
1640 static bool check_msdfs_link(connection_struct *conn,
1641 struct smb_filename *smb_fname)
1643 int saved_errno = errno;
1644 if(lp_host_msdfs() &&
1645 lp_msdfs_root(SNUM(conn)) &&
1646 is_msdfs_link(conn, smb_fname)) {
1648 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1650 smb_fname->base_name));
1651 smb_fname->st.st_ex_mode =
1652 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1653 errno = saved_errno;
1656 errno = saved_errno;
1661 /****************************************************************************
1662 Get a level dependent lanman2 dir entry.
1663 ****************************************************************************/
1665 struct smbd_dirptr_lanman2_state {
1666 connection_struct *conn;
1667 uint32_t info_level;
1668 bool check_mangled_names;
1670 bool got_exact_match;
1673 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1679 struct smbd_dirptr_lanman2_state *state =
1680 (struct smbd_dirptr_lanman2_state *)private_data;
1682 char mangled_name[13]; /* mangled 8.3 name. */
1686 /* Mangle fname if it's an illegal name. */
1687 if (mangle_must_mangle(dname, state->conn->params)) {
1689 * Slow path - ensure we can push the original name as UCS2. If
1690 * not, then just don't return this name.
1694 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1695 uint8_t *tmp = talloc_array(talloc_tos(),
1699 status = srvstr_push(NULL,
1700 FLAGS2_UNICODE_STRINGS,
1709 if (!NT_STATUS_IS_OK(status)) {
1713 ok = name_to_8_3(dname, mangled_name,
1714 true, state->conn->params);
1718 fname = mangled_name;
1723 got_match = exact_match(state->has_wild,
1724 state->conn->case_sensitive,
1726 state->got_exact_match = got_match;
1728 got_match = mask_match(fname, mask,
1729 state->conn->case_sensitive);
1732 if(!got_match && state->check_mangled_names &&
1733 !mangle_is_8_3(fname, false, state->conn->params)) {
1735 * It turns out that NT matches wildcards against
1736 * both long *and* short names. This may explain some
1737 * of the wildcard wierdness from old DOS clients
1738 * that some people have been seeing.... JRA.
1740 /* Force the mangling into 8.3. */
1741 ok = name_to_8_3(fname, mangled_name,
1742 false, state->conn->params);
1747 got_match = exact_match(state->has_wild,
1748 state->conn->case_sensitive,
1749 mangled_name, mask);
1750 state->got_exact_match = got_match;
1752 got_match = mask_match(mangled_name, mask,
1753 state->conn->case_sensitive);
1761 *_fname = talloc_strdup(ctx, fname);
1762 if (*_fname == NULL) {
1769 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1771 struct smb_filename *smb_fname,
1775 struct smbd_dirptr_lanman2_state *state =
1776 (struct smbd_dirptr_lanman2_state *)private_data;
1777 bool ms_dfs_link = false;
1780 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1781 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1782 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1783 "Couldn't lstat [%s] (%s)\n",
1784 smb_fname_str_dbg(smb_fname),
1788 } else if (!VALID_STAT(smb_fname->st) &&
1789 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1790 /* Needed to show the msdfs symlinks as
1793 ms_dfs_link = check_msdfs_link(state->conn,
1796 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1797 "Couldn't stat [%s] (%s)\n",
1798 smb_fname_str_dbg(smb_fname),
1805 mode = dos_mode_msdfs(state->conn, smb_fname);
1806 } else if (get_dosmode) {
1807 mode = dos_mode(state->conn, smb_fname);
1814 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1815 connection_struct *conn,
1817 uint32_t info_level,
1818 struct ea_list *name_list,
1819 bool check_mangled_names,
1820 bool requires_resume_key,
1823 const struct smb_filename *smb_fname,
1824 int space_remaining,
1830 uint64_t *last_entry_off)
1832 char *p, *q, *pdata = *ppdata;
1834 uint64_t file_size = 0;
1835 uint64_t allocation_size = 0;
1836 uint64_t file_id = 0;
1838 struct timespec mdate_ts = {0};
1839 struct timespec adate_ts = {0};
1840 struct timespec cdate_ts = {0};
1841 struct timespec create_date_ts = {0};
1842 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1844 char *last_entry_ptr;
1849 struct readdir_attr_data *readdir_attr_data = NULL;
1851 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1852 file_size = get_file_size_stat(&smb_fname->st);
1854 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1856 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1863 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1865 mdate_ts = smb_fname->st.st_ex_mtime;
1866 adate_ts = smb_fname->st.st_ex_atime;
1867 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1868 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1870 if (lp_dos_filetime_resolution(SNUM(conn))) {
1871 dos_filetime_timespec(&create_date_ts);
1872 dos_filetime_timespec(&mdate_ts);
1873 dos_filetime_timespec(&adate_ts);
1874 dos_filetime_timespec(&cdate_ts);
1877 create_date = convert_timespec_to_time_t(create_date_ts);
1878 mdate = convert_timespec_to_time_t(mdate_ts);
1879 adate = convert_timespec_to_time_t(adate_ts);
1881 /* align the record */
1882 SMB_ASSERT(align >= 1);
1884 off = (int)PTR_DIFF(pdata, base_data);
1885 pad = (off + (align-1)) & ~(align-1);
1888 if (pad && pad > space_remaining) {
1889 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1890 "for padding (wanted %u, had %d)\n",
1893 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1897 /* initialize padding to 0 */
1899 memset(pdata, 0, pad);
1901 space_remaining -= pad;
1903 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1913 switch (info_level) {
1914 case SMB_FIND_INFO_STANDARD:
1915 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1916 if(requires_resume_key) {
1920 srv_put_dos_date2(p,0,create_date);
1921 srv_put_dos_date2(p,4,adate);
1922 srv_put_dos_date2(p,8,mdate);
1923 SIVAL(p,12,(uint32_t)file_size);
1924 SIVAL(p,16,(uint32_t)allocation_size);
1928 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1929 p += ucs2_align(base_data, p, 0);
1931 status = srvstr_push(base_data, flags2, p,
1932 fname, PTR_DIFF(end_data, p),
1933 STR_TERMINATE, &len);
1934 if (!NT_STATUS_IS_OK(status)) {
1937 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1939 SCVAL(nameptr, -1, len - 2);
1941 SCVAL(nameptr, -1, 0);
1945 SCVAL(nameptr, -1, len - 1);
1947 SCVAL(nameptr, -1, 0);
1953 case SMB_FIND_EA_SIZE:
1954 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1955 if (requires_resume_key) {
1959 srv_put_dos_date2(p,0,create_date);
1960 srv_put_dos_date2(p,4,adate);
1961 srv_put_dos_date2(p,8,mdate);
1962 SIVAL(p,12,(uint32_t)file_size);
1963 SIVAL(p,16,(uint32_t)allocation_size);
1966 unsigned int ea_size = estimate_ea_size(conn, NULL,
1968 SIVAL(p,22,ea_size); /* Extended attributes */
1972 status = srvstr_push(base_data, flags2,
1973 p, fname, PTR_DIFF(end_data, p),
1974 STR_TERMINATE | STR_NOALIGN, &len);
1975 if (!NT_STATUS_IS_OK(status)) {
1978 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1991 SCVAL(nameptr,0,len);
1993 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1996 case SMB_FIND_EA_LIST:
1998 struct ea_list *file_list = NULL;
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2003 return NT_STATUS_INVALID_PARAMETER;
2005 if (requires_resume_key) {
2009 srv_put_dos_date2(p,0,create_date);
2010 srv_put_dos_date2(p,4,adate);
2011 srv_put_dos_date2(p,8,mdate);
2012 SIVAL(p,12,(uint32_t)file_size);
2013 SIVAL(p,16,(uint32_t)allocation_size);
2015 p += 22; /* p now points to the EA area. */
2017 status = get_ea_list_from_file(ctx, conn, NULL,
2019 &ea_len, &file_list);
2020 if (!NT_STATUS_IS_OK(status)) {
2023 name_list = ea_list_union(name_list, file_list, &ea_len);
2025 /* We need to determine if this entry will fit in the space available. */
2026 /* Max string size is 255 bytes. */
2027 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2028 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2029 "(wanted %u, had %d)\n",
2030 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2032 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2035 /* Push the ea_data followed by the name. */
2036 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2038 status = srvstr_push(base_data, flags2,
2039 p + 1, fname, PTR_DIFF(end_data, p+1),
2040 STR_TERMINATE | STR_NOALIGN, &len);
2041 if (!NT_STATUS_IS_OK(status)) {
2044 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2057 SCVAL(nameptr,0,len);
2059 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2063 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2064 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2065 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2067 SIVAL(p,0,reskey); p += 4;
2068 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2069 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2070 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2071 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2072 SOFF_T(p,0,file_size); p += 8;
2073 SOFF_T(p,0,allocation_size); p += 8;
2074 SIVAL(p,0,mode); p += 4;
2075 q = p; p += 4; /* q is placeholder for name length. */
2076 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2077 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2079 unsigned int ea_size = estimate_ea_size(conn, NULL,
2081 SIVAL(p,0,ea_size); /* Extended attributes */
2084 /* Clear the short name buffer. This is
2085 * IMPORTANT as not doing so will trigger
2086 * a Win2k client bug. JRA.
2088 if (!was_8_3 && check_mangled_names) {
2089 char mangled_name[13]; /* mangled 8.3 name. */
2090 if (!name_to_8_3(fname,mangled_name,True,
2092 /* Error - mangle failed ! */
2093 memset(mangled_name,'\0',12);
2095 mangled_name[12] = 0;
2096 status = srvstr_push(base_data, flags2,
2097 p+2, mangled_name, 24,
2098 STR_UPPER|STR_UNICODE, &len);
2099 if (!NT_STATUS_IS_OK(status)) {
2103 memset(p + 2 + len,'\0',24 - len);
2110 status = srvstr_push(base_data, flags2, p,
2111 fname, PTR_DIFF(end_data, p),
2112 STR_TERMINATE_ASCII, &len);
2113 if (!NT_STATUS_IS_OK(status)) {
2119 len = PTR_DIFF(p, pdata);
2120 pad = (len + (align-1)) & ~(align-1);
2122 * offset to the next entry, the caller
2123 * will overwrite it for the last entry
2124 * that's why we always include the padding
2128 * set padding to zero
2131 memset(p, 0, pad - len);
2138 case SMB_FIND_FILE_DIRECTORY_INFO:
2139 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2141 SIVAL(p,0,reskey); p += 4;
2142 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2143 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2144 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2145 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2146 SOFF_T(p,0,file_size); p += 8;
2147 SOFF_T(p,0,allocation_size); p += 8;
2148 SIVAL(p,0,mode); p += 4;
2149 status = srvstr_push(base_data, flags2,
2150 p + 4, fname, PTR_DIFF(end_data, p+4),
2151 STR_TERMINATE_ASCII, &len);
2152 if (!NT_STATUS_IS_OK(status)) {
2158 len = PTR_DIFF(p, pdata);
2159 pad = (len + (align-1)) & ~(align-1);
2161 * offset to the next entry, the caller
2162 * will overwrite it for the last entry
2163 * that's why we always include the padding
2167 * set padding to zero
2170 memset(p, 0, pad - len);
2177 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2178 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2180 SIVAL(p,0,reskey); p += 4;
2181 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2182 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2183 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2184 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2185 SOFF_T(p,0,file_size); p += 8;
2186 SOFF_T(p,0,allocation_size); p += 8;
2187 SIVAL(p,0,mode); p += 4;
2188 q = p; p += 4; /* q is placeholder for name length. */
2189 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2190 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2192 unsigned int ea_size = estimate_ea_size(conn, NULL,
2194 SIVAL(p,0,ea_size); /* Extended attributes */
2197 status = srvstr_push(base_data, flags2, p,
2198 fname, PTR_DIFF(end_data, p),
2199 STR_TERMINATE_ASCII, &len);
2200 if (!NT_STATUS_IS_OK(status)) {
2206 len = PTR_DIFF(p, pdata);
2207 pad = (len + (align-1)) & ~(align-1);
2209 * offset to the next entry, the caller
2210 * will overwrite it for the last entry
2211 * that's why we always include the padding
2215 * set padding to zero
2218 memset(p, 0, pad - len);
2225 case SMB_FIND_FILE_NAMES_INFO:
2226 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2228 SIVAL(p,0,reskey); p += 4;
2230 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2231 acl on a dir (tridge) */
2232 status = srvstr_push(base_data, flags2, p,
2233 fname, PTR_DIFF(end_data, p),
2234 STR_TERMINATE_ASCII, &len);
2235 if (!NT_STATUS_IS_OK(status)) {
2241 len = PTR_DIFF(p, pdata);
2242 pad = (len + (align-1)) & ~(align-1);
2244 * offset to the next entry, the caller
2245 * will overwrite it for the last entry
2246 * that's why we always include the padding
2250 * set padding to zero
2253 memset(p, 0, pad - len);
2260 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2261 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2263 SIVAL(p,0,reskey); p += 4;
2264 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2265 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2266 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2267 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2268 SOFF_T(p,0,file_size); p += 8;
2269 SOFF_T(p,0,allocation_size); p += 8;
2270 SIVAL(p,0,mode); p += 4;
2271 q = p; p += 4; /* q is placeholder for name length. */
2272 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2273 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2275 unsigned int ea_size = estimate_ea_size(conn, NULL,
2277 SIVAL(p,0,ea_size); /* Extended attributes */
2280 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2281 SBVAL(p,0,file_id); p += 8;
2282 status = srvstr_push(base_data, flags2, p,
2283 fname, PTR_DIFF(end_data, p),
2284 STR_TERMINATE_ASCII, &len);
2285 if (!NT_STATUS_IS_OK(status)) {
2291 len = PTR_DIFF(p, pdata);
2292 pad = (len + (align-1)) & ~(align-1);
2294 * offset to the next entry, the caller
2295 * will overwrite it for the last entry
2296 * that's why we always include the padding
2300 * set padding to zero
2303 memset(p, 0, pad - len);
2310 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2311 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2312 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2314 SIVAL(p,0,reskey); p += 4;
2315 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2316 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2317 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2318 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2319 SOFF_T(p,0,file_size); p += 8;
2320 SOFF_T(p,0,allocation_size); p += 8;
2321 SIVAL(p,0,mode); p += 4;
2322 q = p; p += 4; /* q is placeholder for name length */
2323 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2324 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2325 } else if (readdir_attr_data &&
2326 readdir_attr_data->type == RDATTR_AAPL) {
2328 * OS X specific SMB2 extension negotiated via
2329 * AAPL create context: return max_access in
2332 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2334 unsigned int ea_size = estimate_ea_size(conn, NULL,
2336 SIVAL(p,0,ea_size); /* Extended attributes */
2340 if (readdir_attr_data &&
2341 readdir_attr_data->type == RDATTR_AAPL) {
2343 * OS X specific SMB2 extension negotiated via
2344 * AAPL create context: return resource fork
2345 * length and compressed FinderInfo in
2348 * According to documentation short_name_len
2349 * should be 0, but on the wire behaviour
2350 * shows its set to 24 by clients.
2354 /* Resourefork length */
2355 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2357 /* Compressed FinderInfo */
2358 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2359 } else if (!was_8_3 && check_mangled_names) {
2360 char mangled_name[13]; /* mangled 8.3 name. */
2361 if (!name_to_8_3(fname,mangled_name,True,
2363 /* Error - mangle failed ! */
2364 memset(mangled_name,'\0',12);
2366 mangled_name[12] = 0;
2367 status = srvstr_push(base_data, flags2,
2368 p+2, mangled_name, 24,
2369 STR_UPPER|STR_UNICODE, &len);
2370 if (!NT_STATUS_IS_OK(status)) {
2375 memset(p + 2 + len,'\0',24 - len);
2379 /* Clear the short name buffer. This is
2380 * IMPORTANT as not doing so will trigger
2381 * a Win2k client bug. JRA.
2388 if (readdir_attr_data &&
2389 readdir_attr_data->type == RDATTR_AAPL) {
2391 * OS X specific SMB2 extension negotiated via
2392 * AAPL create context: return UNIX mode in
2395 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2396 SSVAL(p, 0, aapl_mode);
2402 SBVAL(p,0,file_id); p += 8;
2403 status = srvstr_push(base_data, flags2, p,
2404 fname, PTR_DIFF(end_data, p),
2405 STR_TERMINATE_ASCII, &len);
2406 if (!NT_STATUS_IS_OK(status)) {
2412 len = PTR_DIFF(p, pdata);
2413 pad = (len + (align-1)) & ~(align-1);
2415 * offset to the next entry, the caller
2416 * will overwrite it for the last entry
2417 * that's why we always include the padding
2421 * set padding to zero
2424 memset(p, 0, pad - len);
2431 /* CIFS UNIX Extension. */
2433 case SMB_FIND_FILE_UNIX:
2434 case SMB_FIND_FILE_UNIX_INFO2:
2436 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2438 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2440 if (info_level == SMB_FIND_FILE_UNIX) {
2441 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2442 p = store_file_unix_basic(conn, p,
2443 NULL, &smb_fname->st);
2444 status = srvstr_push(base_data, flags2, p,
2445 fname, PTR_DIFF(end_data, p),
2446 STR_TERMINATE, &len);
2447 if (!NT_STATUS_IS_OK(status)) {
2451 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2452 p = store_file_unix_basic_info2(conn, p,
2453 NULL, &smb_fname->st);
2456 status = srvstr_push(base_data, flags2, p, fname,
2457 PTR_DIFF(end_data, p), 0, &len);
2458 if (!NT_STATUS_IS_OK(status)) {
2461 SIVAL(nameptr, 0, len);
2466 len = PTR_DIFF(p, pdata);
2467 pad = (len + (align-1)) & ~(align-1);
2469 * offset to the next entry, the caller
2470 * will overwrite it for the last entry
2471 * that's why we always include the padding
2475 * set padding to zero
2478 memset(p, 0, pad - len);
2483 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2488 return NT_STATUS_INVALID_LEVEL;
2491 if (PTR_DIFF(p,pdata) > space_remaining) {
2492 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2493 "(wanted %u, had %d)\n",
2494 (unsigned int)PTR_DIFF(p,pdata),
2496 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2499 /* Setup the last entry pointer, as an offset from base_data */
2500 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2501 /* Advance the data pointer to the next slot */
2504 return NT_STATUS_OK;
2507 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2508 connection_struct *conn,
2509 struct dptr_struct *dirptr,
2511 const char *path_mask,
2514 int requires_resume_key,
2523 int space_remaining,
2524 struct smb_filename **_smb_fname,
2525 bool *got_exact_match,
2526 int *_last_entry_off,
2527 struct ea_list *name_list,
2528 struct file_id *file_id)
2531 const char *mask = NULL;
2532 long prev_dirpos = 0;
2535 struct smb_filename *smb_fname = NULL;
2536 struct smbd_dirptr_lanman2_state state;
2538 uint64_t last_entry_off = 0;
2540 enum mangled_names_options mangled_names;
2541 bool marshall_with_83_names;
2543 mangled_names = lp_mangled_names(conn->params);
2547 state.info_level = info_level;
2548 if (mangled_names != MANGLED_NAMES_NO) {
2549 state.check_mangled_names = true;
2551 state.has_wild = dptr_has_wild(dirptr);
2552 state.got_exact_match = false;
2554 *got_exact_match = false;
2556 p = strrchr_m(path_mask,'/');
2567 ok = smbd_dirptr_get_entry(ctx,
2574 smbd_dirptr_lanman2_match_fn,
2575 smbd_dirptr_lanman2_mode_fn,
2582 return NT_STATUS_END_OF_FILE;
2585 *got_exact_match = state.got_exact_match;
2587 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2589 status = smbd_marshall_dir_entry(ctx,
2594 marshall_with_83_names,
2595 requires_resume_key,
2606 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2607 DEBUG(1,("Conversion error: illegal character: %s\n",
2608 smb_fname_str_dbg(smb_fname)));
2611 if (file_id != NULL) {
2612 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2615 if (!NT_STATUS_IS_OK(status) &&
2616 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2618 TALLOC_FREE(smb_fname);
2623 if (_smb_fname != NULL) {
2624 struct smb_filename *name = NULL;
2626 name = synthetic_smb_fname(ctx,
2633 TALLOC_FREE(smb_fname);
2635 return NT_STATUS_NO_MEMORY;
2640 TALLOC_FREE(smb_fname);
2643 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2644 dptr_SeekDir(dirptr, prev_dirpos);
2648 *_last_entry_off = last_entry_off;
2649 return NT_STATUS_OK;
2652 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2653 connection_struct *conn,
2654 struct dptr_struct *dirptr,
2656 const char *path_mask,
2659 bool requires_resume_key,
2665 int space_remaining,
2666 bool *got_exact_match,
2667 int *last_entry_off,
2668 struct ea_list *name_list)
2671 const bool do_pad = true;
2673 if (info_level >= 1 && info_level <= 3) {
2674 /* No alignment on earlier info levels. */
2678 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2679 path_mask, dirtype, info_level,
2680 requires_resume_key, dont_descend, ask_sharemode,
2681 true, align, do_pad,
2682 ppdata, base_data, end_data,
2686 last_entry_off, name_list, NULL);
2689 /****************************************************************************
2690 Reply to a TRANS2_FINDFIRST.
2691 ****************************************************************************/
2693 static void call_trans2findfirst(connection_struct *conn,
2694 struct smb_request *req,
2695 char **pparams, int total_params,
2696 char **ppdata, int total_data,
2697 unsigned int max_data_bytes)
2699 /* We must be careful here that we don't return more than the
2700 allowed number of data bytes. If this means returning fewer than
2701 maxentries then so be it. We assume that the redirector has
2702 enough room for the fixed number of parameter bytes it has
2704 struct smb_filename *smb_dname = NULL;
2705 char *params = *pparams;
2706 char *pdata = *ppdata;
2710 uint16_t findfirst_flags;
2711 bool close_after_first;
2713 bool requires_resume_key;
2715 char *directory = NULL;
2718 int last_entry_off=0;
2722 bool finished = False;
2723 bool dont_descend = False;
2724 bool out_of_space = False;
2725 int space_remaining;
2726 struct ea_list *ea_list = NULL;
2727 NTSTATUS ntstatus = NT_STATUS_OK;
2728 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2729 struct smbd_server_connection *sconn = req->sconn;
2730 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2731 ucf_flags_from_smb_request(req);
2732 bool backup_priv = false;
2733 bool as_root = false;
2734 files_struct *fsp = NULL;
2735 const struct loadparm_substitution *lp_sub =
2736 loadparm_s3_global_substitution();
2739 if (total_params < 13) {
2740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2744 dirtype = SVAL(params,0);
2745 maxentries = SVAL(params,2);
2746 findfirst_flags = SVAL(params,4);
2747 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2748 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2749 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2750 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2751 security_token_has_privilege(get_current_nttok(conn),
2754 info_level = SVAL(params,6);
2756 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2757 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2758 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2760 info_level, max_data_bytes));
2763 /* W2K3 seems to treat zero as 1. */
2767 switch (info_level) {
2768 case SMB_FIND_INFO_STANDARD:
2769 case SMB_FIND_EA_SIZE:
2770 case SMB_FIND_EA_LIST:
2771 case SMB_FIND_FILE_DIRECTORY_INFO:
2772 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2773 case SMB_FIND_FILE_NAMES_INFO:
2774 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2775 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2776 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2778 case SMB_FIND_FILE_UNIX:
2779 case SMB_FIND_FILE_UNIX_INFO2:
2780 if (!lp_unix_extensions()) {
2781 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2790 if (req->posix_pathnames) {
2791 /* Always use filesystem for UNIX mtime query. */
2792 ask_sharemode = false;
2795 if (req->posix_pathnames) {
2796 srvstr_get_path_posix(talloc_tos(),
2805 srvstr_get_path(talloc_tos(),
2814 if (!NT_STATUS_IS_OK(ntstatus)) {
2815 reply_nterror(req, ntstatus);
2822 ntstatus = filename_convert_with_privilege(talloc_tos(),
2829 ntstatus = filename_convert(talloc_tos(), conn,
2836 if (!NT_STATUS_IS_OK(ntstatus)) {
2837 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2838 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2839 ERRSRV, ERRbadpath);
2842 reply_nterror(req, ntstatus);
2846 mask = get_original_lcomp(talloc_tos(),
2851 reply_nterror(req, NT_STATUS_NO_MEMORY);
2855 directory = smb_dname->base_name;
2857 p = strrchr_m(directory,'/');
2859 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2860 if((directory[0] == '.') && (directory[1] == '\0')) {
2861 mask = talloc_strdup(talloc_tos(),"*");
2863 reply_nterror(req, NT_STATUS_NO_MEMORY);
2871 if (p == NULL || p == directory) {
2872 struct smb_filename *old_name = smb_dname;
2874 /* Ensure we don't have a directory name of "". */
2875 smb_dname = synthetic_smb_fname(talloc_tos(),
2881 TALLOC_FREE(old_name);
2882 if (smb_dname == NULL) {
2883 reply_nterror(req, NT_STATUS_NO_MEMORY);
2886 directory = smb_dname->base_name;
2889 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2891 if (info_level == SMB_FIND_EA_LIST) {
2894 if (total_data < 4) {
2895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2899 ea_size = IVAL(pdata,0);
2900 if (ea_size != total_data) {
2901 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2902 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2907 if (!lp_ea_support(SNUM(conn))) {
2908 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2912 /* Pull out the list of names. */
2913 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2920 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2925 *ppdata = (char *)SMB_REALLOC(
2926 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2927 if(*ppdata == NULL ) {
2928 reply_nterror(req, NT_STATUS_NO_MEMORY);
2932 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2934 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2937 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2938 /* Realloc the params space */
2939 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2940 if (*pparams == NULL) {
2941 reply_nterror(req, NT_STATUS_NO_MEMORY);
2947 * As we've cut off the last component from
2948 * smb_fname we need to re-stat smb_dname
2949 * so FILE_OPEN disposition knows the directory
2952 if (req->posix_pathnames) {
2953 ret = SMB_VFS_LSTAT(conn, smb_dname);
2955 ret = SMB_VFS_STAT(conn, smb_dname);
2959 ntstatus = map_nt_error_from_unix(errno);
2960 reply_nterror(req, ntstatus);
2965 * Open an fsp on this directory for the dptr.
2967 ntstatus = SMB_VFS_CREATE_FILE(
2970 smb_dname, /* dname */
2971 FILE_LIST_DIRECTORY, /* access_mask */
2973 FILE_SHARE_WRITE, /* share_access */
2974 FILE_OPEN, /* create_disposition*/
2975 FILE_DIRECTORY_FILE, /* create_options */
2976 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2977 NO_OPLOCK, /* oplock_request */
2979 0, /* allocation_size */
2980 0, /* private_flags */
2985 NULL, /* in_context */
2986 NULL);/* out_context */
2988 if (!NT_STATUS_IS_OK(ntstatus)) {
2989 DBG_ERR("failed to open directory %s\n",
2990 smb_fname_str_dbg(smb_dname));
2991 reply_nterror(req, ntstatus);
2995 /* Save the wildcard match and attribs we are using on this directory -
2996 needed as lanman2 assumes these are being saved between calls */
2998 ntstatus = dptr_create(conn,
3008 if (!NT_STATUS_IS_OK(ntstatus)) {
3010 * Use NULL here for the first parameter (req)
3011 * as this is not a client visible handle so
3012 * can'tbe part of an SMB1 chain.
3014 close_file(NULL, fsp, NORMAL_CLOSE);
3016 reply_nterror(req, ntstatus);
3021 /* Remember this in case we have
3022 to do a findnext. */
3023 dptr_set_priv(fsp->dptr);
3026 dptr_num = dptr_dnum(fsp->dptr);
3027 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3029 /* We don't need to check for VOL here as this is returned by
3030 a different TRANS2 call. */
3032 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3033 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3034 if (in_list(directory,
3035 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3036 conn->case_sensitive)) {
3037 dont_descend = True;
3041 space_remaining = max_data_bytes;
3042 out_of_space = False;
3044 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3045 bool got_exact_match = False;
3047 /* this is a heuristic to avoid seeking the dirptr except when
3048 absolutely necessary. It allows for a filename of about 40 chars */
3049 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3050 out_of_space = True;
3053 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3057 mask,dirtype,info_level,
3058 requires_resume_key,dont_descend,
3063 &last_entry_off, ea_list);
3064 if (NT_STATUS_EQUAL(ntstatus,
3065 NT_STATUS_ILLEGAL_CHARACTER)) {
3067 * Bad character conversion on name. Ignore this
3072 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3073 out_of_space = true;
3075 finished = !NT_STATUS_IS_OK(ntstatus);
3079 if (!finished && !out_of_space)
3083 * As an optimisation if we know we aren't looking
3084 * for a wildcard name (ie. the name matches the wildcard exactly)
3085 * then we can finish on any (first) match.
3086 * This speeds up large directory searches. JRA.
3092 /* Ensure space_remaining never goes -ve. */
3093 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3094 space_remaining = 0;
3095 out_of_space = true;
3097 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3101 /* Check if we can close the dirptr */
3102 if(close_after_first || (finished && close_if_end)) {
3103 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3105 close_file(NULL, fsp, NORMAL_CLOSE);
3110 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3111 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3112 * the protocol level is less than NT1. Tested with smbclient. JRA.
3113 * This should fix the OS/2 client bug #2335.
3116 if(numentries == 0) {
3119 * We may have already closed the file in the
3120 * close_after_first or finished case above.
3123 close_file(NULL, fsp, NORMAL_CLOSE);
3126 if (get_Protocol() < PROTOCOL_NT1) {
3127 reply_force_doserror(req, ERRDOS, ERRnofiles);
3130 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3131 ERRDOS, ERRbadfile);
3136 /* At this point pdata points to numentries directory entries. */
3138 /* Set up the return parameter block */
3139 SSVAL(params,0,dptr_num);
3140 SSVAL(params,2,numentries);
3141 SSVAL(params,4,finished);
3142 SSVAL(params,6,0); /* Never an EA error */
3143 SSVAL(params,8,last_entry_off);
3145 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3148 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3149 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3151 reply_nterror(req, NT_STATUS_NO_MEMORY);
3155 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3156 smb_fn_name(req->cmd),
3157 mask, directory, dirtype, numentries ) );
3160 * Force a name mangle here to ensure that the
3161 * mask as an 8.3 name is top of the mangled cache.
3162 * The reasons for this are subtle. Don't remove
3163 * this code unless you know what you are doing
3164 * (see PR#13758). JRA.
3167 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3168 char mangled_name[13];
3169 name_to_8_3(mask, mangled_name, True, conn->params);
3177 TALLOC_FREE(smb_dname);
3181 /****************************************************************************
3182 Reply to a TRANS2_FINDNEXT.
3183 ****************************************************************************/
3185 static void call_trans2findnext(connection_struct *conn,
3186 struct smb_request *req,
3187 char **pparams, int total_params,
3188 char **ppdata, int total_data,
3189 unsigned int max_data_bytes)
3191 /* We must be careful here that we don't return more than the
3192 allowed number of data bytes. If this means returning fewer than
3193 maxentries then so be it. We assume that the redirector has
3194 enough room for the fixed number of parameter bytes it has
3196 char *params = *pparams;
3197 char *pdata = *ppdata;
3201 uint16_t info_level;
3202 uint32_t resume_key;
3203 uint16_t findnext_flags;
3204 bool close_after_request;
3206 bool requires_resume_key;
3208 char *resume_name = NULL;
3209 const char *mask = NULL;
3210 const char *directory = NULL;
3214 int i, last_entry_off=0;
3215 bool finished = False;
3216 bool dont_descend = False;
3217 bool out_of_space = False;
3218 int space_remaining;
3219 struct ea_list *ea_list = NULL;
3220 NTSTATUS ntstatus = NT_STATUS_OK;
3221 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3222 TALLOC_CTX *ctx = talloc_tos();
3223 struct smbd_server_connection *sconn = req->sconn;
3224 bool backup_priv = false;
3225 bool as_root = false;
3226 files_struct *fsp = NULL;
3227 const struct loadparm_substitution *lp_sub =
3228 loadparm_s3_global_substitution();
3230 if (total_params < 13) {
3231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3235 dptr_num = SVAL(params,0);
3236 maxentries = SVAL(params,2);
3237 info_level = SVAL(params,4);
3238 resume_key = IVAL(params,6);
3239 findnext_flags = SVAL(params,10);
3240 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3241 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3242 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3243 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3245 if (!continue_bit) {
3246 /* We only need resume_name if continue_bit is zero. */
3247 if (req->posix_pathnames) {
3248 srvstr_get_path_posix(ctx,
3257 srvstr_get_path(ctx,
3266 if (!NT_STATUS_IS_OK(ntstatus)) {
3267 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3268 complain (it thinks we're asking for the directory above the shared
3269 path or an invalid name). Catch this as the resume name is only compared, never used in
3270 a file access. JRA. */
3271 srvstr_pull_talloc(ctx, params, req->flags2,
3272 &resume_name, params+12,
3276 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3277 reply_nterror(req, ntstatus);
3283 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3284 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3285 resume_key = %d resume name = %s continue=%d level = %d\n",
3286 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3287 requires_resume_key, resume_key,
3288 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3291 /* W2K3 seems to treat zero as 1. */
3295 switch (info_level) {
3296 case SMB_FIND_INFO_STANDARD:
3297 case SMB_FIND_EA_SIZE:
3298 case SMB_FIND_EA_LIST:
3299 case SMB_FIND_FILE_DIRECTORY_INFO:
3300 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3301 case SMB_FIND_FILE_NAMES_INFO:
3302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3303 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3304 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3306 case SMB_FIND_FILE_UNIX:
3307 case SMB_FIND_FILE_UNIX_INFO2:
3308 /* Always use filesystem for UNIX mtime query. */
3309 ask_sharemode = false;
3310 if (!lp_unix_extensions()) {
3311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3316 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3320 if (info_level == SMB_FIND_EA_LIST) {
3323 if (total_data < 4) {
3324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3328 ea_size = IVAL(pdata,0);
3329 if (ea_size != total_data) {
3330 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3336 if (!lp_ea_support(SNUM(conn))) {
3337 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3341 /* Pull out the list of names. */
3342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3349 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3354 *ppdata = (char *)SMB_REALLOC(
3355 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3356 if(*ppdata == NULL) {
3357 reply_nterror(req, NT_STATUS_NO_MEMORY);
3362 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3365 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3368 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3369 /* Realloc the params space */
3370 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3371 if(*pparams == NULL ) {
3372 reply_nterror(req, NT_STATUS_NO_MEMORY);
3378 /* Check that the dptr is valid */
3379 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3381 reply_nterror(req, STATUS_NO_MORE_FILES);
3385 directory = dptr_path(sconn, dptr_num);
3387 /* Get the wildcard mask from the dptr */
3388 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3389 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3390 reply_nterror(req, STATUS_NO_MORE_FILES);
3394 /* Get the attr mask from the dptr */
3395 dirtype = dptr_attr(sconn, dptr_num);
3397 backup_priv = dptr_get_priv(fsp->dptr);
3399 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3400 "backup_priv = %d\n",
3401 dptr_num, mask, dirtype,
3403 dptr_TellDir(fsp->dptr),
3406 /* We don't need to check for VOL here as this is returned by
3407 a different TRANS2 call. */
3409 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3410 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3411 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3412 dont_descend = True;
3415 space_remaining = max_data_bytes;
3416 out_of_space = False;
3424 * Seek to the correct position. We no longer use the resume key but
3425 * depend on the last file name instead.
3428 if(!continue_bit && resume_name && *resume_name) {
3431 long current_pos = 0;
3433 * Remember, name_to_8_3 is called by
3434 * get_lanman2_dir_entry(), so the resume name
3435 * could be mangled. Ensure we check the unmangled name.
3438 if (mangle_is_mangled(resume_name, conn->params)) {
3439 char *new_resume_name = NULL;
3440 mangle_lookup_name_from_8_3(ctx,
3444 if (new_resume_name) {
3445 resume_name = new_resume_name;
3450 * Fix for NT redirector problem triggered by resume key indexes
3451 * changing between directory scans. We now return a resume key of 0
3452 * and instead look for the filename to continue from (also given
3453 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3454 * findfirst/findnext (as is usual) then the directory pointer
3455 * should already be at the correct place.
3458 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3459 } /* end if resume_name && !continue_bit */
3461 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3462 bool got_exact_match = False;
3464 /* this is a heuristic to avoid seeking the fsp->dptr except when
3465 absolutely necessary. It allows for a filename of about 40 chars */
3466 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3467 out_of_space = True;
3470 ntstatus = get_lanman2_dir_entry(ctx,
3474 mask,dirtype,info_level,
3475 requires_resume_key,dont_descend,
3480 &last_entry_off, ea_list);
3481 if (NT_STATUS_EQUAL(ntstatus,
3482 NT_STATUS_ILLEGAL_CHARACTER)) {
3484 * Bad character conversion on name. Ignore this
3489 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3490 out_of_space = true;
3492 finished = !NT_STATUS_IS_OK(ntstatus);
3496 if (!finished && !out_of_space)
3500 * As an optimisation if we know we aren't looking
3501 * for a wildcard name (ie. the name matches the wildcard exactly)
3502 * then we can finish on any (first) match.
3503 * This speeds up large directory searches. JRA.
3509 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3512 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3513 smb_fn_name(req->cmd),
3514 mask, directory, dirtype, numentries ) );
3516 /* Check if we can close the fsp->dptr */
3517 if(close_after_request || (finished && close_if_end)) {
3518 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3520 close_file(NULL, fsp, NORMAL_CLOSE);
3528 /* Set up the return parameter block */
3529 SSVAL(params,0,numentries);
3530 SSVAL(params,2,finished);
3531 SSVAL(params,4,0); /* Never an EA error */
3532 SSVAL(params,6,last_entry_off);
3534 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3540 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3542 const struct loadparm_substitution *lp_sub =
3543 loadparm_s3_global_substitution();
3545 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3549 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3551 SMB_ASSERT(extended_info != NULL);
3553 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3554 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3555 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3556 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3557 #ifdef SAMBA_VERSION_REVISION
3558 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3560 extended_info->samba_subversion = 0;
3561 #ifdef SAMBA_VERSION_RC_RELEASE
3562 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3564 #ifdef SAMBA_VERSION_PRE_RELEASE
3565 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3568 #ifdef SAMBA_VERSION_VENDOR_PATCH
3569 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3571 extended_info->samba_gitcommitdate = 0;
3572 #ifdef SAMBA_VERSION_COMMIT_TIME
3573 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3576 memset(extended_info->samba_version_string, 0,
3577 sizeof(extended_info->samba_version_string));
3579 snprintf (extended_info->samba_version_string,
3580 sizeof(extended_info->samba_version_string),
3581 "%s", samba_version_string());
3584 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3585 connection_struct *conn,
3586 TALLOC_CTX *mem_ctx,
3587 uint16_t info_level,
3589 unsigned int max_data_bytes,
3590 size_t *fixed_portion,
3591 struct smb_filename *fname,
3595 const struct loadparm_substitution *lp_sub =
3596 loadparm_s3_global_substitution();
3597 char *pdata, *end_data;
3600 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3601 int snum = SNUM(conn);
3602 const char *fstype = lp_fstype(SNUM(conn));
3603 const char *filename = NULL;
3604 const uint64_t bytes_per_sector = 512;
3605 uint32_t additional_flags = 0;
3606 struct smb_filename smb_fname;
3608 NTSTATUS status = NT_STATUS_OK;
3611 if (fname == NULL || fname->base_name == NULL) {
3614 filename = fname->base_name;
3618 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3619 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3620 "info level (0x%x) on IPC$.\n",
3621 (unsigned int)info_level));
3622 return NT_STATUS_ACCESS_DENIED;
3626 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3628 smb_fname = (struct smb_filename) {
3629 .base_name = discard_const_p(char, filename),
3630 .flags = fname ? fname->flags : 0,
3631 .twrp = fname ? fname->twrp : 0,
3634 if(info_level != SMB_FS_QUOTA_INFORMATION
3635 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3636 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3637 return map_nt_error_from_unix(errno);
3642 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3643 return NT_STATUS_INVALID_PARAMETER;
3646 *ppdata = (char *)SMB_REALLOC(
3647 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3648 if (*ppdata == NULL) {
3649 return NT_STATUS_NO_MEMORY;
3653 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3654 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3658 switch (info_level) {
3659 case SMB_INFO_ALLOCATION:
3661 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3663 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3665 if (df_ret == (uint64_t)-1) {
3666 return map_nt_error_from_unix(errno);
3669 block_size = lp_block_size(snum);
3670 if (bsize < block_size) {
3671 uint64_t factor = block_size/bsize;
3676 if (bsize > block_size) {
3677 uint64_t factor = bsize/block_size;
3682 sectors_per_unit = bsize/bytes_per_sector;
3684 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3685 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3686 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3689 * For large drives, return max values and not modulo.
3691 dsize = MIN(dsize, UINT32_MAX);
3692 dfree = MIN(dfree, UINT32_MAX);
3694 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3695 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3696 SIVAL(pdata,l1_cUnit,dsize);
3697 SIVAL(pdata,l1_cUnitAvail,dfree);
3698 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3702 case SMB_INFO_VOLUME:
3703 /* Return volume name */
3705 * Add volume serial number - hash of a combination of
3706 * the called hostname and the service name.
3708 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3710 * Win2k3 and previous mess this up by sending a name length
3711 * one byte short. I believe only older clients (OS/2 Win9x) use
3712 * this call so try fixing this by adding a terminating null to
3713 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3715 status = srvstr_push(
3717 pdata+l2_vol_szVolLabel, vname,
3718 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3719 STR_NOALIGN|STR_TERMINATE, &len);
3720 if (!NT_STATUS_IS_OK(status)) {
3723 SCVAL(pdata,l2_vol_cch,len);
3724 data_len = l2_vol_szVolLabel + len;
3725 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3726 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3727 (unsigned)len, vname));
3730 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3731 case SMB_FS_ATTRIBUTE_INFORMATION:
3733 additional_flags = 0;
3734 #if defined(HAVE_SYS_QUOTAS)
3735 additional_flags |= FILE_VOLUME_QUOTAS;
3738 if(lp_nt_acl_support(SNUM(conn))) {
3739 additional_flags |= FILE_PERSISTENT_ACLS;
3742 /* Capabilities are filled in at connection time through STATVFS call */
3743 additional_flags |= conn->fs_capabilities;
3744 additional_flags |= lp_parm_int(conn->params->service,
3745 "share", "fake_fscaps",
3748 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3749 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3750 additional_flags); /* FS ATTRIBUTES */
3752 SIVAL(pdata,4,255); /* Max filename component length */
3753 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3754 and will think we can't do long filenames */
3755 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3756 PTR_DIFF(end_data, pdata+12),
3758 if (!NT_STATUS_IS_OK(status)) {
3762 data_len = 12 + len;
3763 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3764 /* the client only requested a portion of the
3766 data_len = max_data_bytes;
3767 status = STATUS_BUFFER_OVERFLOW;
3769 *fixed_portion = 16;
3772 case SMB_QUERY_FS_LABEL_INFO:
3773 case SMB_FS_LABEL_INFORMATION:
3774 status = srvstr_push(pdata, flags2, pdata+4, vname,
3775 PTR_DIFF(end_data, pdata+4), 0, &len);
3776 if (!NT_STATUS_IS_OK(status)) {
3783 case SMB_QUERY_FS_VOLUME_INFO:
3784 case SMB_FS_VOLUME_INFORMATION:
3787 * Add volume serial number - hash of a combination of
3788 * the called hostname and the service name.
3790 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3791 (str_checksum(get_local_machine_name())<<16));
3793 /* Max label len is 32 characters. */
3794 status = srvstr_push(pdata, flags2, pdata+18, vname,
3795 PTR_DIFF(end_data, pdata+18),
3797 if (!NT_STATUS_IS_OK(status)) {
3800 SIVAL(pdata,12,len);
3803 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3804 (int)strlen(vname),vname,
3805 lp_servicename(talloc_tos(), lp_sub, snum)));
3806 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3807 /* the client only requested a portion of the
3809 data_len = max_data_bytes;
3810 status = STATUS_BUFFER_OVERFLOW;
3812 *fixed_portion = 24;
3815 case SMB_QUERY_FS_SIZE_INFO:
3816 case SMB_FS_SIZE_INFORMATION:
3818 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3820 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3822 if (df_ret == (uint64_t)-1) {
3823 return map_nt_error_from_unix(errno);
3825 block_size = lp_block_size(snum);
3826 if (bsize < block_size) {
3827 uint64_t factor = block_size/bsize;
3832 if (bsize > block_size) {
3833 uint64_t factor = bsize/block_size;
3838 sectors_per_unit = bsize/bytes_per_sector;
3839 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3840 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3841 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3842 SBIG_UINT(pdata,0,dsize);
3843 SBIG_UINT(pdata,8,dfree);
3844 SIVAL(pdata,16,sectors_per_unit);
3845 SIVAL(pdata,20,bytes_per_sector);
3846 *fixed_portion = 24;
3850 case SMB_FS_FULL_SIZE_INFORMATION:
3852 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3854 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3856 if (df_ret == (uint64_t)-1) {
3857 return map_nt_error_from_unix(errno);
3859 block_size = lp_block_size(snum);
3860 if (bsize < block_size) {
3861 uint64_t factor = block_size/bsize;
3866 if (bsize > block_size) {
3867 uint64_t factor = bsize/block_size;
3872 sectors_per_unit = bsize/bytes_per_sector;
3873 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3874 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3875 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3876 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3877 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3878 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3879 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3880 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3881 *fixed_portion = 32;
3885 case SMB_QUERY_FS_DEVICE_INFO:
3886 case SMB_FS_DEVICE_INFORMATION:
3888 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3890 if (!CAN_WRITE(conn)) {
3891 characteristics |= FILE_READ_ONLY_DEVICE;
3894 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3895 SIVAL(pdata,4,characteristics);
3900 #ifdef HAVE_SYS_QUOTAS
3901 case SMB_FS_QUOTA_INFORMATION:
3903 * what we have to send --metze:
3905 * Unknown1: 24 NULL bytes
3906 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3907 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3908 * Quota Flags: 2 byte :
3909 * Unknown3: 6 NULL bytes
3913 * details for Quota Flags:
3915 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3916 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3917 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3918 * 0x0001 Enable Quotas: enable quota for this fs
3922 /* we need to fake up a fsp here,
3923 * because its not send in this call
3926 SMB_NTQUOTA_STRUCT quotas;
3929 ZERO_STRUCT(quotas);
3932 fsp.fnum = FNUM_FIELD_INVALID;
3935 if (get_current_uid(conn) != 0) {
3936 DEBUG(0,("get_user_quota: access_denied "
3937 "service [%s] user [%s]\n",
3938 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3939 conn->session_info->unix_info->unix_name));
3940 return NT_STATUS_ACCESS_DENIED;
3943 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3945 if (!NT_STATUS_IS_OK(status)) {
3946 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3952 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3953 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3955 /* Unknown1 24 NULL bytes*/
3956 SBIG_UINT(pdata,0,(uint64_t)0);
3957 SBIG_UINT(pdata,8,(uint64_t)0);
3958 SBIG_UINT(pdata,16,(uint64_t)0);
3960 /* Default Soft Quota 8 bytes */
3961 SBIG_UINT(pdata,24,quotas.softlim);
3963 /* Default Hard Quota 8 bytes */
3964 SBIG_UINT(pdata,32,quotas.hardlim);
3966 /* Quota flag 2 bytes */
3967 SSVAL(pdata,40,quotas.qflags);
3969 /* Unknown3 6 NULL bytes */
3975 #endif /* HAVE_SYS_QUOTAS */
3976 case SMB_FS_OBJECTID_INFORMATION:
3978 unsigned char objid[16];
3979 struct smb_extended_info extended_info;
3980 memcpy(pdata,create_volume_objectid(conn, objid),16);
3981 samba_extended_info_version (&extended_info);
3982 SIVAL(pdata,16,extended_info.samba_magic);
3983 SIVAL(pdata,20,extended_info.samba_version);
3984 SIVAL(pdata,24,extended_info.samba_subversion);
3985 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3986 memcpy(pdata+36,extended_info.samba_version_string,28);
3991 case SMB_FS_SECTOR_SIZE_INFORMATION:
3995 * These values match a physical Windows Server 2012
3996 * share backed by NTFS atop spinning rust.
3998 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3999 /* logical_bytes_per_sector */
4000 SIVAL(pdata, 0, bytes_per_sector);
4001 /* phys_bytes_per_sector_atomic */
4002 SIVAL(pdata, 4, bytes_per_sector);
4003 /* phys_bytes_per_sector_perf */
4004 SIVAL(pdata, 8, bytes_per_sector);
4005 /* fs_effective_phys_bytes_per_sector_atomic */
4006 SIVAL(pdata, 12, bytes_per_sector);
4008 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4009 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4010 /* byte_off_sector_align */
4011 SIVAL(pdata, 20, 0);
4012 /* byte_off_partition_align */
4013 SIVAL(pdata, 24, 0);
4014 *fixed_portion = 28;
4020 * Query the version and capabilities of the CIFS UNIX extensions
4024 case SMB_QUERY_CIFS_UNIX_INFO:
4026 bool large_write = lp_min_receive_file_size() &&
4027 !srv_is_signing_active(xconn);
4028 bool large_read = !srv_is_signing_active(xconn);
4029 int encrypt_caps = 0;
4031 if (!lp_unix_extensions()) {
4032 return NT_STATUS_INVALID_LEVEL;
4035 switch (conn->encrypt_level) {
4036 case SMB_SIGNING_OFF:
4039 case SMB_SIGNING_DESIRED:
4040 case SMB_SIGNING_IF_REQUIRED:
4041 case SMB_SIGNING_DEFAULT:
4042 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4044 case SMB_SIGNING_REQUIRED:
4045 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4046 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4047 large_write = false;
4053 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4054 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4056 /* We have POSIX ACLs, pathname, encryption,
4057 * large read/write, and locking capability. */
4059 SBIG_UINT(pdata,4,((uint64_t)(
4060 CIFS_UNIX_POSIX_ACLS_CAP|
4061 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4062 CIFS_UNIX_FCNTL_LOCKS_CAP|
4063 CIFS_UNIX_EXTATTR_CAP|
4064 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4066 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4068 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4072 case SMB_QUERY_POSIX_FS_INFO:
4075 vfs_statvfs_struct svfs;
4077 if (!lp_unix_extensions()) {
4078 return NT_STATUS_INVALID_LEVEL;
4081 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4085 SIVAL(pdata,0,svfs.OptimalTransferSize);
4086 SIVAL(pdata,4,svfs.BlockSize);
4087 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4088 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4089 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4090 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4091 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4092 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4093 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4095 } else if (rc == EOPNOTSUPP) {
4096 return NT_STATUS_INVALID_LEVEL;
4097 #endif /* EOPNOTSUPP */
4099 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4100 return NT_STATUS_DOS(ERRSRV, ERRerror);
4105 case SMB_QUERY_POSIX_WHOAMI:
4111 if (!lp_unix_extensions()) {
4112 return NT_STATUS_INVALID_LEVEL;
4115 if (max_data_bytes < 40) {
4116 return NT_STATUS_BUFFER_TOO_SMALL;
4119 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4120 flags |= SMB_WHOAMI_GUEST;
4123 /* NOTE: 8 bytes for UID/GID, irrespective of native
4124 * platform size. This matches
4125 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4127 data_len = 4 /* flags */
4134 + 4 /* pad/reserved */
4135 + (conn->session_info->unix_token->ngroups * 8)
4137 + (conn->session_info->security_token->num_sids *
4141 SIVAL(pdata, 0, flags);
4142 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4144 (uint64_t)conn->session_info->unix_token->uid);
4145 SBIG_UINT(pdata, 16,
4146 (uint64_t)conn->session_info->unix_token->gid);
4149 if (data_len >= max_data_bytes) {
4150 /* Potential overflow, skip the GIDs and SIDs. */
4152 SIVAL(pdata, 24, 0); /* num_groups */
4153 SIVAL(pdata, 28, 0); /* num_sids */
4154 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4155 SIVAL(pdata, 36, 0); /* reserved */
4161 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4162 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4164 /* We walk the SID list twice, but this call is fairly
4165 * infrequent, and I don't expect that it's performance
4166 * sensitive -- jpeach
4168 for (i = 0, sid_bytes = 0;
4169 i < conn->session_info->security_token->num_sids; ++i) {
4170 sid_bytes += ndr_size_dom_sid(
4171 &conn->session_info->security_token->sids[i],
4175 /* SID list byte count */
4176 SIVAL(pdata, 32, sid_bytes);
4178 /* 4 bytes pad/reserved - must be zero */
4179 SIVAL(pdata, 36, 0);
4183 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4184 SBIG_UINT(pdata, data_len,
4185 (uint64_t)conn->session_info->unix_token->groups[i]);
4191 i < conn->session_info->security_token->num_sids; ++i) {
4192 int sid_len = ndr_size_dom_sid(
4193 &conn->session_info->security_token->sids[i],
4196 sid_linearize((uint8_t *)(pdata + data_len),
4198 &conn->session_info->security_token->sids[i]);
4199 data_len += sid_len;
4205 case SMB_MAC_QUERY_FS_INFO:
4207 * Thursby MAC extension... ONLY on NTFS filesystems
4208 * once we do streams then we don't need this
4210 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4212 SIVAL(pdata,84,0x100); /* Don't support mac... */
4218 return NT_STATUS_INVALID_LEVEL;
4221 *ret_data_len = data_len;
4225 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4226 struct smb_request *req,
4228 const DATA_BLOB *qdata)
4230 const struct loadparm_substitution *lp_sub =
4231 loadparm_s3_global_substitution();
4233 SMB_NTQUOTA_STRUCT quotas;
4235 ZERO_STRUCT(quotas);
4238 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4239 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4240 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4241 conn->session_info->unix_info->unix_name));
4242 return NT_STATUS_ACCESS_DENIED;
4245 if (!check_fsp_ntquota_handle(conn, req,
4247 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4248 return NT_STATUS_INVALID_HANDLE;
4251 /* note: normally there're 48 bytes,
4252 * but we didn't use the last 6 bytes for now
4255 if (qdata->length < 42) {
4256 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4257 (unsigned int)qdata->length));
4258 return NT_STATUS_INVALID_PARAMETER;
4261 /* unknown_1 24 NULL bytes in pdata*/
4263 /* the soft quotas 8 bytes (uint64_t)*/
4264 quotas.softlim = BVAL(qdata->data,24);
4266 /* the hard quotas 8 bytes (uint64_t)*/
4267 quotas.hardlim = BVAL(qdata->data,32);
4269 /* quota_flags 2 bytes **/
4270 quotas.qflags = SVAL(qdata->data,40);
4272 /* unknown_2 6 NULL bytes follow*/
4274 /* now set the quotas */
4275 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4276 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4277 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4278 status = map_nt_error_from_unix(errno);
4280 status = NT_STATUS_OK;
4285 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4286 struct smb_request *req,
4287 TALLOC_CTX *mem_ctx,
4288 uint16_t info_level,
4290 const DATA_BLOB *pdata)
4292 switch (info_level) {
4293 case SMB_FS_QUOTA_INFORMATION:
4295 return smb_set_fsquota(conn,
4304 return NT_STATUS_INVALID_LEVEL;
4307 /****************************************************************************
4308 Reply to a TRANS2_QFSINFO (query filesystem info).
4309 ****************************************************************************/
4311 static void call_trans2qfsinfo(connection_struct *conn,
4312 struct smb_request *req,
4313 char **pparams, int total_params,
4314 char **ppdata, int total_data,
4315 unsigned int max_data_bytes)
4317 char *params = *pparams;
4318 uint16_t info_level;
4320 size_t fixed_portion;
4323 if (total_params < 2) {
4324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4328 info_level = SVAL(params,0);
4330 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4331 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4332 DEBUG(0,("call_trans2qfsinfo: encryption required "
4333 "and info level 0x%x sent.\n",
4334 (unsigned int)info_level));
4335 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4340 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4342 status = smbd_do_qfsinfo(req->xconn, conn, req,
4349 if (!NT_STATUS_IS_OK(status)) {
4350 reply_nterror(req, status);
4354 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4357 DEBUG( 4, ( "%s info_level = %d\n",
4358 smb_fn_name(req->cmd), info_level) );
4363 /****************************************************************************
4364 Reply to a TRANS2_SETFSINFO (set filesystem info).
4365 ****************************************************************************/
4367 static void call_trans2setfsinfo(connection_struct *conn,
4368 struct smb_request *req,
4369 char **pparams, int total_params,
4370 char **ppdata, int total_data,
4371 unsigned int max_data_bytes)
4373 const struct loadparm_substitution *lp_sub =
4374 loadparm_s3_global_substitution();
4375 struct smbXsrv_connection *xconn = req->xconn;
4376 char *pdata = *ppdata;
4377 char *params = *pparams;
4378 uint16_t info_level;
4380 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4381 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4384 if (total_params < 4) {
4385 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4391 info_level = SVAL(params,2);
4394 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4395 info_level != SMB_SET_CIFS_UNIX_INFO) {
4396 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4397 "info level (0x%x) on IPC$.\n",
4398 (unsigned int)info_level));
4399 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4404 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4405 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4406 DEBUG(0,("call_trans2setfsinfo: encryption required "
4407 "and info level 0x%x sent.\n",
4408 (unsigned int)info_level));
4409 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4414 switch(info_level) {
4415 case SMB_SET_CIFS_UNIX_INFO:
4416 if (!lp_unix_extensions()) {
4417 DEBUG(2,("call_trans2setfsinfo: "
4418 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4419 "unix extensions off\n"));
4421 NT_STATUS_INVALID_LEVEL);
4425 /* There should be 12 bytes of capabilities set. */
4426 if (total_data < 12) {
4429 NT_STATUS_INVALID_PARAMETER);
4432 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4433 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4434 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4435 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4436 /* Just print these values for now. */
4437 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4438 "major = %u, minor = %u cap_low = 0x%x, "
4440 (unsigned int)xconn->
4441 smb1.unix_info.client_major,
4442 (unsigned int)xconn->
4443 smb1.unix_info.client_minor,
4444 (unsigned int)xconn->
4445 smb1.unix_info.client_cap_low,
4446 (unsigned int)xconn->
4447 smb1.unix_info.client_cap_high));
4449 /* Here is where we must switch to posix pathname processing... */
4450 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4451 lp_set_posix_pathnames();
4452 mangle_change_to_posix();
4455 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4456 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4457 /* Client that knows how to do posix locks,
4458 * but not posix open/mkdir operations. Set a
4459 * default type for read/write checks. */
4461 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4466 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4469 size_t param_len = 0;
4470 size_t data_len = total_data;
4472 if (!lp_unix_extensions()) {
4475 NT_STATUS_INVALID_LEVEL);
4479 if (lp_server_smb_encrypt(SNUM(conn)) ==
4480 SMB_ENCRYPTION_OFF) {
4483 NT_STATUS_NOT_SUPPORTED);
4487 if (xconn->smb1.echo_handler.trusted_fde) {
4488 DEBUG( 2,("call_trans2setfsinfo: "
4489 "request transport encryption disabled"
4490 "with 'fork echo handler = yes'\n"));
4493 NT_STATUS_NOT_SUPPORTED);
4497 DEBUG( 4,("call_trans2setfsinfo: "
4498 "request transport encryption.\n"));
4500 status = srv_request_encryption_setup(conn,
4501 (unsigned char **)ppdata,
4503 (unsigned char **)pparams,
4506 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4507 !NT_STATUS_IS_OK(status)) {
4508 reply_nterror(req, status);
4512 send_trans2_replies(conn, req,
4520 if (NT_STATUS_IS_OK(status)) {
4521 /* Server-side transport
4522 * encryption is now *on*. */
4523 status = srv_encryption_start(conn);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 char *reason = talloc_asprintf(talloc_tos(),
4526 "Failure in setting "
4527 "up encrypted transport: %s",
4529 exit_server_cleanly(reason);
4535 case SMB_FS_QUOTA_INFORMATION:
4539 .data = (uint8_t *)pdata,
4540 .length = total_data
4542 files_struct *fsp = NULL;
4543 fsp = file_fsp(req, SVAL(params,0));
4545 status = smb_set_fsquota(conn,
4549 if (!NT_STATUS_IS_OK(status)) {
4550 reply_nterror(req, status);
4556 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4558 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4564 * sending this reply works fine,
4565 * but I'm not sure it's the same
4566 * like windows do...
4569 reply_outbuf(req, 10, 0);
4572 #if defined(HAVE_POSIX_ACLS)
4573 /****************************************************************************
4574 Utility function to count the number of entries in a POSIX acl.
4575 ****************************************************************************/
4577 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4579 unsigned int ace_count = 0;
4580 int entry_id = SMB_ACL_FIRST_ENTRY;
4581 SMB_ACL_ENTRY_T entry;
4583 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4585 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4586 entry_id = SMB_ACL_NEXT_ENTRY;
4593 /****************************************************************************
4594 Utility function to marshall a POSIX acl into wire format.
4595 ****************************************************************************/
4597 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4599 int entry_id = SMB_ACL_FIRST_ENTRY;
4600 SMB_ACL_ENTRY_T entry;
4602 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4603 SMB_ACL_TAG_T tagtype;
4604 SMB_ACL_PERMSET_T permset;
4605 unsigned char perms = 0;
4606 unsigned int own_grp;
4609 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4610 entry_id = SMB_ACL_NEXT_ENTRY;
4613 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4614 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4618 if (sys_acl_get_permset(entry, &permset) == -1) {
4619 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4623 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4624 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4625 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4627 SCVAL(pdata,1,perms);
4630 case SMB_ACL_USER_OBJ:
4631 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4632 own_grp = (unsigned int)pst->st_ex_uid;
4633 SIVAL(pdata,2,own_grp);
4638 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4640 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4643 own_grp = (unsigned int)*puid;
4644 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4645 SIVAL(pdata,2,own_grp);
4649 case SMB_ACL_GROUP_OBJ:
4650 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4651 own_grp = (unsigned int)pst->st_ex_gid;
4652 SIVAL(pdata,2,own_grp);
4657 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4659 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4662 own_grp = (unsigned int)*pgid;
4663 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4664 SIVAL(pdata,2,own_grp);
4669 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4670 SIVAL(pdata,2,0xFFFFFFFF);
4671 SIVAL(pdata,6,0xFFFFFFFF);
4674 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4675 SIVAL(pdata,2,0xFFFFFFFF);
4676 SIVAL(pdata,6,0xFFFFFFFF);
4679 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4682 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4689 /****************************************************************************
4690 Store the FILE_UNIX_BASIC info.
4691 ****************************************************************************/
4693 static char *store_file_unix_basic(connection_struct *conn,
4696 const SMB_STRUCT_STAT *psbuf)
4700 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4701 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4703 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4706 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4709 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4710 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4711 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4714 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4718 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4722 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4725 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4726 devno = psbuf->st_ex_rdev;
4728 devno = psbuf->st_ex_dev;
4731 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4735 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4739 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4742 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4746 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4753 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4754 * the chflags(2) (or equivalent) flags.
4756 * XXX: this really should be behind the VFS interface. To do this, we would
4757 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4758 * Each VFS module could then implement its own mapping as appropriate for the
4759 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4761 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4765 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4769 { UF_IMMUTABLE, EXT_IMMUTABLE },
4773 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4777 { UF_HIDDEN, EXT_HIDDEN },
4780 /* Do not remove. We need to guarantee that this array has at least one
4781 * entry to build on HP-UX.
4787 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4788 uint32_t *smb_fflags, uint32_t *smb_fmask)
4792 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4793 *smb_fmask |= info2_flags_map[i].smb_fflag;
4794 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4795 *smb_fflags |= info2_flags_map[i].smb_fflag;
4800 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4801 const uint32_t smb_fflags,
4802 const uint32_t smb_fmask,
4805 uint32_t max_fmask = 0;
4808 *stat_fflags = psbuf->st_ex_flags;
4810 /* For each flags requested in smb_fmask, check the state of the
4811 * corresponding flag in smb_fflags and set or clear the matching
4815 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4816 max_fmask |= info2_flags_map[i].smb_fflag;
4817 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4818 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4819 *stat_fflags |= info2_flags_map[i].stat_fflag;
4821 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4826 /* If smb_fmask is asking to set any bits that are not supported by
4827 * our flag mappings, we should fail.
4829 if ((smb_fmask & max_fmask) != smb_fmask) {
4837 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4838 * of file flags and birth (create) time.
4840 static char *store_file_unix_basic_info2(connection_struct *conn,
4843 const SMB_STRUCT_STAT *psbuf)
4845 uint32_t file_flags = 0;
4846 uint32_t flags_mask = 0;
4848 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4850 /* Create (birth) time 64 bit */
4851 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4854 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4855 SIVAL(pdata, 0, file_flags); /* flags */
4856 SIVAL(pdata, 4, flags_mask); /* mask */
4862 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4863 const struct stream_struct *streams,
4865 unsigned int max_data_bytes,
4866 unsigned int *data_size)
4869 unsigned int ofs = 0;
4871 if (max_data_bytes < 32) {
4872 return NT_STATUS_INFO_LENGTH_MISMATCH;
4875 for (i = 0; i < num_streams; i++) {
4876 unsigned int next_offset;
4878 smb_ucs2_t *namebuf;
4880 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4881 streams[i].name, &namelen) ||
4884 return NT_STATUS_INVALID_PARAMETER;
4888 * name_buf is now null-terminated, we need to marshall as not
4895 * We cannot overflow ...
4897 if ((ofs + 24 + namelen) > max_data_bytes) {
4898 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4900 TALLOC_FREE(namebuf);
4901 return STATUS_BUFFER_OVERFLOW;
4904 SIVAL(data, ofs+4, namelen);
4905 SOFF_T(data, ofs+8, streams[i].size);
4906 SOFF_T(data, ofs+16, streams[i].alloc_size);
4907 memcpy(data+ofs+24, namebuf, namelen);
4908 TALLOC_FREE(namebuf);
4910 next_offset = ofs + 24 + namelen;
4912 if (i == num_streams-1) {
4913 SIVAL(data, ofs, 0);
4916 unsigned int align = ndr_align_size(next_offset, 8);
4918 if ((next_offset + align) > max_data_bytes) {
4919 DEBUG(10, ("refusing to overflow align "
4920 "reply at stream %u\n",
4922 TALLOC_FREE(namebuf);
4923 return STATUS_BUFFER_OVERFLOW;
4926 memset(data+next_offset, 0, align);
4927 next_offset += align;
4929 SIVAL(data, ofs, next_offset - ofs);
4936 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4940 return NT_STATUS_OK;
4943 #if defined(HAVE_POSIX_ACLS)
4944 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4945 struct smb_request *req,
4947 struct smb_filename *smb_fname,
4949 unsigned int data_size_in,
4950 unsigned int *pdata_size_out)
4952 SMB_ACL_T file_acl = NULL;
4953 SMB_ACL_T def_acl = NULL;
4954 uint16_t num_file_acls = 0;
4955 uint16_t num_def_acls = 0;
4956 unsigned int size_needed = 0;
4959 bool close_fsp = false;
4962 * Ensure we always operate on a file descriptor, not just
4966 uint32_t access_mask = SEC_STD_READ_CONTROL|
4967 FILE_READ_ATTRIBUTES|
4968 FILE_WRITE_ATTRIBUTES;
4970 status = get_posix_fsp(conn,
4976 if (!NT_STATUS_IS_OK(status)) {
4982 SMB_ASSERT(fsp != NULL);
4984 status = refuse_symlink(conn,
4987 if (!NT_STATUS_IS_OK(status)) {
4991 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4994 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4995 DBG_INFO("ACLs not implemented on "
4996 "filesystem containing %s\n",
4998 status = NT_STATUS_NOT_IMPLEMENTED;
5002 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5004 * We can only have default POSIX ACLs on
5007 if (!fsp->fsp_flags.is_directory) {
5008 DBG_INFO("Non-directory open %s\n",
5010 status = NT_STATUS_INVALID_HANDLE;
5013 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5015 SMB_ACL_TYPE_DEFAULT,
5017 def_acl = free_empty_sys_acl(conn, def_acl);
5020 num_file_acls = count_acl_entries(conn, file_acl);
5021 num_def_acls = count_acl_entries(conn, def_acl);
5024 if (num_file_acls + num_def_acls < num_file_acls) {
5025 status = NT_STATUS_INVALID_PARAMETER;
5029 size_needed = num_file_acls + num_def_acls;
5032 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5033 * than UINT_MAX, so check by division.
5035 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5036 status = NT_STATUS_INVALID_PARAMETER;
5040 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5041 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5042 status = NT_STATUS_INVALID_PARAMETER;
5045 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5047 if ( data_size_in < size_needed) {
5048 DBG_INFO("data_size too small (%u) need %u\n",
5051 status = NT_STATUS_BUFFER_TOO_SMALL;
5055 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5056 SSVAL(pdata,2,num_file_acls);
5057 SSVAL(pdata,4,num_def_acls);
5058 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5060 ok = marshall_posix_acl(conn,
5065 status = NT_STATUS_INTERNAL_ERROR;
5068 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5070 ok = marshall_posix_acl(conn,
5075 status = NT_STATUS_INTERNAL_ERROR;
5079 *pdata_size_out = size_needed;
5080 status = NT_STATUS_OK;
5086 * Ensure the stat struct in smb_fname is up to
5087 * date. Structure copy.
5089 smb_fname->st = fsp->fsp_name->st;
5090 (void)close_file(req, fsp, NORMAL_CLOSE);
5094 TALLOC_FREE(file_acl);
5095 TALLOC_FREE(def_acl);
5100 /****************************************************************************
5101 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5102 ****************************************************************************/
5104 static void call_trans2qpipeinfo(connection_struct *conn,
5105 struct smb_request *req,
5106 unsigned int tran_call,
5107 char **pparams, int total_params,
5108 char **ppdata, int total_data,
5109 unsigned int max_data_bytes)
5111 char *params = *pparams;
5112 char *pdata = *ppdata;
5113 unsigned int data_size = 0;
5114 unsigned int param_size = 2;
5115 uint16_t info_level;
5119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5123 if (total_params < 4) {
5124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5128 fsp = file_fsp(req, SVAL(params,0));
5129 if (!fsp_is_np(fsp)) {
5130 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5134 info_level = SVAL(params,2);
5136 *pparams = (char *)SMB_REALLOC(*pparams,2);
5137 if (*pparams == NULL) {
5138 reply_nterror(req, NT_STATUS_NO_MEMORY);
5143 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5147 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5148 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5149 if (*ppdata == NULL ) {
5150 reply_nterror(req, NT_STATUS_NO_MEMORY);
5155 switch (info_level) {
5156 case SMB_FILE_STANDARD_INFORMATION:
5158 SOFF_T(pdata,0,4096LL);
5165 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5169 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5175 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5176 TALLOC_CTX *mem_ctx,
5177 struct smb_request *req,
5178 uint16_t info_level,
5180 struct smb_filename *smb_fname,
5181 bool delete_pending,
5182 struct timespec write_time_ts,
5183 struct ea_list *ea_list,
5184 int lock_data_count,
5187 unsigned int max_data_bytes,
5188 size_t *fixed_portion,
5190 unsigned int *pdata_size)
5192 char *pdata = *ppdata;
5193 char *dstart, *dend;
5194 unsigned int data_size;
5195 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5196 time_t create_time, mtime, atime, c_time;
5197 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5204 uint64_t file_size = 0;
5206 uint64_t allocation_size = 0;
5207 uint64_t file_id = 0;
5208 uint32_t access_mask = 0;
5211 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5212 return NT_STATUS_INVALID_LEVEL;
5215 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5216 smb_fname_str_dbg(smb_fname),
5218 info_level, max_data_bytes));
5220 mode = dos_mode(conn, smb_fname);
5221 nlink = psbuf->st_ex_nlink;
5223 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5227 if ((nlink > 0) && delete_pending) {
5231 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5232 return NT_STATUS_INVALID_PARAMETER;
5235 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5236 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5237 if (*ppdata == NULL) {
5238 return NT_STATUS_NO_MEMORY;
5242 dend = dstart + data_size - 1;
5244 if (!is_omit_timespec(&write_time_ts) &&
5245 !INFO_LEVEL_IS_UNIX(info_level))
5247 update_stat_ex_mtime(psbuf, write_time_ts);
5250 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5251 mtime_ts = psbuf->st_ex_mtime;
5252 atime_ts = psbuf->st_ex_atime;
5253 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5255 if (lp_dos_filetime_resolution(SNUM(conn))) {
5256 dos_filetime_timespec(&create_time_ts);
5257 dos_filetime_timespec(&mtime_ts);
5258 dos_filetime_timespec(&atime_ts);
5259 dos_filetime_timespec(&ctime_ts);
5262 create_time = convert_timespec_to_time_t(create_time_ts);
5263 mtime = convert_timespec_to_time_t(mtime_ts);
5264 atime = convert_timespec_to_time_t(atime_ts);
5265 c_time = convert_timespec_to_time_t(ctime_ts);
5267 p = strrchr_m(smb_fname->base_name,'/');
5269 base_name = smb_fname->base_name;
5273 /* NT expects the name to be in an exact form of the *full*
5274 filename. See the trans2 torture test */
5275 if (ISDOT(base_name)) {
5276 dos_fname = talloc_strdup(mem_ctx, "\\");
5278 return NT_STATUS_NO_MEMORY;
5281 dos_fname = talloc_asprintf(mem_ctx,
5283 smb_fname->base_name);
5285 return NT_STATUS_NO_MEMORY;
5287 if (is_ntfs_stream_smb_fname(smb_fname)) {
5288 dos_fname = talloc_asprintf(dos_fname, "%s",
5289 smb_fname->stream_name);
5291 return NT_STATUS_NO_MEMORY;
5295 string_replace(dos_fname, '/', '\\');
5298 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5301 /* Do we have this path open ? */
5303 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5304 fsp1 = file_find_di_first(conn->sconn, fileid);
5305 if (fsp1 && fsp1->initial_allocation_size) {
5306 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5310 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5311 file_size = get_file_size_stat(psbuf);
5315 pos = fh_get_position_information(fsp->fh);
5319 access_mask = fsp->access_mask;
5321 /* GENERIC_EXECUTE mapping from Windows */
5322 access_mask = 0x12019F;
5325 /* This should be an index number - looks like
5328 I think this causes us to fail the IFSKIT
5329 BasicFileInformationTest. -tpot */
5330 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5334 switch (info_level) {
5335 case SMB_INFO_STANDARD:
5336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5338 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5339 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5340 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5341 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5342 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5343 SSVAL(pdata,l1_attrFile,mode);
5346 case SMB_INFO_QUERY_EA_SIZE:
5348 unsigned int ea_size =
5349 estimate_ea_size(conn, fsp,
5351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5353 srv_put_dos_date2(pdata,0,create_time);
5354 srv_put_dos_date2(pdata,4,atime);
5355 srv_put_dos_date2(pdata,8,mtime); /* write time */
5356 SIVAL(pdata,12,(uint32_t)file_size);
5357 SIVAL(pdata,16,(uint32_t)allocation_size);
5358 SSVAL(pdata,20,mode);
5359 SIVAL(pdata,22,ea_size);
5363 case SMB_INFO_IS_NAME_VALID:
5364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5366 /* os/2 needs this ? really ?*/
5367 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5369 /* This is only reached for qpathinfo */
5373 case SMB_INFO_QUERY_EAS_FROM_LIST:
5375 size_t total_ea_len = 0;
5376 struct ea_list *ea_file_list = NULL;
5377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5380 get_ea_list_from_file(mem_ctx, conn, fsp,
5382 &total_ea_len, &ea_file_list);
5383 if (!NT_STATUS_IS_OK(status)) {
5387 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5389 if (!ea_list || (total_ea_len > data_size)) {
5391 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5395 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5399 case SMB_INFO_QUERY_ALL_EAS:
5401 /* We have data_size bytes to put EA's into. */
5402 size_t total_ea_len = 0;
5403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5405 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5407 &total_ea_len, &ea_list);
5408 if (!NT_STATUS_IS_OK(status)) {
5412 if (!ea_list || (total_ea_len > data_size)) {
5414 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5418 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5422 case SMB2_FILE_FULL_EA_INFORMATION:
5424 /* We have data_size bytes to put EA's into. */
5425 size_t total_ea_len = 0;
5426 struct ea_list *ea_file_list = NULL;
5428 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5430 /*TODO: add filtering and index handling */
5433 get_ea_list_from_file(mem_ctx, conn, fsp,
5435 &total_ea_len, &ea_file_list);
5436 if (!NT_STATUS_IS_OK(status)) {
5439 if (!ea_file_list) {
5440 return NT_STATUS_NO_EAS_ON_FILE;
5443 status = fill_ea_chained_buffer(mem_ctx,
5447 conn, ea_file_list);
5448 if (!NT_STATUS_IS_OK(status)) {
5454 case SMB_FILE_BASIC_INFORMATION:
5455 case SMB_QUERY_FILE_BASIC_INFO:
5457 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5459 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5461 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5465 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5466 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5467 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5468 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5469 SIVAL(pdata,32,mode);
5471 DEBUG(5,("SMB_QFBI - "));
5472 DEBUG(5,("create: %s ", ctime(&create_time)));
5473 DEBUG(5,("access: %s ", ctime(&atime)));
5474 DEBUG(5,("write: %s ", ctime(&mtime)));
5475 DEBUG(5,("change: %s ", ctime(&c_time)));
5476 DEBUG(5,("mode: %x\n", mode));
5477 *fixed_portion = data_size;
5480 case SMB_FILE_STANDARD_INFORMATION:
5481 case SMB_QUERY_FILE_STANDARD_INFO:
5483 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5485 SOFF_T(pdata,0,allocation_size);
5486 SOFF_T(pdata,8,file_size);
5487 SIVAL(pdata,16,nlink);
5488 SCVAL(pdata,20,delete_pending?1:0);
5489 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5490 SSVAL(pdata,22,0); /* Padding. */
5491 *fixed_portion = 24;
5494 case SMB_FILE_EA_INFORMATION:
5495 case SMB_QUERY_FILE_EA_INFO:
5497 unsigned int ea_size =
5498 estimate_ea_size(conn, fsp, smb_fname);
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5502 SIVAL(pdata,0,ea_size);
5506 /* Get the 8.3 name - used if NT SMB was negotiated. */
5507 case SMB_QUERY_FILE_ALT_NAME_INFO:
5508 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5510 char mangled_name[13];
5511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5512 if (!name_to_8_3(base_name,mangled_name,
5513 True,conn->params)) {
5514 return NT_STATUS_NO_MEMORY;
5516 status = srvstr_push(dstart, flags2,
5517 pdata+4, mangled_name,
5518 PTR_DIFF(dend, pdata+4),
5520 if (!NT_STATUS_IS_OK(status)) {
5523 data_size = 4 + len;
5529 case SMB_QUERY_FILE_NAME_INFO:
5532 this must be *exactly* right for ACLs on mapped drives to work
5534 status = srvstr_push(dstart, flags2,
5536 PTR_DIFF(dend, pdata+4),
5538 if (!NT_STATUS_IS_OK(status)) {
5541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5542 data_size = 4 + len;
5547 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5549 char *nfname = NULL;
5551 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5552 return NT_STATUS_INVALID_LEVEL;
5555 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5556 if (nfname == NULL) {
5557 return NT_STATUS_NO_MEMORY;
5560 if (ISDOT(nfname)) {
5563 string_replace(nfname, '/', '\\');
5565 if (smb_fname->stream_name != NULL) {
5566 const char *s = smb_fname->stream_name;
5567 const char *e = NULL;
5570 SMB_ASSERT(s[0] != '\0');
5573 * smb_fname->stream_name is in form
5574 * of ':StrEam:$DATA', but we should only
5575 * append ':StrEam' here.
5578 e = strchr(&s[1], ':');
5584 nfname = talloc_strndup_append(nfname, s, n);
5585 if (nfname == NULL) {
5586 return NT_STATUS_NO_MEMORY;
5590 status = srvstr_push(dstart, flags2,
5592 PTR_DIFF(dend, pdata+4),
5594 if (!NT_STATUS_IS_OK(status)) {
5597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5598 data_size = 4 + len;
5604 case SMB_FILE_ALLOCATION_INFORMATION:
5605 case SMB_QUERY_FILE_ALLOCATION_INFO:
5606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5608 SOFF_T(pdata,0,allocation_size);
5611 case SMB_FILE_END_OF_FILE_INFORMATION:
5612 case SMB_QUERY_FILE_END_OF_FILEINFO:
5613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5615 SOFF_T(pdata,0,file_size);
5618 case SMB_QUERY_FILE_ALL_INFO:
5619 case SMB_FILE_ALL_INFORMATION:
5621 unsigned int ea_size =
5622 estimate_ea_size(conn, fsp, smb_fname);
5623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5624 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5625 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5626 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5627 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5628 SIVAL(pdata,32,mode);
5629 SIVAL(pdata,36,0); /* padding. */
5631 SOFF_T(pdata,0,allocation_size);
5632 SOFF_T(pdata,8,file_size);
5633 SIVAL(pdata,16,nlink);
5634 SCVAL(pdata,20,delete_pending);
5635 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5638 SIVAL(pdata,0,ea_size);
5639 pdata += 4; /* EA info */
5640 status = srvstr_push(dstart, flags2,
5642 PTR_DIFF(dend, pdata+4),
5644 if (!NT_STATUS_IS_OK(status)) {
5649 data_size = PTR_DIFF(pdata,(*ppdata));
5650 *fixed_portion = 10;
5654 case SMB2_FILE_ALL_INFORMATION:
5656 unsigned int ea_size =
5657 estimate_ea_size(conn, fsp, smb_fname);
5658 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5659 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5660 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5661 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5662 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5663 SIVAL(pdata, 0x20, mode);
5664 SIVAL(pdata, 0x24, 0); /* padding. */
5665 SBVAL(pdata, 0x28, allocation_size);
5666 SBVAL(pdata, 0x30, file_size);
5667 SIVAL(pdata, 0x38, nlink);
5668 SCVAL(pdata, 0x3C, delete_pending);
5669 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5670 SSVAL(pdata, 0x3E, 0); /* padding */
5671 SBVAL(pdata, 0x40, file_id);
5672 SIVAL(pdata, 0x48, ea_size);
5673 SIVAL(pdata, 0x4C, access_mask);
5674 SBVAL(pdata, 0x50, pos);
5675 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5676 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5680 status = srvstr_push(dstart, flags2,
5682 PTR_DIFF(dend, pdata+4),
5684 if (!NT_STATUS_IS_OK(status)) {
5689 data_size = PTR_DIFF(pdata,(*ppdata));
5690 *fixed_portion = 104;
5693 case SMB_FILE_INTERNAL_INFORMATION:
5695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5696 SBVAL(pdata, 0, file_id);
5701 case SMB_FILE_ACCESS_INFORMATION:
5702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5703 SIVAL(pdata, 0, access_mask);
5708 case SMB_FILE_NAME_INFORMATION:
5709 /* Pathname with leading '\'. */
5712 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5714 SIVAL(pdata,0,byte_len);
5715 data_size = 4 + byte_len;
5719 case SMB_FILE_DISPOSITION_INFORMATION:
5720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5722 SCVAL(pdata,0,delete_pending);
5726 case SMB_FILE_POSITION_INFORMATION:
5727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5729 SOFF_T(pdata,0,pos);
5733 case SMB_FILE_MODE_INFORMATION:
5734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5735 SIVAL(pdata,0,mode);
5740 case SMB_FILE_ALIGNMENT_INFORMATION:
5741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5742 SIVAL(pdata,0,0); /* No alignment needed. */
5748 * NT4 server just returns "invalid query" to this - if we try
5749 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5752 /* The first statement above is false - verified using Thursby
5753 * client against NT4 -- gcolley.
5755 case SMB_QUERY_FILE_STREAM_INFO:
5756 case SMB_FILE_STREAM_INFORMATION: {
5757 unsigned int num_streams = 0;
5758 struct stream_struct *streams = NULL;
5760 DEBUG(10,("smbd_do_qfilepathinfo: "
5761 "SMB_FILE_STREAM_INFORMATION\n"));
5763 if (is_ntfs_stream_smb_fname(smb_fname)) {
5764 return NT_STATUS_INVALID_PARAMETER;
5767 status = vfs_streaminfo(conn,
5774 if (!NT_STATUS_IS_OK(status)) {
5775 DEBUG(10, ("could not get stream info: %s\n",
5776 nt_errstr(status)));
5780 status = marshall_stream_info(num_streams, streams,
5781 pdata, max_data_bytes,
5784 if (!NT_STATUS_IS_OK(status)) {
5785 DEBUG(10, ("marshall_stream_info failed: %s\n",
5786 nt_errstr(status)));
5787 TALLOC_FREE(streams);
5791 TALLOC_FREE(streams);
5793 *fixed_portion = 32;
5797 case SMB_QUERY_COMPRESSION_INFO:
5798 case SMB_FILE_COMPRESSION_INFORMATION:
5799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5800 SOFF_T(pdata,0,file_size);
5801 SIVAL(pdata,8,0); /* ??? */
5802 SIVAL(pdata,12,0); /* ??? */
5804 *fixed_portion = 16;
5807 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5809 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5810 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5811 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5812 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5813 SOFF_T(pdata,32,allocation_size);
5814 SOFF_T(pdata,40,file_size);
5815 SIVAL(pdata,48,mode);
5816 SIVAL(pdata,52,0); /* ??? */
5818 *fixed_portion = 56;
5821 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5823 SIVAL(pdata,0,mode);
5830 * CIFS UNIX Extensions.
5833 case SMB_QUERY_FILE_UNIX_BASIC:
5835 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5836 data_size = PTR_DIFF(pdata,(*ppdata));
5838 DEBUG(4,("smbd_do_qfilepathinfo: "
5839 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5840 dump_data(4, (uint8_t *)(*ppdata), data_size);
5844 case SMB_QUERY_FILE_UNIX_INFO2:
5846 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5847 data_size = PTR_DIFF(pdata,(*ppdata));
5851 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5853 for (i=0; i<100; i++)
5854 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5860 case SMB_QUERY_FILE_UNIX_LINK:
5863 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5866 return NT_STATUS_NO_MEMORY;
5869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5871 if(!S_ISLNK(psbuf->st_ex_mode)) {
5872 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5875 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5877 link_len = SMB_VFS_READLINKAT(conn,
5883 if (link_len == -1) {
5884 return map_nt_error_from_unix(errno);
5886 buffer[link_len] = 0;
5887 status = srvstr_push(dstart, flags2,
5889 PTR_DIFF(dend, pdata),
5890 STR_TERMINATE, &len);
5891 if (!NT_STATUS_IS_OK(status)) {
5895 data_size = PTR_DIFF(pdata,(*ppdata));
5900 #if defined(HAVE_POSIX_ACLS)
5901 case SMB_QUERY_POSIX_ACL:
5903 status = smb_query_posix_acl(conn,
5910 if (!NT_STATUS_IS_OK(status)) {
5918 case SMB_QUERY_POSIX_LOCK:
5923 enum brl_type lock_type;
5925 /* We need an open file with a real fd for this. */
5927 fsp->fsp_flags.is_pathref ||
5928 fsp_get_io_fd(fsp) == -1)
5930 return NT_STATUS_INVALID_LEVEL;
5933 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5934 return NT_STATUS_INVALID_PARAMETER;
5937 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5938 case POSIX_LOCK_TYPE_READ:
5939 lock_type = READ_LOCK;
5941 case POSIX_LOCK_TYPE_WRITE:
5942 lock_type = WRITE_LOCK;
5944 case POSIX_LOCK_TYPE_UNLOCK:
5946 /* There's no point in asking for an unlock... */
5947 return NT_STATUS_INVALID_PARAMETER;
5950 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5951 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5952 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5954 status = query_lock(fsp,
5961 if (ERROR_WAS_LOCK_DENIED(status)) {
5962 /* Here we need to report who has it locked... */
5963 data_size = POSIX_LOCK_DATA_SIZE;
5965 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5966 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5967 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5968 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5969 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5971 } else if (NT_STATUS_IS_OK(status)) {
5972 /* For success we just return a copy of what we sent
5973 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5974 data_size = POSIX_LOCK_DATA_SIZE;
5975 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5976 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5984 return NT_STATUS_INVALID_LEVEL;
5987 *pdata_size = data_size;
5988 return NT_STATUS_OK;
5991 /****************************************************************************
5992 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5993 file name or file id).
5994 ****************************************************************************/
5996 static void call_trans2qfilepathinfo(connection_struct *conn,
5997 struct smb_request *req,
5998 unsigned int tran_call,
5999 char **pparams, int total_params,
6000 char **ppdata, int total_data,
6001 unsigned int max_data_bytes)
6003 char *params = *pparams;
6004 char *pdata = *ppdata;
6005 uint16_t info_level;
6006 unsigned int data_size = 0;
6007 unsigned int param_size = 2;
6008 struct smb_filename *smb_fname = NULL;
6009 bool delete_pending = False;
6010 struct timespec write_time_ts;
6011 files_struct *fsp = NULL;
6012 struct file_id fileid;
6013 struct ea_list *ea_list = NULL;
6014 int lock_data_count = 0;
6015 char *lock_data = NULL;
6016 size_t fixed_portion;
6017 NTSTATUS status = NT_STATUS_OK;
6020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6024 ZERO_STRUCT(write_time_ts);
6026 if (tran_call == TRANSACT2_QFILEINFO) {
6027 if (total_params < 4) {
6028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6033 call_trans2qpipeinfo(conn, req, tran_call,
6034 pparams, total_params,
6040 fsp = file_fsp(req, SVAL(params,0));
6041 info_level = SVAL(params,2);
6043 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6045 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6046 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6050 /* Initial check for valid fsp ptr. */
6051 if (!check_fsp_open(conn, req, fsp)) {
6055 smb_fname = fsp->fsp_name;
6057 if(fsp->fake_file_handle) {
6059 * This is actually for the QUOTA_FAKE_FILE --metze
6062 /* We know this name is ok, it's already passed the checks. */
6064 } else if(fsp_get_pathref_fd(fsp) == -1) {
6066 * This is actually a QFILEINFO on a directory
6067 * handle (returned from an NT SMB). NT5.0 seems
6068 * to do this call. JRA.
6071 if (INFO_LEVEL_IS_UNIX(info_level)) {
6072 /* Always do lstat for UNIX calls. */
6073 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6074 DEBUG(3,("call_trans2qfilepathinfo: "
6075 "SMB_VFS_LSTAT of %s failed "
6077 smb_fname_str_dbg(smb_fname),
6080 map_nt_error_from_unix(errno));
6083 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6084 DEBUG(3,("call_trans2qfilepathinfo: "
6085 "SMB_VFS_STAT of %s failed (%s)\n",
6086 smb_fname_str_dbg(smb_fname),
6089 map_nt_error_from_unix(errno));
6093 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6094 fileid = vfs_file_id_from_sbuf(
6095 conn, &smb_fname->st);
6096 get_file_infos(fileid, fsp->name_hash,
6102 * Original code - this is an open file.
6104 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6105 DEBUG(3, ("fstat of %s failed (%s)\n",
6106 fsp_fnum_dbg(fsp), strerror(errno)));
6108 map_nt_error_from_unix(errno));
6111 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6112 fileid = vfs_file_id_from_sbuf(
6113 conn, &smb_fname->st);
6114 get_file_infos(fileid, fsp->name_hash,
6123 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6126 if (total_params < 7) {
6127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6131 info_level = SVAL(params,0);
6133 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6135 if (INFO_LEVEL_IS_UNIX(info_level)) {
6136 if (!lp_unix_extensions()) {
6137 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6142 if (req->posix_pathnames) {
6143 srvstr_get_path_posix(req,
6152 srvstr_get_path(req,
6161 if (!NT_STATUS_IS_OK(status)) {
6162 reply_nterror(req, status);
6166 status = filename_convert(req,
6172 if (!NT_STATUS_IS_OK(status)) {
6173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6174 reply_botherror(req,
6175 NT_STATUS_PATH_NOT_COVERED,
6176 ERRSRV, ERRbadpath);
6179 reply_nterror(req, status);
6183 /* If this is a stream, check if there is a delete_pending. */
6184 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6185 && is_ntfs_stream_smb_fname(smb_fname)) {
6186 struct smb_filename *smb_fname_base;
6188 /* Create an smb_filename with stream_name == NULL. */
6189 smb_fname_base = synthetic_smb_fname(
6191 smb_fname->base_name,
6196 if (smb_fname_base == NULL) {
6197 reply_nterror(req, NT_STATUS_NO_MEMORY);
6201 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6202 /* Always do lstat for UNIX calls. */
6203 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6204 DEBUG(3,("call_trans2qfilepathinfo: "
6205 "SMB_VFS_LSTAT of %s failed "
6207 smb_fname_str_dbg(smb_fname_base),
6209 TALLOC_FREE(smb_fname_base);
6211 map_nt_error_from_unix(errno));
6215 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6216 DEBUG(3,("call_trans2qfilepathinfo: "
6217 "fileinfo of %s failed "
6219 smb_fname_str_dbg(smb_fname_base),
6221 TALLOC_FREE(smb_fname_base);
6223 map_nt_error_from_unix(errno));
6228 status = file_name_hash(conn,
6229 smb_fname_str_dbg(smb_fname_base),
6231 if (!NT_STATUS_IS_OK(status)) {
6232 TALLOC_FREE(smb_fname_base);
6233 reply_nterror(req, status);
6237 fileid = vfs_file_id_from_sbuf(conn,
6238 &smb_fname_base->st);
6239 TALLOC_FREE(smb_fname_base);
6240 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6241 if (delete_pending) {
6242 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6247 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6248 /* Always do lstat for UNIX calls. */
6249 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6250 DEBUG(3,("call_trans2qfilepathinfo: "
6251 "SMB_VFS_LSTAT of %s failed (%s)\n",
6252 smb_fname_str_dbg(smb_fname),
6255 map_nt_error_from_unix(errno));
6260 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6261 DEBUG(3,("call_trans2qfilepathinfo: "
6262 "SMB_VFS_STAT of %s failed (%s)\n",
6263 smb_fname_str_dbg(smb_fname),
6266 map_nt_error_from_unix(errno));
6271 status = file_name_hash(conn,
6272 smb_fname_str_dbg(smb_fname),
6274 if (!NT_STATUS_IS_OK(status)) {
6275 reply_nterror(req, status);
6279 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6280 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6281 get_file_infos(fileid, name_hash, &delete_pending,
6285 if (delete_pending) {
6286 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6291 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6292 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6294 info_level,tran_call,total_data));
6296 /* Pull out any data sent here before we realloc. */
6297 switch (info_level) {
6298 case SMB_INFO_QUERY_EAS_FROM_LIST:
6300 /* Pull any EA list from the data portion. */
6303 if (total_data < 4) {
6305 req, NT_STATUS_INVALID_PARAMETER);
6308 ea_size = IVAL(pdata,0);
6310 if (total_data > 0 && ea_size != total_data) {
6311 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6312 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6314 req, NT_STATUS_INVALID_PARAMETER);
6318 if (!lp_ea_support(SNUM(conn))) {
6319 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6323 /* Pull out the list of names. */
6324 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6327 req, NT_STATUS_INVALID_PARAMETER);
6333 case SMB_QUERY_POSIX_LOCK:
6336 fsp->fsp_flags.is_pathref ||
6337 fsp_get_io_fd(fsp) == -1)
6339 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6343 if (total_data != POSIX_LOCK_DATA_SIZE) {
6345 req, NT_STATUS_INVALID_PARAMETER);
6349 /* Copy the lock range data. */
6350 lock_data = (char *)talloc_memdup(
6351 req, pdata, total_data);
6353 reply_nterror(req, NT_STATUS_NO_MEMORY);
6356 lock_data_count = total_data;
6362 *pparams = (char *)SMB_REALLOC(*pparams,2);
6363 if (*pparams == NULL) {
6364 reply_nterror(req, NT_STATUS_NO_MEMORY);
6371 * draft-leach-cifs-v1-spec-02.txt
6372 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6375 * The requested information is placed in the Data portion of the
6376 * transaction response. For the information levels greater than 0x100,
6377 * the transaction response has 1 parameter word which should be
6378 * ignored by the client.
6380 * However Windows only follows this rule for the IS_NAME_VALID call.
6382 switch (info_level) {
6383 case SMB_INFO_IS_NAME_VALID:
6388 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
6390 * We use levels that start with 0xFF00
6391 * internally to represent SMB2 specific levels
6393 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6397 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6399 delete_pending, write_time_ts,
6401 lock_data_count, lock_data,
6402 req->flags2, max_data_bytes,
6404 ppdata, &data_size);
6405 if (!NT_STATUS_IS_OK(status)) {
6406 if (open_was_deferred(req->xconn, req->mid)) {
6407 /* We have re-scheduled this call. */
6410 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6411 bool ok = defer_smb1_sharing_violation(req);
6416 reply_nterror(req, status);
6419 if (fixed_portion > max_data_bytes) {
6420 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6424 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6430 /****************************************************************************
6431 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6433 ****************************************************************************/
6435 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6436 connection_struct *conn,
6437 struct smb_request *req,
6438 bool overwrite_if_exists,
6439 const struct smb_filename *smb_fname_old,
6440 struct smb_filename *smb_fname_new)
6442 NTSTATUS status = NT_STATUS_OK;
6446 /* source must already exist. */
6447 if (!VALID_STAT(smb_fname_old->st)) {
6448 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6451 if (VALID_STAT(smb_fname_new->st)) {
6452 if (overwrite_if_exists) {
6453 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6454 return NT_STATUS_FILE_IS_A_DIRECTORY;
6456 status = unlink_internals(conn,
6458 FILE_ATTRIBUTE_NORMAL,
6461 if (!NT_STATUS_IS_OK(status)) {
6465 /* Disallow if newname already exists. */
6466 return NT_STATUS_OBJECT_NAME_COLLISION;
6470 /* No links from a directory. */
6471 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6472 return NT_STATUS_FILE_IS_A_DIRECTORY;
6475 /* Setting a hardlink to/from a stream isn't currently supported. */
6476 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6478 DBG_DEBUG("Old name has streams\n");
6479 return NT_STATUS_INVALID_PARAMETER;
6481 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6483 DBG_DEBUG("New name has streams\n");
6484 return NT_STATUS_INVALID_PARAMETER;
6487 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6488 smb_fname_old->base_name, smb_fname_new->base_name));
6490 ret = SMB_VFS_LINKAT(conn,
6498 status = map_nt_error_from_unix(errno);
6499 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6500 nt_errstr(status), smb_fname_old->base_name,
6501 smb_fname_new->base_name));
6506 /****************************************************************************
6507 Deal with setting the time from any of the setfilepathinfo functions.
6508 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6509 calling this function.
6510 ****************************************************************************/
6512 NTSTATUS smb_set_file_time(connection_struct *conn,
6514 const struct smb_filename *smb_fname,
6515 struct smb_file_time *ft,
6516 bool setting_write_time)
6518 struct smb_filename smb_fname_base;
6519 struct timeval_buf tbuf[4];
6521 FILE_NOTIFY_CHANGE_LAST_ACCESS
6522 |FILE_NOTIFY_CHANGE_LAST_WRITE
6523 |FILE_NOTIFY_CHANGE_CREATION;
6525 if (!VALID_STAT(smb_fname->st)) {
6526 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6529 /* get some defaults (no modifications) if any info is zero or -1. */
6530 if (is_omit_timespec(&ft->create_time)) {
6531 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6534 if (is_omit_timespec(&ft->atime)) {
6535 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6538 if (is_omit_timespec(&ft->mtime)) {
6539 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6542 if (!setting_write_time) {
6543 /* ft->mtime comes from change time, not write time. */
6544 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6547 /* Ensure the resolution is the correct for
6548 * what we can store on this filesystem. */
6550 round_timespec(conn->ts_res, &ft->create_time);
6551 round_timespec(conn->ts_res, &ft->ctime);
6552 round_timespec(conn->ts_res, &ft->atime);
6553 round_timespec(conn->ts_res, &ft->mtime);
6555 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6556 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6557 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6558 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6559 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6560 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6561 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6562 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6564 if (setting_write_time) {
6566 * This was a Windows setfileinfo on an open file.
6567 * NT does this a lot. We also need to
6568 * set the time here, as it can be read by
6569 * FindFirst/FindNext and with the patch for bug #2045
6570 * in smbd/fileio.c it ensures that this timestamp is
6571 * kept sticky even after a write. We save the request
6572 * away and will set it on file close and after a write. JRA.
6575 DBG_DEBUG("setting pending modtime to %s\n",
6576 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6579 if (fsp->base_fsp) {
6580 set_sticky_write_time_fsp(fsp->base_fsp,
6583 set_sticky_write_time_fsp(fsp, ft->mtime);
6586 set_sticky_write_time_path(
6587 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6592 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6594 /* Always call ntimes on the base, even if a stream was passed in. */
6595 smb_fname_base = *smb_fname;
6596 smb_fname_base.stream_name = NULL;
6598 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6599 return map_nt_error_from_unix(errno);
6602 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6603 smb_fname->base_name);
6604 return NT_STATUS_OK;
6607 /****************************************************************************
6608 Deal with setting the dosmode from any of the setfilepathinfo functions.
6609 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6610 done before calling this function.
6611 ****************************************************************************/
6613 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6614 const struct smb_filename *smb_fname,
6617 struct smb_filename *smb_fname_base;
6620 if (!VALID_STAT(smb_fname->st)) {
6621 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6624 /* Always operate on the base_name, even if a stream was passed in. */
6625 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6626 smb_fname->base_name,
6631 if (smb_fname_base == NULL) {
6632 return NT_STATUS_NO_MEMORY;
6636 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6637 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6639 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6643 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6645 /* check the mode isn't different, before changing it */
6646 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6647 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6648 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6649 (unsigned int)dosmode));
6651 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6653 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6655 smb_fname_str_dbg(smb_fname_base),
6657 status = map_nt_error_from_unix(errno);
6661 status = NT_STATUS_OK;
6663 TALLOC_FREE(smb_fname_base);
6667 /****************************************************************************
6668 Deal with setting the size from any of the setfilepathinfo functions.
6669 ****************************************************************************/
6671 static NTSTATUS smb_set_file_size(connection_struct *conn,
6672 struct smb_request *req,
6674 const struct smb_filename *smb_fname,
6675 const SMB_STRUCT_STAT *psbuf,
6677 bool fail_after_createfile)
6679 NTSTATUS status = NT_STATUS_OK;
6680 struct smb_filename *smb_fname_tmp = NULL;
6681 files_struct *new_fsp = NULL;
6683 if (!VALID_STAT(*psbuf)) {
6684 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6687 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6689 get_file_size_stat(psbuf));
6691 if (size == get_file_size_stat(psbuf)) {
6693 return NT_STATUS_OK;
6695 if (!fsp->fsp_flags.modified) {
6696 return NT_STATUS_OK;
6698 trigger_write_time_update_immediate(fsp);
6699 return NT_STATUS_OK;
6702 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6703 smb_fname_str_dbg(smb_fname), (double)size));
6706 !fsp->fsp_flags.is_pathref &&
6707 fsp_get_io_fd(fsp) != -1)
6709 /* Handle based call. */
6710 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6711 return NT_STATUS_ACCESS_DENIED;
6714 if (vfs_set_filelen(fsp, size) == -1) {
6715 return map_nt_error_from_unix(errno);
6717 trigger_write_time_update_immediate(fsp);
6718 return NT_STATUS_OK;
6721 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6722 if (smb_fname_tmp == NULL) {
6723 return NT_STATUS_NO_MEMORY;
6726 smb_fname_tmp->st = *psbuf;
6728 status = SMB_VFS_CREATE_FILE(
6731 smb_fname_tmp, /* fname */
6732 FILE_WRITE_DATA, /* access_mask */
6733 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6735 FILE_OPEN, /* create_disposition*/
6736 0, /* create_options */
6737 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6738 0, /* oplock_request */
6740 0, /* allocation_size */
6741 0, /* private_flags */
6744 &new_fsp, /* result */
6746 NULL, NULL); /* create context */
6748 TALLOC_FREE(smb_fname_tmp);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 /* NB. We check for open_was_deferred in the caller. */
6755 /* See RAW-SFILEINFO-END-OF-FILE */
6756 if (fail_after_createfile) {
6757 close_file(req, new_fsp,NORMAL_CLOSE);
6758 return NT_STATUS_INVALID_LEVEL;
6761 if (vfs_set_filelen(new_fsp, size) == -1) {
6762 status = map_nt_error_from_unix(errno);
6763 close_file(req, new_fsp,NORMAL_CLOSE);
6767 trigger_write_time_update_immediate(new_fsp);
6768 close_file(req, new_fsp,NORMAL_CLOSE);
6769 return NT_STATUS_OK;
6772 /****************************************************************************
6773 Deal with SMB_INFO_SET_EA.
6774 ****************************************************************************/
6776 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6780 const struct smb_filename *smb_fname)
6782 struct ea_list *ea_list = NULL;
6783 TALLOC_CTX *ctx = NULL;
6784 NTSTATUS status = NT_STATUS_OK;
6786 if (total_data < 10) {
6788 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6789 length. They seem to have no effect. Bug #3212. JRA */
6791 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6792 /* We're done. We only get EA info in this call. */
6793 return NT_STATUS_OK;
6796 return NT_STATUS_INVALID_PARAMETER;
6799 if (IVAL(pdata,0) > total_data) {
6800 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6801 IVAL(pdata,0), (unsigned int)total_data));
6802 return NT_STATUS_INVALID_PARAMETER;
6806 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6808 return NT_STATUS_INVALID_PARAMETER;
6811 status = set_ea(conn, fsp, smb_fname, ea_list);
6816 /****************************************************************************
6817 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6818 ****************************************************************************/
6820 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6825 struct ea_list *ea_list = NULL;
6829 return NT_STATUS_INVALID_HANDLE;
6832 if (!lp_ea_support(SNUM(conn))) {
6833 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6834 "EA's not supported.\n",
6835 (unsigned int)total_data));
6836 return NT_STATUS_EAS_NOT_SUPPORTED;
6839 if (total_data < 10) {
6840 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6842 (unsigned int)total_data));
6843 return NT_STATUS_INVALID_PARAMETER;
6846 ea_list = read_nttrans_ea_list(talloc_tos(),
6851 return NT_STATUS_INVALID_PARAMETER;
6854 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6856 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6857 smb_fname_str_dbg(fsp->fsp_name),
6858 nt_errstr(status) ));
6864 /****************************************************************************
6865 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6866 ****************************************************************************/
6868 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6872 struct smb_filename *smb_fname)
6874 NTSTATUS status = NT_STATUS_OK;
6875 bool delete_on_close;
6876 uint32_t dosmode = 0;
6878 if (total_data < 1) {
6879 return NT_STATUS_INVALID_PARAMETER;
6883 return NT_STATUS_INVALID_HANDLE;
6886 delete_on_close = (CVAL(pdata,0) ? True : False);
6887 dosmode = dos_mode(conn, smb_fname);
6889 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6890 "delete_on_close = %u\n",
6891 smb_fname_str_dbg(smb_fname),
6892 (unsigned int)dosmode,
6893 (unsigned int)delete_on_close ));
6895 if (delete_on_close) {
6896 status = can_set_delete_on_close(fsp, dosmode);
6897 if (!NT_STATUS_IS_OK(status)) {
6902 /* The set is across all open files on this dev/inode pair. */
6903 if (!set_delete_on_close(fsp, delete_on_close,
6904 conn->session_info->security_token,
6905 conn->session_info->unix_token)) {
6906 return NT_STATUS_ACCESS_DENIED;
6908 return NT_STATUS_OK;
6911 /****************************************************************************
6912 Deal with SMB_FILE_POSITION_INFORMATION.
6913 ****************************************************************************/
6915 static NTSTATUS smb_file_position_information(connection_struct *conn,
6920 uint64_t position_information;
6922 if (total_data < 8) {
6923 return NT_STATUS_INVALID_PARAMETER;
6927 /* Ignore on pathname based set. */
6928 return NT_STATUS_OK;
6931 position_information = (uint64_t)IVAL(pdata,0);
6932 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6934 DEBUG(10,("smb_file_position_information: Set file position "
6935 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6936 (double)position_information));
6937 fh_set_position_information(fsp->fh, position_information);
6938 return NT_STATUS_OK;
6941 /****************************************************************************
6942 Deal with SMB_FILE_MODE_INFORMATION.
6943 ****************************************************************************/
6945 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6951 if (total_data < 4) {
6952 return NT_STATUS_INVALID_PARAMETER;
6954 mode = IVAL(pdata,0);
6955 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6956 return NT_STATUS_INVALID_PARAMETER;
6958 return NT_STATUS_OK;
6961 /****************************************************************************
6962 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6963 ****************************************************************************/
6965 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6966 struct smb_request *req,
6969 const struct smb_filename *new_smb_fname)
6971 char *link_target = NULL;
6972 struct smb_filename target_fname;
6973 TALLOC_CTX *ctx = talloc_tos();
6977 /* Set a symbolic link. */
6978 /* Don't allow this if follow links is false. */
6980 if (total_data == 0) {
6981 return NT_STATUS_INVALID_PARAMETER;
6984 if (!lp_follow_symlinks(SNUM(conn))) {
6985 return NT_STATUS_ACCESS_DENIED;
6988 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6989 total_data, STR_TERMINATE);
6992 return NT_STATUS_INVALID_PARAMETER;
6995 target_fname = (struct smb_filename) {
6996 .base_name = link_target,
6999 /* Removes @GMT tokens if any */
7000 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7001 if (!NT_STATUS_IS_OK(status)) {
7005 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7006 new_smb_fname->base_name, link_target ));
7008 ret = SMB_VFS_SYMLINKAT(conn,
7013 return map_nt_error_from_unix(errno);
7016 return NT_STATUS_OK;
7019 /****************************************************************************
7020 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7021 ****************************************************************************/
7023 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7024 struct smb_request *req,
7025 const char *pdata, int total_data,
7026 struct smb_filename *smb_fname_new)
7028 char *oldname = NULL;
7029 struct smb_filename *smb_fname_old = NULL;
7030 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7031 TALLOC_CTX *ctx = talloc_tos();
7032 NTSTATUS status = NT_STATUS_OK;
7034 /* Set a hard link. */
7035 if (total_data == 0) {
7036 return NT_STATUS_INVALID_PARAMETER;
7039 if (req->posix_pathnames) {
7040 srvstr_get_path_posix(ctx,
7049 srvstr_get_path(ctx,
7058 if (!NT_STATUS_IS_OK(status)) {
7062 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7063 smb_fname_str_dbg(smb_fname_new), oldname));
7065 status = filename_convert(ctx,
7071 if (!NT_STATUS_IS_OK(status)) {
7075 return hardlink_internals(ctx, conn, req, false,
7076 smb_fname_old, smb_fname_new);
7079 /****************************************************************************
7080 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7081 ****************************************************************************/
7083 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7084 struct smb_request *req,
7088 struct smb_filename *smb_fname_src)
7092 char *newname = NULL;
7093 struct smb_filename *smb_fname_dst = NULL;
7094 const char *dst_original_lcomp = NULL;
7095 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7096 NTSTATUS status = NT_STATUS_OK;
7097 TALLOC_CTX *ctx = talloc_tos();
7100 return NT_STATUS_INVALID_HANDLE;
7103 if (total_data < 20) {
7104 return NT_STATUS_INVALID_PARAMETER;
7107 overwrite = (CVAL(pdata,0) ? True : False);
7108 len = IVAL(pdata,16);
7110 if (len > (total_data - 20) || (len == 0)) {
7111 return NT_STATUS_INVALID_PARAMETER;
7114 if (req->posix_pathnames) {
7115 srvstr_get_path_posix(ctx,
7124 srvstr_get_path(ctx,
7133 if (!NT_STATUS_IS_OK(status)) {
7137 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7140 status = filename_convert(ctx,
7146 if (!NT_STATUS_IS_OK(status)) {
7150 if (fsp->base_fsp) {
7151 /* newname must be a stream name. */
7152 if (newname[0] != ':') {
7153 return NT_STATUS_NOT_SUPPORTED;
7156 /* Create an smb_fname to call rename_internals_fsp() with. */
7157 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7158 fsp->base_fsp->fsp_name->base_name,
7161 fsp->base_fsp->fsp_name->twrp,
7162 fsp->base_fsp->fsp_name->flags);
7163 if (smb_fname_dst == NULL) {
7164 status = NT_STATUS_NO_MEMORY;
7170 * Set the original last component, since
7171 * rename_internals_fsp() requires it.
7173 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7177 if (dst_original_lcomp == NULL) {
7178 status = NT_STATUS_NO_MEMORY;
7182 DEBUG(10,("smb2_file_rename_information: "
7183 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7184 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7185 smb_fname_str_dbg(smb_fname_dst)));
7186 status = rename_internals_fsp(conn,
7190 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7194 TALLOC_FREE(smb_fname_dst);
7198 static NTSTATUS smb_file_link_information(connection_struct *conn,
7199 struct smb_request *req,
7203 struct smb_filename *smb_fname_src)
7207 char *newname = NULL;
7208 struct smb_filename *smb_fname_dst = NULL;
7209 NTSTATUS status = NT_STATUS_OK;
7210 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7211 TALLOC_CTX *ctx = talloc_tos();
7214 return NT_STATUS_INVALID_HANDLE;
7217 if (total_data < 20) {
7218 return NT_STATUS_INVALID_PARAMETER;
7221 overwrite = (CVAL(pdata,0) ? true : false);
7222 len = IVAL(pdata,16);
7224 if (len > (total_data - 20) || (len == 0)) {
7225 return NT_STATUS_INVALID_PARAMETER;
7228 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7229 srvstr_get_path_posix(ctx,
7237 ucf_flags |= UCF_POSIX_PATHNAMES;
7239 srvstr_get_path(ctx,
7248 if (!NT_STATUS_IS_OK(status)) {
7252 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7255 status = filename_convert(ctx,
7261 if (!NT_STATUS_IS_OK(status)) {
7265 if (fsp->base_fsp) {
7266 /* No stream names. */
7267 return NT_STATUS_NOT_SUPPORTED;
7270 DEBUG(10,("smb_file_link_information: "
7271 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7272 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7273 smb_fname_str_dbg(smb_fname_dst)));
7274 status = hardlink_internals(ctx,
7281 TALLOC_FREE(smb_fname_dst);
7285 /****************************************************************************
7286 Deal with SMB_FILE_RENAME_INFORMATION.
7287 ****************************************************************************/
7289 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7290 struct smb_request *req,
7294 struct smb_filename *smb_fname_src)
7299 char *newname = NULL;
7300 struct smb_filename *smb_fname_dst = NULL;
7301 const char *dst_original_lcomp = NULL;
7302 NTSTATUS status = NT_STATUS_OK;
7304 TALLOC_CTX *ctx = talloc_tos();
7306 if (total_data < 13) {
7307 return NT_STATUS_INVALID_PARAMETER;
7310 overwrite = (CVAL(pdata,0) ? True : False);
7311 root_fid = IVAL(pdata,4);
7312 len = IVAL(pdata,8);
7314 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7315 return NT_STATUS_INVALID_PARAMETER;
7318 if (req->posix_pathnames) {
7319 srvstr_get_path_posix(ctx,
7328 srvstr_get_path(ctx,
7337 if (!NT_STATUS_IS_OK(status)) {
7341 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7344 /* Check the new name has no '/' characters. */
7345 if (strchr_m(newname, '/')) {
7346 return NT_STATUS_NOT_SUPPORTED;
7349 if (fsp && fsp->base_fsp) {
7350 /* newname must be a stream name. */
7351 if (newname[0] != ':') {
7352 return NT_STATUS_NOT_SUPPORTED;
7355 /* Create an smb_fname to call rename_internals_fsp() with. */
7356 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7357 fsp->base_fsp->fsp_name->base_name,
7360 fsp->base_fsp->fsp_name->twrp,
7361 fsp->base_fsp->fsp_name->flags);
7362 if (smb_fname_dst == NULL) {
7363 status = NT_STATUS_NO_MEMORY;
7368 * Get the original last component, since
7369 * rename_internals_fsp() requires it.
7371 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7375 if (dst_original_lcomp == NULL) {
7376 status = NT_STATUS_NO_MEMORY;
7382 * Build up an smb_fname_dst based on the filename passed in.
7383 * We basically just strip off the last component, and put on
7384 * the newname instead.
7386 char *base_name = NULL;
7387 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP|
7388 ucf_flags_from_smb_request(req);
7390 /* newname must *not* be a stream name. */
7391 if (newname[0] == ':') {
7392 return NT_STATUS_NOT_SUPPORTED;
7396 * Strip off the last component (filename) of the path passed
7399 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7401 return NT_STATUS_NO_MEMORY;
7403 p = strrchr_m(base_name, '/');
7407 base_name = talloc_strdup(ctx, "");
7409 return NT_STATUS_NO_MEMORY;
7412 /* Append the new name. */
7413 base_name = talloc_asprintf_append(base_name,
7417 return NT_STATUS_NO_MEMORY;
7420 status = filename_convert(ctx,
7427 /* If an error we expect this to be
7428 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7430 if (!NT_STATUS_IS_OK(status)) {
7431 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7435 /* Create an smb_fname to call rename_internals_fsp() */
7436 smb_fname_dst = synthetic_smb_fname(ctx,
7440 smb_fname_src->twrp,
7441 smb_fname_src->flags);
7442 if (smb_fname_dst == NULL) {
7443 status = NT_STATUS_NO_MEMORY;
7447 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7451 if (dst_original_lcomp == NULL) {
7452 status = NT_STATUS_NO_MEMORY;
7458 DEBUG(10,("smb_file_rename_information: "
7459 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7460 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7461 smb_fname_str_dbg(smb_fname_dst)));
7462 status = rename_internals_fsp(conn,
7469 DEBUG(10,("smb_file_rename_information: "
7470 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7471 smb_fname_str_dbg(smb_fname_src),
7472 smb_fname_str_dbg(smb_fname_dst)));
7473 status = rename_internals(ctx,
7482 FILE_WRITE_ATTRIBUTES);
7485 TALLOC_FREE(smb_fname_dst);
7489 /****************************************************************************
7490 Deal with SMB_SET_POSIX_ACL.
7491 ****************************************************************************/
7493 #if defined(HAVE_POSIX_ACLS)
7494 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7495 struct smb_request *req,
7499 const struct smb_filename *smb_fname)
7501 uint16_t posix_acl_version;
7502 uint16_t num_file_acls;
7503 uint16_t num_def_acls;
7504 bool valid_file_acls = true;
7505 bool valid_def_acls = true;
7507 unsigned int size_needed;
7508 unsigned int total_data;
7509 bool close_fsp = false;
7511 if (total_data_in < 0) {
7512 status = NT_STATUS_INVALID_PARAMETER;
7516 total_data = total_data_in;
7518 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7519 status = NT_STATUS_INVALID_PARAMETER;
7522 posix_acl_version = SVAL(pdata,0);
7523 num_file_acls = SVAL(pdata,2);
7524 num_def_acls = SVAL(pdata,4);
7526 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7527 valid_file_acls = false;
7531 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7532 valid_def_acls = false;
7536 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7537 status = NT_STATUS_INVALID_PARAMETER;
7542 if (num_file_acls + num_def_acls < num_file_acls) {
7543 status = NT_STATUS_INVALID_PARAMETER;
7547 size_needed = num_file_acls + num_def_acls;
7550 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7551 * than UINT_MAX, so check by division.
7553 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7554 status = NT_STATUS_INVALID_PARAMETER;
7558 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7559 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7560 status = NT_STATUS_INVALID_PARAMETER;
7563 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7565 if (total_data < size_needed) {
7566 status = NT_STATUS_INVALID_PARAMETER;
7571 * Ensure we always operate on a file descriptor, not just
7575 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7577 SEC_STD_READ_CONTROL|
7578 FILE_READ_ATTRIBUTES|
7579 FILE_WRITE_ATTRIBUTES;
7581 status = get_posix_fsp(conn,
7587 if (!NT_STATUS_IS_OK(status)) {
7593 /* Here we know fsp != NULL */
7594 SMB_ASSERT(fsp != NULL);
7596 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7597 if (!NT_STATUS_IS_OK(status)) {
7601 /* If we have a default acl, this *must* be a directory. */
7602 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7603 DBG_INFO("Can't set default acls on "
7604 "non-directory %s\n",
7606 return NT_STATUS_INVALID_HANDLE;
7609 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7610 "num_def_acls = %"PRIu16"\n",
7615 /* Move pdata to the start of the file ACL entries. */
7616 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7618 if (valid_file_acls) {
7619 status = set_unix_posix_acl(conn,
7623 if (!NT_STATUS_IS_OK(status)) {
7628 /* Move pdata to the start of the default ACL entries. */
7629 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7631 if (valid_def_acls) {
7632 status = set_unix_posix_default_acl(conn,
7636 if (!NT_STATUS_IS_OK(status)) {
7641 status = NT_STATUS_OK;
7646 (void)close_file(req, fsp, NORMAL_CLOSE);
7653 /****************************************************************************
7654 Deal with SMB_SET_POSIX_LOCK.
7655 ****************************************************************************/
7657 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7659 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7660 struct smb_request *req,
7665 struct tevent_req *subreq = NULL;
7666 struct smbd_lock_element *lck = NULL;
7670 bool blocking_lock = False;
7671 enum brl_type lock_type;
7673 NTSTATUS status = NT_STATUS_OK;
7676 fsp->fsp_flags.is_pathref ||
7677 fsp_get_io_fd(fsp) == -1)
7679 return NT_STATUS_INVALID_HANDLE;
7682 if (total_data != POSIX_LOCK_DATA_SIZE) {
7683 return NT_STATUS_INVALID_PARAMETER;
7686 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7687 case POSIX_LOCK_TYPE_READ:
7688 lock_type = READ_LOCK;
7690 case POSIX_LOCK_TYPE_WRITE:
7691 /* Return the right POSIX-mappable error code for files opened read-only. */
7692 if (!fsp->fsp_flags.can_write) {
7693 return NT_STATUS_INVALID_HANDLE;
7695 lock_type = WRITE_LOCK;
7697 case POSIX_LOCK_TYPE_UNLOCK:
7698 lock_type = UNLOCK_LOCK;
7701 return NT_STATUS_INVALID_PARAMETER;
7704 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7705 case POSIX_LOCK_FLAG_NOWAIT:
7706 blocking_lock = false;
7708 case POSIX_LOCK_FLAG_WAIT:
7709 blocking_lock = true;
7712 return NT_STATUS_INVALID_PARAMETER;
7715 if (!lp_blocking_locks(SNUM(conn))) {
7716 blocking_lock = False;
7719 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7720 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7721 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7722 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7723 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7725 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7726 "count = %"PRIu64", offset = %"PRIu64"\n",
7728 (unsigned int)lock_type,
7733 if (lock_type == UNLOCK_LOCK) {
7734 struct smbd_lock_element l = {
7735 .req_guid = smbd_request_guid(req, 0),
7737 .brltype = UNLOCK_LOCK,
7741 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7745 lck = talloc(req, struct smbd_lock_element);
7747 return NT_STATUS_NO_MEMORY;
7750 *lck = (struct smbd_lock_element) {
7751 .req_guid = smbd_request_guid(req, 0),
7753 .brltype = lock_type,
7758 subreq = smbd_smb1_do_locks_send(
7763 blocking_lock ? UINT32_MAX : 0,
7764 true, /* large_offset */
7768 if (subreq == NULL) {
7770 return NT_STATUS_NO_MEMORY;
7772 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7773 return NT_STATUS_EVENT_PENDING;
7776 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7778 struct smb_request *req = NULL;
7782 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7785 status = smbd_smb1_do_locks_recv(subreq);
7786 TALLOC_FREE(subreq);
7788 if (NT_STATUS_IS_OK(status)) {
7789 char params[2] = {0};
7790 /* Fake up max_data_bytes here - we know it fits. */
7791 send_trans2_replies(
7801 reply_nterror(req, status);
7804 (char *)req->outbuf,
7807 IS_CONN_ENCRYPTED(req->conn),
7810 exit_server_cleanly("smb_set_posix_lock_done: "
7811 "srv_send_smb failed.");
7819 /****************************************************************************
7820 Deal with SMB_SET_FILE_BASIC_INFO.
7821 ****************************************************************************/
7823 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7827 const struct smb_filename *smb_fname)
7829 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7830 struct smb_file_time ft;
7831 uint32_t dosmode = 0;
7832 NTSTATUS status = NT_STATUS_OK;
7834 init_smb_file_time(&ft);
7836 if (total_data < 36) {
7837 return NT_STATUS_INVALID_PARAMETER;
7841 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7843 status = smbd_check_access_rights(conn,
7847 FILE_WRITE_ATTRIBUTES);
7849 if (!NT_STATUS_IS_OK(status)) {
7853 /* Set the attributes */
7854 dosmode = IVAL(pdata,32);
7855 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7856 if (!NT_STATUS_IS_OK(status)) {
7861 ft.create_time = pull_long_date_full_timespec(pdata);
7864 ft.atime = pull_long_date_full_timespec(pdata+8);
7867 ft.mtime = pull_long_date_full_timespec(pdata+16);
7870 ft.ctime = pull_long_date_full_timespec(pdata+24);
7872 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7873 smb_fname_str_dbg(smb_fname)));
7875 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7876 if (!NT_STATUS_IS_OK(status)) {
7880 if (fsp != NULL && fsp->fsp_flags.modified) {
7881 trigger_write_time_update_immediate(fsp);
7883 return NT_STATUS_OK;
7886 /****************************************************************************
7887 Deal with SMB_INFO_STANDARD.
7888 ****************************************************************************/
7890 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7894 const struct smb_filename *smb_fname)
7897 struct smb_file_time ft;
7899 init_smb_file_time(&ft);
7901 if (total_data < 12) {
7902 return NT_STATUS_INVALID_PARAMETER;
7906 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7908 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7910 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7912 DEBUG(10,("smb_set_info_standard: file %s\n",
7913 smb_fname_str_dbg(smb_fname)));
7916 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7918 status = smbd_check_access_rights(conn,
7922 FILE_WRITE_ATTRIBUTES);
7924 if (!NT_STATUS_IS_OK(status)) {
7928 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7929 if (!NT_STATUS_IS_OK(status)) {
7933 if (fsp != NULL && fsp->fsp_flags.modified) {
7934 trigger_write_time_update_immediate(fsp);
7936 return NT_STATUS_OK;
7939 /****************************************************************************
7940 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7941 ****************************************************************************/
7943 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7944 struct smb_request *req,
7948 struct smb_filename *smb_fname)
7950 uint64_t allocation_size = 0;
7951 NTSTATUS status = NT_STATUS_OK;
7952 files_struct *new_fsp = NULL;
7954 if (!VALID_STAT(smb_fname->st)) {
7955 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7958 if (total_data < 8) {
7959 return NT_STATUS_INVALID_PARAMETER;
7962 allocation_size = (uint64_t)IVAL(pdata,0);
7963 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7964 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7965 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7966 (double)allocation_size));
7968 if (allocation_size) {
7969 allocation_size = smb_roundup(conn, allocation_size);
7972 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7973 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7974 (double)allocation_size));
7977 !fsp->fsp_flags.is_pathref &&
7978 fsp_get_io_fd(fsp) != -1)
7980 /* Open file handle. */
7981 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7982 return NT_STATUS_ACCESS_DENIED;
7985 /* Only change if needed. */
7986 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7987 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7988 return map_nt_error_from_unix(errno);
7991 /* But always update the time. */
7993 * This is equivalent to a write. Ensure it's seen immediately
7994 * if there are no pending writes.
7996 trigger_write_time_update_immediate(fsp);
7997 return NT_STATUS_OK;
8000 /* Pathname or stat or directory file. */
8001 status = SMB_VFS_CREATE_FILE(
8004 smb_fname, /* fname */
8005 FILE_WRITE_DATA, /* access_mask */
8006 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8008 FILE_OPEN, /* create_disposition*/
8009 0, /* create_options */
8010 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8011 0, /* oplock_request */
8013 0, /* allocation_size */
8014 0, /* private_flags */
8017 &new_fsp, /* result */
8019 NULL, NULL); /* create context */
8021 if (!NT_STATUS_IS_OK(status)) {
8022 /* NB. We check for open_was_deferred in the caller. */
8026 /* Only change if needed. */
8027 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8028 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8029 status = map_nt_error_from_unix(errno);
8030 close_file(req, new_fsp, NORMAL_CLOSE);
8035 /* Changing the allocation size should set the last mod time. */
8037 * This is equivalent to a write. Ensure it's seen immediately
8038 * if there are no pending writes.
8040 trigger_write_time_update_immediate(new_fsp);
8041 close_file(req, new_fsp, NORMAL_CLOSE);
8042 return NT_STATUS_OK;
8045 /****************************************************************************
8046 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8047 ****************************************************************************/
8049 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8050 struct smb_request *req,
8054 const struct smb_filename *smb_fname,
8055 bool fail_after_createfile)
8059 if (total_data < 8) {
8060 return NT_STATUS_INVALID_PARAMETER;
8063 size = IVAL(pdata,0);
8064 size |= (((off_t)IVAL(pdata,4)) << 32);
8065 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8066 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8069 return smb_set_file_size(conn, req,
8074 fail_after_createfile);
8077 /****************************************************************************
8078 Allow a UNIX info mknod.
8079 ****************************************************************************/
8081 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8084 const struct smb_filename *smb_fname)
8086 uint32_t file_type = IVAL(pdata,56);
8087 #if defined(HAVE_MAKEDEV)
8088 uint32_t dev_major = IVAL(pdata,60);
8089 uint32_t dev_minor = IVAL(pdata,68);
8091 SMB_DEV_T dev = (SMB_DEV_T)0;
8092 uint32_t raw_unixmode = IVAL(pdata,84);
8097 if (total_data < 100) {
8098 return NT_STATUS_INVALID_PARAMETER;
8101 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8102 PERM_NEW_FILE, &unixmode);
8103 if (!NT_STATUS_IS_OK(status)) {
8107 #if defined(HAVE_MAKEDEV)
8108 dev = makedev(dev_major, dev_minor);
8111 switch (file_type) {
8112 /* We can't create other objects here. */
8113 case UNIX_TYPE_FILE:
8115 case UNIX_TYPE_SYMLINK:
8116 return NT_STATUS_ACCESS_DENIED;
8117 #if defined(S_IFIFO)
8118 case UNIX_TYPE_FIFO:
8119 unixmode |= S_IFIFO;
8122 #if defined(S_IFSOCK)
8123 case UNIX_TYPE_SOCKET:
8124 unixmode |= S_IFSOCK;
8127 #if defined(S_IFCHR)
8128 case UNIX_TYPE_CHARDEV:
8129 /* This is only allowed for root. */
8130 if (get_current_uid(conn) != sec_initial_uid()) {
8131 return NT_STATUS_ACCESS_DENIED;
8133 unixmode |= S_IFCHR;
8136 #if defined(S_IFBLK)
8137 case UNIX_TYPE_BLKDEV:
8138 if (get_current_uid(conn) != sec_initial_uid()) {
8139 return NT_STATUS_ACCESS_DENIED;
8141 unixmode |= S_IFBLK;
8145 return NT_STATUS_INVALID_PARAMETER;
8148 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8149 "%.0f mode 0%o for file %s\n", (double)dev,
8150 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8152 /* Ok - do the mknod. */
8153 ret = SMB_VFS_MKNODAT(conn,
8160 return map_nt_error_from_unix(errno);
8163 /* If any of the other "set" calls fail we
8164 * don't want to end up with a half-constructed mknod.
8167 if (lp_inherit_permissions(SNUM(conn))) {
8168 struct smb_filename *parent_fname = NULL;
8171 ok = parent_smb_fname(talloc_tos(),
8176 return NT_STATUS_NO_MEMORY;
8178 inherit_access_posix_acl(conn,
8182 TALLOC_FREE(parent_fname);
8185 return NT_STATUS_OK;
8188 /****************************************************************************
8189 Deal with SMB_SET_FILE_UNIX_BASIC.
8190 ****************************************************************************/
8192 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8193 struct smb_request *req,
8197 const struct smb_filename *smb_fname)
8199 struct smb_file_time ft;
8200 uint32_t raw_unixmode;
8203 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8204 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8205 NTSTATUS status = NT_STATUS_OK;
8206 enum perm_type ptype;
8207 files_struct *all_fsps = NULL;
8208 bool modify_mtime = true;
8210 SMB_STRUCT_STAT sbuf;
8212 init_smb_file_time(&ft);
8214 if (total_data < 100) {
8215 return NT_STATUS_INVALID_PARAMETER;
8218 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8219 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8220 size=IVAL(pdata,0); /* first 8 Bytes are size */
8221 size |= (((off_t)IVAL(pdata,4)) << 32);
8224 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8225 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8226 set_owner = (uid_t)IVAL(pdata,40);
8227 set_grp = (gid_t)IVAL(pdata,48);
8228 raw_unixmode = IVAL(pdata,84);
8230 if (VALID_STAT(smb_fname->st)) {
8231 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8232 ptype = PERM_EXISTING_DIR;
8234 ptype = PERM_EXISTING_FILE;
8237 ptype = PERM_NEW_FILE;
8240 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8242 if (!NT_STATUS_IS_OK(status)) {
8246 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8247 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8248 smb_fname_str_dbg(smb_fname), (double)size,
8249 (unsigned int)set_owner, (unsigned int)set_grp,
8250 (int)raw_unixmode));
8252 sbuf = smb_fname->st;
8254 if (!VALID_STAT(sbuf)) {
8256 * The only valid use of this is to create character and block
8257 * devices, and named pipes. This is deprecated (IMHO) and
8258 * a new info level should be used for mknod. JRA.
8261 return smb_unix_mknod(conn,
8268 /* Horrible backwards compatibility hack as an old server bug
8269 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8273 size = get_file_size_stat(&sbuf);
8278 * Deal with the UNIX specific mode set.
8281 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8284 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8285 "setting mode 0%o for file %s\n",
8286 (unsigned int)unixmode,
8287 smb_fname_str_dbg(smb_fname)));
8289 !fsp->fsp_flags.is_pathref &&
8290 fsp_get_io_fd(fsp) != -1)
8292 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8294 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8297 return map_nt_error_from_unix(errno);
8302 * Deal with the UNIX specific uid set.
8305 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8306 (sbuf.st_ex_uid != set_owner)) {
8309 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8310 "changing owner %u for path %s\n",
8311 (unsigned int)set_owner,
8312 smb_fname_str_dbg(smb_fname)));
8315 !fsp->fsp_flags.is_pathref &&
8316 fsp_get_io_fd(fsp) != -1)
8318 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8321 * UNIX extensions calls must always operate
8324 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8325 set_owner, (gid_t)-1);
8329 status = map_nt_error_from_unix(errno);
8335 * Deal with the UNIX specific gid set.
8338 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8339 (sbuf.st_ex_gid != set_grp)) {
8342 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8343 "changing group %u for file %s\n",
8344 (unsigned int)set_grp,
8345 smb_fname_str_dbg(smb_fname)));
8347 !fsp->fsp_flags.is_pathref &&
8348 fsp_get_io_fd(fsp) != -1)
8350 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8353 * UNIX extensions calls must always operate
8356 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8360 status = map_nt_error_from_unix(errno);
8365 /* Deal with any size changes. */
8367 if (S_ISREG(sbuf.st_ex_mode)) {
8368 status = smb_set_file_size(conn, req,
8374 if (!NT_STATUS_IS_OK(status)) {
8379 /* Deal with any time changes. */
8380 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8381 /* No change, don't cancel anything. */
8385 id = vfs_file_id_from_sbuf(conn, &sbuf);
8386 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8387 all_fsps = file_find_di_next(all_fsps)) {
8389 * We're setting the time explicitly for UNIX.
8390 * Cancel any pending changes over all handles.
8392 all_fsps->fsp_flags.update_write_time_on_close = false;
8393 TALLOC_FREE(all_fsps->update_write_time_event);
8397 * Override the "setting_write_time"
8398 * parameter here as it almost does what
8399 * we need. Just remember if we modified
8400 * mtime and send the notify ourselves.
8402 if (is_omit_timespec(&ft.mtime)) {
8403 modify_mtime = false;
8406 status = smb_set_file_time(conn,
8412 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8413 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8418 /****************************************************************************
8419 Deal with SMB_SET_FILE_UNIX_INFO2.
8420 ****************************************************************************/
8422 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8423 struct smb_request *req,
8427 const struct smb_filename *smb_fname)
8430 uint32_t smb_fflags;
8433 if (total_data < 116) {
8434 return NT_STATUS_INVALID_PARAMETER;
8437 /* Start by setting all the fields that are common between UNIX_BASIC
8440 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8442 if (!NT_STATUS_IS_OK(status)) {
8446 smb_fflags = IVAL(pdata, 108);
8447 smb_fmask = IVAL(pdata, 112);
8449 /* NB: We should only attempt to alter the file flags if the client
8450 * sends a non-zero mask.
8452 if (smb_fmask != 0) {
8453 int stat_fflags = 0;
8455 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8456 smb_fmask, &stat_fflags)) {
8457 /* Client asked to alter a flag we don't understand. */
8458 return NT_STATUS_INVALID_PARAMETER;
8462 !fsp->fsp_flags.is_pathref &&
8463 fsp_get_io_fd(fsp) != -1)
8465 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8466 return NT_STATUS_NOT_SUPPORTED;
8468 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8469 stat_fflags) != 0) {
8470 return map_nt_error_from_unix(errno);
8475 /* XXX: need to add support for changing the create_time here. You
8476 * can do this for paths on Darwin with setattrlist(2). The right way
8477 * to hook this up is probably by extending the VFS utimes interface.
8480 return NT_STATUS_OK;
8483 /****************************************************************************
8484 Create a directory with POSIX semantics.
8485 ****************************************************************************/
8487 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8488 struct smb_request *req,
8491 struct smb_filename *smb_fname,
8492 int *pdata_return_size)
8494 NTSTATUS status = NT_STATUS_OK;
8495 uint32_t raw_unixmode = 0;
8496 mode_t unixmode = (mode_t)0;
8497 files_struct *fsp = NULL;
8498 uint16_t info_level_return = 0;
8500 char *pdata = *ppdata;
8501 struct smb2_create_blobs *posx = NULL;
8503 if (total_data < 18) {
8504 return NT_STATUS_INVALID_PARAMETER;
8507 raw_unixmode = IVAL(pdata,8);
8508 /* Next 4 bytes are not yet defined. */
8510 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8511 PERM_NEW_DIR, &unixmode);
8512 if (!NT_STATUS_IS_OK(status)) {
8516 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8517 if (!NT_STATUS_IS_OK(status)) {
8518 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8523 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8524 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8526 status = SMB_VFS_CREATE_FILE(
8529 smb_fname, /* fname */
8530 FILE_READ_ATTRIBUTES, /* access_mask */
8531 FILE_SHARE_NONE, /* share_access */
8532 FILE_CREATE, /* create_disposition*/
8533 FILE_DIRECTORY_FILE, /* create_options */
8534 0, /* file_attributes */
8535 0, /* oplock_request */
8537 0, /* allocation_size */
8538 0, /* private_flags */
8543 posx, /* in_context_blobs */
8544 NULL); /* out_context_blobs */
8548 if (NT_STATUS_IS_OK(status)) {
8549 close_file(req, fsp, NORMAL_CLOSE);
8552 info_level_return = SVAL(pdata,16);
8554 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8555 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8556 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8557 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8559 *pdata_return_size = 12;
8562 /* Realloc the data size */
8563 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8564 if (*ppdata == NULL) {
8565 *pdata_return_size = 0;
8566 return NT_STATUS_NO_MEMORY;
8570 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8571 SSVAL(pdata,2,0); /* No fnum. */
8572 SIVAL(pdata,4,info); /* Was directory created. */
8574 switch (info_level_return) {
8575 case SMB_QUERY_FILE_UNIX_BASIC:
8576 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8577 SSVAL(pdata,10,0); /* Padding. */
8578 store_file_unix_basic(conn, pdata + 12, fsp,
8581 case SMB_QUERY_FILE_UNIX_INFO2:
8582 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8583 SSVAL(pdata,10,0); /* Padding. */
8584 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8588 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8589 SSVAL(pdata,10,0); /* Padding. */
8596 /****************************************************************************
8597 Open/Create a file with POSIX semantics.
8598 ****************************************************************************/
8600 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8601 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8603 static NTSTATUS smb_posix_open(connection_struct *conn,
8604 struct smb_request *req,
8607 struct smb_filename *smb_fname,
8608 int *pdata_return_size)
8610 bool extended_oplock_granted = False;
8611 char *pdata = *ppdata;
8613 uint32_t wire_open_mode = 0;
8614 uint32_t raw_unixmode = 0;
8615 uint32_t attributes = 0;
8616 uint32_t create_disp = 0;
8617 uint32_t access_mask = 0;
8618 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8619 NTSTATUS status = NT_STATUS_OK;
8620 mode_t unixmode = (mode_t)0;
8621 files_struct *fsp = NULL;
8622 int oplock_request = 0;
8624 uint16_t info_level_return = 0;
8625 struct smb2_create_blobs *posx = NULL;
8627 if (total_data < 18) {
8628 return NT_STATUS_INVALID_PARAMETER;
8631 flags = IVAL(pdata,0);
8632 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8633 if (oplock_request) {
8634 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8637 wire_open_mode = IVAL(pdata,4);
8639 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8640 return smb_posix_mkdir(conn, req,
8647 switch (wire_open_mode & SMB_ACCMODE) {
8649 access_mask = SMB_O_RDONLY_MAPPING;
8652 access_mask = SMB_O_WRONLY_MAPPING;
8655 access_mask = (SMB_O_RDONLY_MAPPING|
8656 SMB_O_WRONLY_MAPPING);
8659 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8660 (unsigned int)wire_open_mode ));
8661 return NT_STATUS_INVALID_PARAMETER;
8664 wire_open_mode &= ~SMB_ACCMODE;
8666 /* First take care of O_CREAT|O_EXCL interactions. */
8667 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8668 case (SMB_O_CREAT | SMB_O_EXCL):
8669 /* File exists fail. File not exist create. */
8670 create_disp = FILE_CREATE;
8673 /* File exists open. File not exist create. */
8674 create_disp = FILE_OPEN_IF;
8677 /* O_EXCL on its own without O_CREAT is undefined.
8678 We deliberately ignore it as some versions of
8679 Linux CIFSFS can send a bare O_EXCL on the
8680 wire which other filesystems in the kernel
8681 ignore. See bug 9519 for details. */
8686 /* File exists open. File not exist fail. */
8687 create_disp = FILE_OPEN;
8690 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8691 (unsigned int)wire_open_mode ));
8692 return NT_STATUS_INVALID_PARAMETER;
8695 /* Next factor in the effects of O_TRUNC. */
8696 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8698 if (wire_open_mode & SMB_O_TRUNC) {
8699 switch (create_disp) {
8701 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8702 /* Leave create_disp alone as
8703 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8705 /* File exists fail. File not exist create. */
8708 /* SMB_O_CREAT | SMB_O_TRUNC */
8709 /* File exists overwrite. File not exist create. */
8710 create_disp = FILE_OVERWRITE_IF;
8714 /* File exists overwrite. File not exist fail. */
8715 create_disp = FILE_OVERWRITE;
8718 /* Cannot get here. */
8719 smb_panic("smb_posix_open: logic error");
8720 return NT_STATUS_INVALID_PARAMETER;
8724 raw_unixmode = IVAL(pdata,8);
8725 /* Next 4 bytes are not yet defined. */
8727 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8728 (VALID_STAT(smb_fname->st) ?
8729 PERM_EXISTING_FILE : PERM_NEW_FILE),
8732 if (!NT_STATUS_IS_OK(status)) {
8736 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8737 if (!NT_STATUS_IS_OK(status)) {
8738 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8743 if (wire_open_mode & SMB_O_SYNC) {
8744 create_options |= FILE_WRITE_THROUGH;
8746 if (wire_open_mode & SMB_O_APPEND) {
8747 access_mask |= FILE_APPEND_DATA;
8749 if (wire_open_mode & SMB_O_DIRECT) {
8750 attributes |= FILE_FLAG_NO_BUFFERING;
8753 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8754 VALID_STAT_OF_DIR(smb_fname->st)) {
8755 if (access_mask != SMB_O_RDONLY_MAPPING) {
8756 return NT_STATUS_FILE_IS_A_DIRECTORY;
8758 create_options &= ~FILE_NON_DIRECTORY_FILE;
8759 create_options |= FILE_DIRECTORY_FILE;
8762 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8763 smb_fname_str_dbg(smb_fname),
8764 (unsigned int)wire_open_mode,
8765 (unsigned int)unixmode ));
8767 status = SMB_VFS_CREATE_FILE(
8770 smb_fname, /* fname */
8771 access_mask, /* access_mask */
8772 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8774 create_disp, /* create_disposition*/
8775 create_options, /* create_options */
8776 attributes, /* file_attributes */
8777 oplock_request, /* oplock_request */
8779 0, /* allocation_size */
8780 0, /* private_flags */
8785 posx, /* in_context_blobs */
8786 NULL); /* out_context_blobs */
8790 if (!NT_STATUS_IS_OK(status)) {
8794 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8795 extended_oplock_granted = True;
8798 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8799 extended_oplock_granted = True;
8802 info_level_return = SVAL(pdata,16);
8804 /* Allocate the correct return size. */
8806 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8807 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8808 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8809 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8811 *pdata_return_size = 12;
8814 /* Realloc the data size */
8815 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8816 if (*ppdata == NULL) {
8817 close_file(req, fsp, ERROR_CLOSE);
8818 *pdata_return_size = 0;
8819 return NT_STATUS_NO_MEMORY;
8823 if (extended_oplock_granted) {
8824 if (flags & REQUEST_BATCH_OPLOCK) {
8825 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8827 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8829 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8830 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8832 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8835 SSVAL(pdata,2,fsp->fnum);
8836 SIVAL(pdata,4,info); /* Was file created etc. */
8838 switch (info_level_return) {
8839 case SMB_QUERY_FILE_UNIX_BASIC:
8840 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8841 SSVAL(pdata,10,0); /* padding. */
8842 store_file_unix_basic(conn, pdata + 12, fsp,
8845 case SMB_QUERY_FILE_UNIX_INFO2:
8846 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8847 SSVAL(pdata,10,0); /* padding. */
8848 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8852 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8853 SSVAL(pdata,10,0); /* padding. */
8856 return NT_STATUS_OK;
8859 /****************************************************************************
8860 Delete a file with POSIX semantics.
8861 ****************************************************************************/
8863 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8864 struct smb_request *req,
8867 struct smb_filename *smb_fname)
8869 NTSTATUS status = NT_STATUS_OK;
8870 files_struct *fsp = NULL;
8874 int create_options = 0;
8875 struct share_mode_lock *lck = NULL;
8876 bool other_nonposix_opens;
8877 struct smb2_create_blobs *posx = NULL;
8879 if (total_data < 2) {
8880 return NT_STATUS_INVALID_PARAMETER;
8883 flags = SVAL(pdata,0);
8885 if (!VALID_STAT(smb_fname->st)) {
8886 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8889 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8890 !VALID_STAT_OF_DIR(smb_fname->st)) {
8891 return NT_STATUS_NOT_A_DIRECTORY;
8894 DEBUG(10,("smb_posix_unlink: %s %s\n",
8895 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8896 smb_fname_str_dbg(smb_fname)));
8898 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8899 create_options |= FILE_DIRECTORY_FILE;
8902 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8903 if (!NT_STATUS_IS_OK(status)) {
8904 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8909 status = SMB_VFS_CREATE_FILE(
8912 smb_fname, /* fname */
8913 DELETE_ACCESS, /* access_mask */
8914 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8916 FILE_OPEN, /* create_disposition*/
8917 create_options, /* create_options */
8918 0, /* file_attributes */
8919 0, /* oplock_request */
8921 0, /* allocation_size */
8922 0, /* private_flags */
8927 posx, /* in_context_blobs */
8928 NULL); /* out_context_blobs */
8932 if (!NT_STATUS_IS_OK(status)) {
8937 * Don't lie to client. If we can't really delete due to
8938 * non-POSIX opens return SHARING_VIOLATION.
8941 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8943 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8944 "lock for file %s\n", fsp_str_dbg(fsp)));
8945 close_file(req, fsp, NORMAL_CLOSE);
8946 return NT_STATUS_INVALID_PARAMETER;
8949 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8950 if (other_nonposix_opens) {
8951 /* Fail with sharing violation. */
8953 close_file(req, fsp, NORMAL_CLOSE);
8954 return NT_STATUS_SHARING_VIOLATION;
8958 * Set the delete on close.
8960 status = smb_set_file_disposition_info(conn,
8968 if (!NT_STATUS_IS_OK(status)) {
8969 close_file(req, fsp, NORMAL_CLOSE);
8972 return close_file(req, fsp, NORMAL_CLOSE);
8975 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
8976 struct smb_request *req,
8977 TALLOC_CTX *mem_ctx,
8978 uint16_t info_level,
8979 struct smb_filename *smb_fname,
8985 char *pdata = *ppdata;
8986 NTSTATUS status = NT_STATUS_OK;
8987 int data_return_size = 0;
8991 if (!CAN_WRITE(conn)) {
8992 /* Allow POSIX opens. The open path will deny
8993 * any non-readonly opens. */
8994 if (info_level != SMB_POSIX_PATH_OPEN) {
8995 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8999 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
9000 smb_fname_str_dbg(smb_fname),
9005 switch (info_level) {
9006 case SMB_SET_FILE_UNIX_BASIC:
9008 status = smb_set_file_unix_basic(conn, req,
9016 case SMB_SET_FILE_UNIX_INFO2:
9018 status = smb_set_file_unix_info2(conn, req,
9026 case SMB_SET_FILE_UNIX_LINK:
9028 if (smb_fname == NULL) {
9029 /* We must have a pathname for this. */
9030 return NT_STATUS_INVALID_LEVEL;
9032 status = smb_set_file_unix_link(conn, req, pdata,
9033 total_data, smb_fname);
9037 case SMB_SET_FILE_UNIX_HLINK:
9039 if (smb_fname == NULL) {
9040 /* We must have a pathname for this. */
9041 return NT_STATUS_INVALID_LEVEL;
9043 status = smb_set_file_unix_hlink(conn, req,
9049 #if defined(HAVE_POSIX_ACLS)
9050 case SMB_SET_POSIX_ACL:
9052 status = smb_set_posix_acl(conn,
9062 case SMB_SET_POSIX_LOCK:
9065 return NT_STATUS_INVALID_LEVEL;
9067 status = smb_set_posix_lock(conn, req,
9068 pdata, total_data, fsp);
9072 case SMB_POSIX_PATH_OPEN:
9074 if (smb_fname == NULL) {
9075 /* We must have a pathname for this. */
9076 return NT_STATUS_INVALID_LEVEL;
9079 status = smb_posix_open(conn, req,
9087 case SMB_POSIX_PATH_UNLINK:
9089 if (smb_fname == NULL) {
9090 /* We must have a pathname for this. */
9091 return NT_STATUS_INVALID_LEVEL;
9094 status = smb_posix_unlink(conn, req,
9102 return NT_STATUS_INVALID_LEVEL;
9105 if (!NT_STATUS_IS_OK(status)) {
9109 *ret_data_size = data_return_size;
9110 return NT_STATUS_OK;
9113 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
9114 struct smb_request *req,
9115 TALLOC_CTX *mem_ctx,
9116 uint16_t info_level,
9118 struct smb_filename *smb_fname,
9119 char **ppdata, int total_data,
9122 char *pdata = *ppdata;
9123 NTSTATUS status = NT_STATUS_OK;
9124 int data_return_size = 0;
9126 if (INFO_LEVEL_IS_UNIX(info_level)) {
9127 if (!lp_unix_extensions()) {
9128 return NT_STATUS_INVALID_LEVEL;
9131 status = smbd_do_posix_setfilepathinfo(conn,
9140 if (!NT_STATUS_IS_OK(status)) {
9143 *ret_data_size = data_return_size;
9144 return NT_STATUS_OK;
9149 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9150 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9152 info_level, total_data));
9154 switch (info_level) {
9156 case SMB_INFO_STANDARD:
9158 status = smb_set_info_standard(conn,
9166 case SMB_INFO_SET_EA:
9168 status = smb_info_set_ea(conn,
9176 case SMB_SET_FILE_BASIC_INFO:
9177 case SMB_FILE_BASIC_INFORMATION:
9179 status = smb_set_file_basic_info(conn,
9187 case SMB_FILE_ALLOCATION_INFORMATION:
9188 case SMB_SET_FILE_ALLOCATION_INFO:
9190 status = smb_set_file_allocation_info(conn, req,
9198 case SMB_FILE_END_OF_FILE_INFORMATION:
9199 case SMB_SET_FILE_END_OF_FILE_INFO:
9202 * XP/Win7 both fail after the createfile with
9203 * SMB_SET_FILE_END_OF_FILE_INFO but not
9204 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9205 * The level is known here, so pass it down
9209 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9211 status = smb_set_file_end_of_file_info(conn, req,
9220 case SMB_FILE_DISPOSITION_INFORMATION:
9221 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9224 /* JRA - We used to just ignore this on a path ?
9225 * Shouldn't this be invalid level on a pathname
9228 if (tran_call != TRANSACT2_SETFILEINFO) {
9229 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9232 status = smb_set_file_disposition_info(conn,
9240 case SMB_FILE_POSITION_INFORMATION:
9242 status = smb_file_position_information(conn,
9249 case SMB_FILE_FULL_EA_INFORMATION:
9251 status = smb_set_file_full_ea_info(conn,
9258 /* From tridge Samba4 :
9259 * MODE_INFORMATION in setfileinfo (I have no
9260 * idea what "mode information" on a file is - it takes a value of 0,
9261 * 2, 4 or 6. What could it be?).
9264 case SMB_FILE_MODE_INFORMATION:
9266 status = smb_file_mode_information(conn,
9272 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9273 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9274 case SMB_FILE_SHORT_NAME_INFORMATION:
9275 return NT_STATUS_NOT_SUPPORTED;
9277 case SMB_FILE_RENAME_INFORMATION:
9279 status = smb_file_rename_information(conn, req,
9285 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9287 /* SMB2 rename information. */
9288 status = smb2_file_rename_information(conn, req,
9294 case SMB_FILE_LINK_INFORMATION:
9296 status = smb_file_link_information(conn, req,
9303 return NT_STATUS_INVALID_LEVEL;
9306 if (!NT_STATUS_IS_OK(status)) {
9310 *ret_data_size = data_return_size;
9311 return NT_STATUS_OK;
9314 /****************************************************************************
9315 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9316 ****************************************************************************/
9318 static void call_trans2setfilepathinfo(connection_struct *conn,
9319 struct smb_request *req,
9320 unsigned int tran_call,
9321 char **pparams, int total_params,
9322 char **ppdata, int total_data,
9323 unsigned int max_data_bytes)
9325 char *params = *pparams;
9326 char *pdata = *ppdata;
9327 uint16_t info_level;
9328 struct smb_filename *smb_fname = NULL;
9329 files_struct *fsp = NULL;
9330 NTSTATUS status = NT_STATUS_OK;
9331 int data_return_size = 0;
9334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9338 if (tran_call == TRANSACT2_SETFILEINFO) {
9339 if (total_params < 4) {
9340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9344 fsp = file_fsp(req, SVAL(params,0));
9345 /* Basic check for non-null fsp. */
9346 if (!check_fsp_open(conn, req, fsp)) {
9349 info_level = SVAL(params,2);
9351 smb_fname = fsp->fsp_name;
9353 if (fsp_get_pathref_fd(fsp) == -1) {
9355 * This is actually a SETFILEINFO on a directory
9356 * handle (returned from an NT SMB). NT5.0 seems
9357 * to do this call. JRA.
9359 if (INFO_LEVEL_IS_UNIX(info_level)) {
9360 /* Always do lstat for UNIX calls. */
9361 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9362 DEBUG(3,("call_trans2setfilepathinfo: "
9363 "SMB_VFS_LSTAT of %s failed "
9365 smb_fname_str_dbg(smb_fname),
9367 reply_nterror(req, map_nt_error_from_unix(errno));
9371 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9372 DEBUG(3,("call_trans2setfilepathinfo: "
9373 "fileinfo of %s failed (%s)\n",
9374 smb_fname_str_dbg(smb_fname),
9376 reply_nterror(req, map_nt_error_from_unix(errno));
9380 } else if (fsp->print_file) {
9382 * Doing a DELETE_ON_CLOSE should cancel a print job.
9384 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9385 fsp->fh->private_options |= NTCREATEX_FLAG_DELETE_ON_CLOSE;
9387 DEBUG(3,("call_trans2setfilepathinfo: "
9388 "Cancelling print job (%s)\n",
9392 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9398 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9403 * Original code - this is an open file.
9405 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9406 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9407 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9409 reply_nterror(req, map_nt_error_from_unix(errno));
9415 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9418 if (total_params < 7) {
9419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9423 info_level = SVAL(params,0);
9424 if (req->posix_pathnames) {
9425 srvstr_get_path_posix(req,
9434 srvstr_get_path(req,
9443 if (!NT_STATUS_IS_OK(status)) {
9444 reply_nterror(req, status);
9448 status = filename_convert(req, conn,
9453 if (!NT_STATUS_IS_OK(status)) {
9454 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9455 reply_botherror(req,
9456 NT_STATUS_PATH_NOT_COVERED,
9457 ERRSRV, ERRbadpath);
9460 reply_nterror(req, status);
9464 if (INFO_LEVEL_IS_UNIX(info_level)) {
9466 * For CIFS UNIX extensions the target name may not exist.
9469 /* Always do lstat for UNIX calls. */
9470 SMB_VFS_LSTAT(conn, smb_fname);
9472 } else if (!VALID_STAT(smb_fname->st) &&
9473 SMB_VFS_STAT(conn, smb_fname)) {
9474 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9476 smb_fname_str_dbg(smb_fname),
9478 reply_nterror(req, map_nt_error_from_unix(errno));
9483 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9484 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9486 info_level,total_data));
9488 /* Realloc the parameter size */
9489 *pparams = (char *)SMB_REALLOC(*pparams,2);
9490 if (*pparams == NULL) {
9491 reply_nterror(req, NT_STATUS_NO_MEMORY);
9498 status = smbd_do_setfilepathinfo(conn, req, req,
9504 if (!NT_STATUS_IS_OK(status)) {
9505 if (open_was_deferred(req->xconn, req->mid)) {
9506 /* We have re-scheduled this call. */
9509 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9510 bool ok = defer_smb1_sharing_violation(req);
9515 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9516 /* We have re-scheduled this call. */
9519 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9520 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9521 ERRSRV, ERRbadpath);
9524 if (info_level == SMB_POSIX_PATH_OPEN) {
9525 reply_openerror(req, status);
9530 * Invalid EA name needs to return 2 param bytes,
9531 * not a zero-length error packet.
9533 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9534 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9537 reply_nterror(req, status);
9542 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9548 /****************************************************************************
9549 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9550 ****************************************************************************/
9552 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9553 char **pparams, int total_params,
9554 char **ppdata, int total_data,
9555 unsigned int max_data_bytes)
9557 struct smb_filename *smb_dname = NULL;
9558 char *params = *pparams;
9559 char *pdata = *ppdata;
9560 char *directory = NULL;
9561 NTSTATUS status = NT_STATUS_OK;
9562 struct ea_list *ea_list = NULL;
9563 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9564 TALLOC_CTX *ctx = talloc_tos();
9566 if (!CAN_WRITE(conn)) {
9567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9571 if (total_params < 5) {
9572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9576 if (req->posix_pathnames) {
9577 srvstr_get_path_posix(ctx,
9586 srvstr_get_path(ctx,
9595 if (!NT_STATUS_IS_OK(status)) {
9596 reply_nterror(req, status);
9600 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9602 status = filename_convert(ctx,
9609 if (!NT_STATUS_IS_OK(status)) {
9610 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9611 reply_botherror(req,
9612 NT_STATUS_PATH_NOT_COVERED,
9613 ERRSRV, ERRbadpath);
9616 reply_nterror(req, status);
9621 * OS/2 workplace shell seems to send SET_EA requests of "null"
9622 * length (4 bytes containing IVAL 4).
9623 * They seem to have no effect. Bug #3212. JRA.
9626 if (total_data && (total_data != 4)) {
9627 /* Any data in this call is an EA list. */
9628 if (total_data < 10) {
9629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9633 if (IVAL(pdata,0) > total_data) {
9634 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9635 IVAL(pdata,0), (unsigned int)total_data));
9636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9640 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9647 if (!lp_ea_support(SNUM(conn))) {
9648 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9652 /* If total_data == 4 Windows doesn't care what values
9653 * are placed in that field, it just ignores them.
9654 * The System i QNTC IBM SMB client puts bad values here,
9655 * so ignore them. */
9657 status = create_directory(conn, req, smb_dname);
9659 if (!NT_STATUS_IS_OK(status)) {
9660 reply_nterror(req, status);
9664 /* Try and set any given EA. */
9666 status = set_ea(conn, NULL, smb_dname, ea_list);
9667 if (!NT_STATUS_IS_OK(status)) {
9668 reply_nterror(req, status);
9673 /* Realloc the parameter and data sizes */
9674 *pparams = (char *)SMB_REALLOC(*pparams,2);
9675 if(*pparams == NULL) {
9676 reply_nterror(req, NT_STATUS_NO_MEMORY);
9683 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9686 TALLOC_FREE(smb_dname);
9690 /****************************************************************************
9691 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9692 We don't actually do this - we just send a null response.
9693 ****************************************************************************/
9695 static void call_trans2findnotifyfirst(connection_struct *conn,
9696 struct smb_request *req,
9697 char **pparams, int total_params,
9698 char **ppdata, int total_data,
9699 unsigned int max_data_bytes)
9701 char *params = *pparams;
9702 uint16_t info_level;
9704 if (total_params < 6) {
9705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9709 info_level = SVAL(params,4);
9710 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9712 switch (info_level) {
9717 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9721 /* Realloc the parameter and data sizes */
9722 *pparams = (char *)SMB_REALLOC(*pparams,6);
9723 if (*pparams == NULL) {
9724 reply_nterror(req, NT_STATUS_NO_MEMORY);
9729 SSVAL(params,0,fnf_handle);
9730 SSVAL(params,2,0); /* No changes */
9731 SSVAL(params,4,0); /* No EA errors */
9738 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9743 /****************************************************************************
9744 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9745 changes). Currently this does nothing.
9746 ****************************************************************************/
9748 static void call_trans2findnotifynext(connection_struct *conn,
9749 struct smb_request *req,
9750 char **pparams, int total_params,
9751 char **ppdata, int total_data,
9752 unsigned int max_data_bytes)
9754 char *params = *pparams;
9756 DEBUG(3,("call_trans2findnotifynext\n"));
9758 /* Realloc the parameter and data sizes */
9759 *pparams = (char *)SMB_REALLOC(*pparams,4);
9760 if (*pparams == NULL) {
9761 reply_nterror(req, NT_STATUS_NO_MEMORY);
9766 SSVAL(params,0,0); /* No changes */
9767 SSVAL(params,2,0); /* No EA errors */
9769 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9774 /****************************************************************************
9775 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9776 ****************************************************************************/
9778 static void call_trans2getdfsreferral(connection_struct *conn,
9779 struct smb_request *req,
9780 char **pparams, int total_params,
9781 char **ppdata, int total_data,
9782 unsigned int max_data_bytes)
9784 char *params = *pparams;
9785 char *pathname = NULL;
9787 int max_referral_level;
9788 NTSTATUS status = NT_STATUS_OK;
9789 TALLOC_CTX *ctx = talloc_tos();
9791 DEBUG(10,("call_trans2getdfsreferral\n"));
9793 if (total_params < 3) {
9794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9798 max_referral_level = SVAL(params,0);
9800 if(!lp_host_msdfs()) {
9801 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9805 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9806 total_params - 2, STR_TERMINATE);
9808 reply_nterror(req, NT_STATUS_NOT_FOUND);
9811 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9812 ppdata,&status)) < 0) {
9813 reply_nterror(req, status);
9817 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9818 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9819 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9824 #define LMCAT_SPL 0x53
9825 #define LMFUNC_GETJOBID 0x60
9827 /****************************************************************************
9828 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9829 ****************************************************************************/
9831 static void call_trans2ioctl(connection_struct *conn,
9832 struct smb_request *req,
9833 char **pparams, int total_params,
9834 char **ppdata, int total_data,
9835 unsigned int max_data_bytes)
9837 const struct loadparm_substitution *lp_sub =
9838 loadparm_s3_global_substitution();
9839 char *pdata = *ppdata;
9840 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9844 /* check for an invalid fid before proceeding */
9847 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9851 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9852 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9853 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9854 if (*ppdata == NULL) {
9855 reply_nterror(req, NT_STATUS_NO_MEMORY);
9860 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9861 CAN ACCEPT THIS IN UNICODE. JRA. */
9864 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9866 status = srvstr_push(pdata, req->flags2, pdata + 2,
9867 lp_netbios_name(), 15,
9868 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9869 if (!NT_STATUS_IS_OK(status)) {
9870 reply_nterror(req, status);
9873 status = srvstr_push(pdata, req->flags2, pdata+18,
9874 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9875 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9876 if (!NT_STATUS_IS_OK(status)) {
9877 reply_nterror(req, status);
9880 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9885 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9886 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9889 /****************************************************************************
9890 Reply to a SMBfindclose (stop trans2 directory search).
9891 ****************************************************************************/
9893 void reply_findclose(struct smb_request *req)
9896 struct smbd_server_connection *sconn = req->sconn;
9897 files_struct *fsp = NULL;
9899 START_PROFILE(SMBfindclose);
9902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9903 END_PROFILE(SMBfindclose);
9907 dptr_num = SVALS(req->vwv+0, 0);
9909 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9912 * OS/2 seems to use -1 to indicate "close all directories"
9913 * This has to mean on this specific connection struct.
9915 if (dptr_num == -1) {
9916 dptr_closecnum(req->conn);
9918 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9921 close_file(NULL, fsp, NORMAL_CLOSE);
9926 reply_outbuf(req, 0, 0);
9928 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9930 END_PROFILE(SMBfindclose);
9934 /****************************************************************************
9935 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9936 ****************************************************************************/
9938 void reply_findnclose(struct smb_request *req)
9942 START_PROFILE(SMBfindnclose);
9945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9946 END_PROFILE(SMBfindnclose);
9950 dptr_num = SVAL(req->vwv+0, 0);
9952 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9954 /* We never give out valid handles for a
9955 findnotifyfirst - so any dptr_num is ok here.
9958 reply_outbuf(req, 0, 0);
9960 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9962 END_PROFILE(SMBfindnclose);
9966 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9967 struct trans_state *state)
9969 if (get_Protocol() >= PROTOCOL_NT1) {
9970 req->flags2 |= 0x40; /* IS_LONG_NAME */
9971 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9974 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9975 if (state->call != TRANSACT2_QFSINFO &&
9976 state->call != TRANSACT2_SETFSINFO) {
9977 DEBUG(0,("handle_trans2: encryption required "
9979 (unsigned int)state->call));
9980 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9985 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9987 /* Now we must call the relevant TRANS2 function */
9988 switch(state->call) {
9989 case TRANSACT2_OPEN:
9991 START_PROFILE(Trans2_open);
9992 call_trans2open(conn, req,
9993 &state->param, state->total_param,
9994 &state->data, state->total_data,
9995 state->max_data_return);
9996 END_PROFILE(Trans2_open);
10000 case TRANSACT2_FINDFIRST:
10002 START_PROFILE(Trans2_findfirst);
10003 call_trans2findfirst(conn, req,
10004 &state->param, state->total_param,
10005 &state->data, state->total_data,
10006 state->max_data_return);
10007 END_PROFILE(Trans2_findfirst);
10011 case TRANSACT2_FINDNEXT:
10013 START_PROFILE(Trans2_findnext);
10014 call_trans2findnext(conn, req,
10015 &state->param, state->total_param,
10016 &state->data, state->total_data,
10017 state->max_data_return);
10018 END_PROFILE(Trans2_findnext);
10022 case TRANSACT2_QFSINFO:
10024 START_PROFILE(Trans2_qfsinfo);
10025 call_trans2qfsinfo(conn, req,
10026 &state->param, state->total_param,
10027 &state->data, state->total_data,
10028 state->max_data_return);
10029 END_PROFILE(Trans2_qfsinfo);
10033 case TRANSACT2_SETFSINFO:
10035 START_PROFILE(Trans2_setfsinfo);
10036 call_trans2setfsinfo(conn, req,
10037 &state->param, state->total_param,
10038 &state->data, state->total_data,
10039 state->max_data_return);
10040 END_PROFILE(Trans2_setfsinfo);
10044 case TRANSACT2_QPATHINFO:
10045 case TRANSACT2_QFILEINFO:
10047 START_PROFILE(Trans2_qpathinfo);
10048 call_trans2qfilepathinfo(conn, req, state->call,
10049 &state->param, state->total_param,
10050 &state->data, state->total_data,
10051 state->max_data_return);
10052 END_PROFILE(Trans2_qpathinfo);
10056 case TRANSACT2_SETPATHINFO:
10057 case TRANSACT2_SETFILEINFO:
10059 START_PROFILE(Trans2_setpathinfo);
10060 call_trans2setfilepathinfo(conn, req, state->call,
10061 &state->param, state->total_param,
10062 &state->data, state->total_data,
10063 state->max_data_return);
10064 END_PROFILE(Trans2_setpathinfo);
10068 case TRANSACT2_FINDNOTIFYFIRST:
10070 START_PROFILE(Trans2_findnotifyfirst);
10071 call_trans2findnotifyfirst(conn, req,
10072 &state->param, state->total_param,
10073 &state->data, state->total_data,
10074 state->max_data_return);
10075 END_PROFILE(Trans2_findnotifyfirst);
10079 case TRANSACT2_FINDNOTIFYNEXT:
10081 START_PROFILE(Trans2_findnotifynext);
10082 call_trans2findnotifynext(conn, req,
10083 &state->param, state->total_param,
10084 &state->data, state->total_data,
10085 state->max_data_return);
10086 END_PROFILE(Trans2_findnotifynext);
10090 case TRANSACT2_MKDIR:
10092 START_PROFILE(Trans2_mkdir);
10093 call_trans2mkdir(conn, req,
10094 &state->param, state->total_param,
10095 &state->data, state->total_data,
10096 state->max_data_return);
10097 END_PROFILE(Trans2_mkdir);
10101 case TRANSACT2_GET_DFS_REFERRAL:
10103 START_PROFILE(Trans2_get_dfs_referral);
10104 call_trans2getdfsreferral(conn, req,
10105 &state->param, state->total_param,
10106 &state->data, state->total_data,
10107 state->max_data_return);
10108 END_PROFILE(Trans2_get_dfs_referral);
10112 case TRANSACT2_IOCTL:
10114 START_PROFILE(Trans2_ioctl);
10115 call_trans2ioctl(conn, req,
10116 &state->param, state->total_param,
10117 &state->data, state->total_data,
10118 state->max_data_return);
10119 END_PROFILE(Trans2_ioctl);
10124 /* Error in request */
10125 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10126 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10130 /****************************************************************************
10131 Reply to a SMBtrans2.
10132 ****************************************************************************/
10134 void reply_trans2(struct smb_request *req)
10136 connection_struct *conn = req->conn;
10137 unsigned int dsoff;
10138 unsigned int dscnt;
10139 unsigned int psoff;
10140 unsigned int pscnt;
10141 unsigned int tran_call;
10142 struct trans_state *state;
10145 START_PROFILE(SMBtrans2);
10147 if (req->wct < 14) {
10148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10149 END_PROFILE(SMBtrans2);
10153 dsoff = SVAL(req->vwv+12, 0);
10154 dscnt = SVAL(req->vwv+11, 0);
10155 psoff = SVAL(req->vwv+10, 0);
10156 pscnt = SVAL(req->vwv+9, 0);
10157 tran_call = SVAL(req->vwv+14, 0);
10159 result = allow_new_trans(conn->pending_trans, req->mid);
10160 if (!NT_STATUS_IS_OK(result)) {
10161 DEBUG(2, ("Got invalid trans2 request: %s\n",
10162 nt_errstr(result)));
10163 reply_nterror(req, result);
10164 END_PROFILE(SMBtrans2);
10168 if (IS_IPC(conn)) {
10169 switch (tran_call) {
10170 /* List the allowed trans2 calls on IPC$ */
10171 case TRANSACT2_OPEN:
10172 case TRANSACT2_GET_DFS_REFERRAL:
10173 case TRANSACT2_QFILEINFO:
10174 case TRANSACT2_QFSINFO:
10175 case TRANSACT2_SETFSINFO:
10178 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10179 END_PROFILE(SMBtrans2);
10184 if ((state = talloc(conn, struct trans_state)) == NULL) {
10185 DEBUG(0, ("talloc failed\n"));
10186 reply_nterror(req, NT_STATUS_NO_MEMORY);
10187 END_PROFILE(SMBtrans2);
10191 state->cmd = SMBtrans2;
10193 state->mid = req->mid;
10194 state->vuid = req->vuid;
10195 state->setup_count = SVAL(req->vwv+13, 0);
10196 state->setup = NULL;
10197 state->total_param = SVAL(req->vwv+0, 0);
10198 state->param = NULL;
10199 state->total_data = SVAL(req->vwv+1, 0);
10200 state->data = NULL;
10201 state->max_param_return = SVAL(req->vwv+2, 0);
10202 state->max_data_return = SVAL(req->vwv+3, 0);
10203 state->max_setup_return = SVAL(req->vwv+4, 0);
10204 state->close_on_completion = BITSETW(req->vwv+5, 0);
10205 state->one_way = BITSETW(req->vwv+5, 1);
10207 state->call = tran_call;
10209 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10210 is so as a sanity check */
10211 if (state->setup_count != 1) {
10213 * Need to have rc=0 for ioctl to get job id for OS/2.
10214 * Network printing will fail if function is not successful.
10215 * Similar function in reply.c will be used if protocol
10216 * is LANMAN1.0 instead of LM1.2X002.
10217 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10218 * outbuf doesn't have to be set(only job id is used).
10220 if ( (state->setup_count == 4)
10221 && (tran_call == TRANSACT2_IOCTL)
10222 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10223 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10224 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10226 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10227 DEBUG(2,("Transaction is %d\n",tran_call));
10228 TALLOC_FREE(state);
10229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10230 END_PROFILE(SMBtrans2);
10235 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10238 if (state->total_data) {
10240 if (trans_oob(state->total_data, 0, dscnt)
10241 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10245 /* Can't use talloc here, the core routines do realloc on the
10246 * params and data. */
10247 state->data = (char *)SMB_MALLOC(state->total_data);
10248 if (state->data == NULL) {
10249 DEBUG(0,("reply_trans2: data malloc fail for %u "
10250 "bytes !\n", (unsigned int)state->total_data));
10251 TALLOC_FREE(state);
10252 reply_nterror(req, NT_STATUS_NO_MEMORY);
10253 END_PROFILE(SMBtrans2);
10257 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10260 if (state->total_param) {
10262 if (trans_oob(state->total_param, 0, pscnt)
10263 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10267 /* Can't use talloc here, the core routines do realloc on the
10268 * params and data. */
10269 state->param = (char *)SMB_MALLOC(state->total_param);
10270 if (state->param == NULL) {
10271 DEBUG(0,("reply_trans: param malloc fail for %u "
10272 "bytes !\n", (unsigned int)state->total_param));
10273 SAFE_FREE(state->data);
10274 TALLOC_FREE(state);
10275 reply_nterror(req, NT_STATUS_NO_MEMORY);
10276 END_PROFILE(SMBtrans2);
10280 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10283 state->received_data = dscnt;
10284 state->received_param = pscnt;
10286 if ((state->received_param == state->total_param) &&
10287 (state->received_data == state->total_data)) {
10289 handle_trans2(conn, req, state);
10291 SAFE_FREE(state->data);
10292 SAFE_FREE(state->param);
10293 TALLOC_FREE(state);
10294 END_PROFILE(SMBtrans2);
10298 DLIST_ADD(conn->pending_trans, state);
10300 /* We need to send an interim response then receive the rest
10301 of the parameter/data bytes */
10302 reply_outbuf(req, 0, 0);
10303 show_msg((char *)req->outbuf);
10304 END_PROFILE(SMBtrans2);
10309 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10310 SAFE_FREE(state->data);
10311 SAFE_FREE(state->param);
10312 TALLOC_FREE(state);
10313 END_PROFILE(SMBtrans2);
10314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10318 /****************************************************************************
10319 Reply to a SMBtranss2
10320 ****************************************************************************/
10322 void reply_transs2(struct smb_request *req)
10324 connection_struct *conn = req->conn;
10325 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10326 struct trans_state *state;
10328 START_PROFILE(SMBtranss2);
10330 show_msg((const char *)req->inbuf);
10332 /* Windows clients expect all replies to
10333 a transact secondary (SMBtranss2 0x33)
10334 to have a command code of transact
10335 (SMBtrans2 0x32). See bug #8989
10336 and also [MS-CIFS] section 2.2.4.47.2
10339 req->cmd = SMBtrans2;
10341 if (req->wct < 8) {
10342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10343 END_PROFILE(SMBtranss2);
10347 for (state = conn->pending_trans; state != NULL;
10348 state = state->next) {
10349 if (state->mid == req->mid) {
10354 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10356 END_PROFILE(SMBtranss2);
10360 /* Revise state->total_param and state->total_data in case they have
10361 changed downwards */
10363 if (SVAL(req->vwv+0, 0) < state->total_param)
10364 state->total_param = SVAL(req->vwv+0, 0);
10365 if (SVAL(req->vwv+1, 0) < state->total_data)
10366 state->total_data = SVAL(req->vwv+1, 0);
10368 pcnt = SVAL(req->vwv+2, 0);
10369 poff = SVAL(req->vwv+3, 0);
10370 pdisp = SVAL(req->vwv+4, 0);
10372 dcnt = SVAL(req->vwv+5, 0);
10373 doff = SVAL(req->vwv+6, 0);
10374 ddisp = SVAL(req->vwv+7, 0);
10376 state->received_param += pcnt;
10377 state->received_data += dcnt;
10379 if ((state->received_data > state->total_data) ||
10380 (state->received_param > state->total_param))
10384 if (trans_oob(state->total_param, pdisp, pcnt)
10385 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10388 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10392 if (trans_oob(state->total_data, ddisp, dcnt)
10393 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10396 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10399 if ((state->received_param < state->total_param) ||
10400 (state->received_data < state->total_data)) {
10401 END_PROFILE(SMBtranss2);
10405 handle_trans2(conn, req, state);
10407 DLIST_REMOVE(conn->pending_trans, state);
10408 SAFE_FREE(state->data);
10409 SAFE_FREE(state->param);
10410 TALLOC_FREE(state);
10412 END_PROFILE(SMBtranss2);
10417 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10418 DLIST_REMOVE(conn->pending_trans, state);
10419 SAFE_FREE(state->data);
10420 SAFE_FREE(state->param);
10421 TALLOC_FREE(state);
10422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10423 END_PROFILE(SMBtranss2);