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"
48 #define DIR_ENTRY_SAFETY_MARGIN 4096
50 static char *store_file_unix_basic(connection_struct *conn,
53 const SMB_STRUCT_STAT *psbuf);
55 static char *store_file_unix_basic_info2(connection_struct *conn,
58 const SMB_STRUCT_STAT *psbuf);
60 /****************************************************************************
61 Check if an open file handle or smb_fname is a symlink.
62 ****************************************************************************/
64 static NTSTATUS refuse_symlink(connection_struct *conn,
65 const files_struct *fsp,
66 const struct smb_filename *smb_fname)
69 const SMB_STRUCT_STAT *pst = NULL;
72 pst = &fsp->fsp_name->st;
77 if (!VALID_STAT(*pst)) {
78 int ret = vfs_stat_smb_basename(conn,
81 if (ret == -1 && errno != ENOENT) {
82 return map_nt_error_from_unix(errno);
83 } else if (ret == -1) {
84 /* it's not a symlink.. */
90 if (S_ISLNK(pst->st_ex_mode)) {
91 return NT_STATUS_ACCESS_DENIED;
96 NTSTATUS check_access_fsp(const struct files_struct *fsp,
99 if (!(fsp->access_mask & access_mask)) {
100 return NT_STATUS_ACCESS_DENIED;
105 #if defined(HAVE_POSIX_ACLS)
106 /****************************************************************************
107 Utility function to open a fsp for a POSIX handle operation.
108 ****************************************************************************/
110 static NTSTATUS get_posix_fsp(connection_struct *conn,
111 struct smb_request *req,
112 const struct smb_filename *smb_fname,
113 uint32_t access_mask,
114 files_struct **ret_fsp)
117 struct smb_filename *smb_fname_tmp = NULL;
118 uint32_t create_disposition = FILE_OPEN;
119 uint32_t share_access = FILE_SHARE_READ|
122 struct smb2_create_blobs *posx = NULL;
125 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
126 * but set reasonable defaults.
128 uint32_t file_attributes = 0664;
129 uint32_t oplock = NO_OPLOCK;
130 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
132 /* File or directory must exist. */
133 if (!VALID_STAT(smb_fname->st)) {
134 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
136 /* Cannot be a symlink. */
137 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
138 return NT_STATUS_ACCESS_DENIED;
140 /* Set options correctly for directory open. */
141 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
143 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
144 * directories, but set reasonable defaults.
146 file_attributes = 0775;
147 create_options = FILE_DIRECTORY_FILE;
150 /* Createfile uses a non-const smb_fname. */
151 smb_fname_tmp = cp_smb_filename(talloc_tos(),
153 if (smb_fname_tmp == NULL) {
154 status = NT_STATUS_NO_MEMORY;
158 status = make_smb2_posix_create_ctx(
159 talloc_tos(), &posx, file_attributes);
160 if (!NT_STATUS_IS_OK(status)) {
161 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
166 status = SMB_VFS_CREATE_FILE(
169 0, /* root_dir_fid */
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 The canonical "check access" based on object handle or path function.
196 ********************************************************************/
198 static NTSTATUS check_access(connection_struct *conn,
200 const struct smb_filename *smb_fname,
201 uint32_t access_mask)
206 status = check_access_fsp(fsp, access_mask);
208 status = smbd_check_access_rights(conn, smb_fname,
215 /********************************************************************
216 Roundup a value to the nearest allocation roundup size boundary.
217 Only do this for Windows clients.
218 ********************************************************************/
220 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
222 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
224 /* Only roundup for Windows clients. */
225 enum remote_arch_types ra_type = get_remote_arch();
226 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
227 val = SMB_ROUNDUP(val,rval);
232 /****************************************************************************
233 Utility functions for dealing with extended attributes.
234 ****************************************************************************/
236 /****************************************************************************
237 Refuse to allow clients to overwrite our private xattrs.
238 ****************************************************************************/
240 bool samba_private_attr_name(const char *unix_ea_name)
242 static const char * const prohibited_ea_names[] = {
243 SAMBA_POSIX_INHERITANCE_EA_NAME,
244 SAMBA_XATTR_DOS_ATTRIB,
252 for (i = 0; prohibited_ea_names[i]; i++) {
253 if (strequal( prohibited_ea_names[i], unix_ea_name))
256 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
257 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
263 /****************************************************************************
264 Get one EA value. Fill in a struct ea_struct.
265 ****************************************************************************/
267 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
268 connection_struct *conn,
270 const struct smb_filename *smb_fname,
272 struct ea_struct *pea)
274 /* Get the value of this xattr. Max size is 64k. */
275 size_t attr_size = 256;
281 val = talloc_realloc(mem_ctx, val, char, attr_size);
283 return NT_STATUS_NO_MEMORY;
286 if (fsp && fsp->fh->fd != -1) {
287 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
289 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
290 ea_name, val, attr_size);
293 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
299 return map_nt_error_from_unix(errno);
302 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
303 dump_data(10, (uint8_t *)val, sizeret);
306 if (strnequal(ea_name, "user.", 5)) {
307 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
309 pea->name = talloc_strdup(mem_ctx, ea_name);
311 if (pea->name == NULL) {
313 return NT_STATUS_NO_MEMORY;
315 pea->value.data = (unsigned char *)val;
316 pea->value.length = (size_t)sizeret;
320 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
321 connection_struct *conn,
323 const struct smb_filename *smb_fname,
328 /* Get a list of all xattrs. Max namesize is 64k. */
329 size_t ea_namelist_size = 1024;
330 char *ea_namelist = smallbuf;
331 char *to_free = NULL;
336 ssize_t sizeret = -1;
344 status = refuse_symlink(conn, fsp, smb_fname);
345 if (!NT_STATUS_IS_OK(status)) {
347 * Just return no EA's on a symlink.
352 if (fsp && fsp->fh->fd != -1) {
353 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
356 sizeret = SMB_VFS_LISTXATTR(conn,
362 if ((sizeret == -1) && (errno == ERANGE)) {
363 ea_namelist_size = 65536;
364 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
365 if (ea_namelist == NULL) {
366 return NT_STATUS_NO_MEMORY;
368 to_free = ea_namelist;
370 if (fsp && fsp->fh->fd != -1) {
371 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
374 sizeret = SMB_VFS_LISTXATTR(conn,
382 status = map_nt_error_from_unix(errno);
383 TALLOC_FREE(to_free);
387 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
390 TALLOC_FREE(to_free);
395 * Ensure the result is 0-terminated
398 if (ea_namelist[sizeret-1] != '\0') {
399 TALLOC_FREE(to_free);
400 return NT_STATUS_INTERNAL_ERROR;
408 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
412 *pnum_names = num_names;
414 if (pnames == NULL) {
415 TALLOC_FREE(to_free);
419 names = talloc_array(mem_ctx, char *, num_names);
421 DEBUG(0, ("talloc failed\n"));
422 TALLOC_FREE(to_free);
423 return NT_STATUS_NO_MEMORY;
426 if (ea_namelist == smallbuf) {
427 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
428 if (ea_namelist == NULL) {
430 return NT_STATUS_NO_MEMORY;
433 talloc_steal(names, ea_namelist);
435 ea_namelist = talloc_realloc(names, ea_namelist, char,
437 if (ea_namelist == NULL) {
439 return NT_STATUS_NO_MEMORY;
445 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
446 names[num_names++] = p;
454 /****************************************************************************
455 Return a linked list of the total EA's. Plus the total size
456 ****************************************************************************/
458 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
459 connection_struct *conn,
461 const struct smb_filename *smb_fname,
462 size_t *pea_total_len,
463 struct ea_list **ea_list)
465 /* Get a list of all xattrs. Max namesize is 64k. */
468 struct ea_list *ea_list_head = NULL;
469 bool posix_pathnames = false;
475 if (!lp_ea_support(SNUM(conn))) {
481 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
483 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
486 status = get_ea_names_from_file(talloc_tos(),
493 if (!NT_STATUS_IS_OK(status)) {
497 if (num_names == 0) {
501 for (i=0; i<num_names; i++) {
502 struct ea_list *listp;
505 if (strnequal(names[i], "system.", 7)
506 || samba_private_attr_name(names[i]))
510 * Filter out any underlying POSIX EA names
511 * that a Windows client can't handle.
513 if (!posix_pathnames &&
514 is_invalid_windows_ea_name(names[i])) {
518 listp = talloc(mem_ctx, struct ea_list);
520 return NT_STATUS_NO_MEMORY;
523 status = get_ea_value(listp,
530 if (!NT_STATUS_IS_OK(status)) {
535 if (listp->ea.value.length == 0) {
537 * We can never return a zero length EA.
538 * Windows reports the EA's as corrupted.
544 push_ascii_fstring(dos_ea_name, listp->ea.name);
547 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
549 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
550 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
551 (unsigned int)listp->ea.value.length));
553 DLIST_ADD_END(ea_list_head, listp);
557 /* Add on 4 for total length. */
558 if (*pea_total_len) {
562 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
563 (unsigned int)*pea_total_len));
565 *ea_list = ea_list_head;
569 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
570 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
575 if (!lp_ea_support(SNUM(conn))) {
579 if (is_ntfs_stream_smb_fname(smb_fname)) {
580 return NT_STATUS_INVALID_PARAMETER;
583 return get_ea_list_from_file_path(mem_ctx,
591 /****************************************************************************
592 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
594 ****************************************************************************/
596 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
597 connection_struct *conn, struct ea_list *ea_list)
599 unsigned int ret_data_size = 4;
602 SMB_ASSERT(total_data_size >= 4);
604 if (!lp_ea_support(SNUM(conn))) {
609 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
612 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
613 dos_namelen = strlen(dos_ea_name);
614 if (dos_namelen > 255 || dos_namelen == 0) {
617 if (ea_list->ea.value.length > 65535) {
620 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
624 /* We know we have room. */
625 SCVAL(p,0,ea_list->ea.flags);
626 SCVAL(p,1,dos_namelen);
627 SSVAL(p,2,ea_list->ea.value.length);
628 strlcpy(p+4, dos_ea_name, dos_namelen+1);
629 if (ea_list->ea.value.length > 0) {
630 memcpy(p + 4 + dos_namelen + 1,
631 ea_list->ea.value.data,
632 ea_list->ea.value.length);
635 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
636 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
639 ret_data_size = PTR_DIFF(p, pdata);
640 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
641 SIVAL(pdata,0,ret_data_size);
642 return ret_data_size;
645 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
647 unsigned int total_data_size,
648 unsigned int *ret_data_size,
649 connection_struct *conn,
650 struct ea_list *ea_list)
652 uint8_t *p = (uint8_t *)pdata;
653 uint8_t *last_start = NULL;
654 bool do_store_data = (pdata != NULL);
658 if (!lp_ea_support(SNUM(conn))) {
659 return NT_STATUS_NO_EAS_ON_FILE;
662 for (; ea_list; ea_list = ea_list->next) {
668 if (last_start != NULL && do_store_data) {
669 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
673 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
674 dos_namelen = strlen(dos_ea_name);
675 if (dos_namelen > 255 || dos_namelen == 0) {
676 return NT_STATUS_INTERNAL_ERROR;
678 if (ea_list->ea.value.length > 65535) {
679 return NT_STATUS_INTERNAL_ERROR;
682 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
685 pad = (4 - (this_size % 4)) % 4;
690 if (this_size > total_data_size) {
691 return NT_STATUS_INFO_LENGTH_MISMATCH;
694 /* We know we have room. */
695 SIVAL(p, 0x00, 0); /* next offset */
696 SCVAL(p, 0x04, ea_list->ea.flags);
697 SCVAL(p, 0x05, dos_namelen);
698 SSVAL(p, 0x06, ea_list->ea.value.length);
699 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
700 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
702 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
706 total_data_size -= this_size;
712 *ret_data_size = PTR_DIFF(p, pdata);
713 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
717 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
719 size_t total_ea_len = 0;
721 struct ea_list *ea_list = NULL;
723 if (!lp_ea_support(SNUM(conn))) {
726 mem_ctx = talloc_stackframe();
728 /* If this is a stream fsp, then we need to instead find the
729 * estimated ea len from the main file, not the stream
730 * (streams cannot have EAs), but the estimate isn't just 0 in
732 if (is_ntfs_stream_smb_fname(smb_fname)) {
735 (void)get_ea_list_from_file_path(mem_ctx,
741 if(conn->sconn->using_smb2) {
743 unsigned int ret_data_size;
745 * We're going to be using fill_ea_chained_buffer() to
746 * marshall EA's - this size is significantly larger
747 * than the SMB1 buffer. Re-calculate the size without
750 status = fill_ea_chained_buffer(mem_ctx,
756 if (!NT_STATUS_IS_OK(status)) {
759 total_ea_len = ret_data_size;
761 TALLOC_FREE(mem_ctx);
765 /****************************************************************************
766 Ensure the EA name is case insensitive by matching any existing EA name.
767 ****************************************************************************/
769 static void canonicalize_ea_name(connection_struct *conn,
771 const struct smb_filename *smb_fname,
772 fstring unix_ea_name)
775 TALLOC_CTX *mem_ctx = talloc_tos();
776 struct ea_list *ea_list;
777 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
783 if (!NT_STATUS_IS_OK(status)) {
787 for (; ea_list; ea_list = ea_list->next) {
788 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
789 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
790 &unix_ea_name[5], ea_list->ea.name));
791 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
797 /****************************************************************************
798 Set or delete an extended attribute.
799 ****************************************************************************/
801 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
802 const struct smb_filename *smb_fname, struct ea_list *ea_list)
805 bool posix_pathnames = false;
807 if (!lp_ea_support(SNUM(conn))) {
808 return NT_STATUS_EAS_NOT_SUPPORTED;
813 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
815 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
818 status = refuse_symlink(conn, fsp, smb_fname);
819 if (!NT_STATUS_IS_OK(status)) {
823 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
824 if (!NT_STATUS_IS_OK(status)) {
828 /* Setting EAs on streams isn't supported. */
829 if (is_ntfs_stream_smb_fname(smb_fname)) {
830 return NT_STATUS_INVALID_PARAMETER;
834 * Filter out invalid Windows EA names - before
835 * we set *any* of them.
838 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
839 return STATUS_INVALID_EA_NAME;
842 for (;ea_list; ea_list = ea_list->next) {
844 fstring unix_ea_name;
846 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
847 fstrcat(unix_ea_name, ea_list->ea.name);
849 canonicalize_ea_name(conn,
854 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
856 if (samba_private_attr_name(unix_ea_name)) {
857 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
858 return NT_STATUS_ACCESS_DENIED;
861 if (ea_list->ea.value.length == 0) {
862 /* Remove the attribute. */
863 if (fsp && (fsp->fh->fd != -1)) {
864 DEBUG(10,("set_ea: deleting ea name %s on "
865 "file %s by file descriptor.\n",
866 unix_ea_name, fsp_str_dbg(fsp)));
867 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
869 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
870 unix_ea_name, smb_fname->base_name));
871 ret = SMB_VFS_REMOVEXATTR(conn,
876 /* Removing a non existent attribute always succeeds. */
877 if (ret == -1 && errno == ENOATTR) {
878 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
884 if (fsp && (fsp->fh->fd != -1)) {
885 DEBUG(10,("set_ea: setting ea name %s on file "
886 "%s by file descriptor.\n",
887 unix_ea_name, fsp_str_dbg(fsp)));
888 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
889 ea_list->ea.value.data, ea_list->ea.value.length, 0);
891 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
892 unix_ea_name, smb_fname->base_name));
893 ret = SMB_VFS_SETXATTR(conn,
896 ea_list->ea.value.data,
897 ea_list->ea.value.length,
904 if (errno == ENOTSUP) {
905 return NT_STATUS_EAS_NOT_SUPPORTED;
908 return map_nt_error_from_unix(errno);
914 /****************************************************************************
915 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
916 ****************************************************************************/
918 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
920 struct ea_list *ea_list_head = NULL;
921 size_t converted_size, offset = 0;
923 while (offset + 2 < data_size) {
924 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
925 unsigned int namelen = CVAL(pdata,offset);
927 offset++; /* Go past the namelen byte. */
929 /* integer wrap paranioa. */
930 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
931 (offset > data_size) || (namelen > data_size) ||
932 (offset + namelen >= data_size)) {
935 /* Ensure the name is null terminated. */
936 if (pdata[offset + namelen] != '\0') {
939 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
941 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
942 "failed: %s", strerror(errno)));
948 offset += (namelen + 1); /* Go past the name + terminating zero. */
949 DLIST_ADD_END(ea_list_head, eal);
950 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
956 /****************************************************************************
957 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
958 ****************************************************************************/
960 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
962 struct ea_list *ea_list_head = NULL;
964 size_t bytes_used = 0;
966 while (offset < data_size) {
967 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
973 DLIST_ADD_END(ea_list_head, eal);
974 offset += bytes_used;
980 /****************************************************************************
981 Count the total EA size needed.
982 ****************************************************************************/
984 static size_t ea_list_size(struct ea_list *ealist)
987 struct ea_list *listp;
990 for (listp = ealist; listp; listp = listp->next) {
991 push_ascii_fstring(dos_ea_name, listp->ea.name);
992 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
994 /* Add on 4 for total length. */
1002 /****************************************************************************
1003 Return a union of EA's from a file list and a list of names.
1004 The TALLOC context for the two lists *MUST* be identical as we steal
1005 memory from one list to add to another. JRA.
1006 ****************************************************************************/
1008 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1010 struct ea_list *nlistp, *flistp;
1012 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1013 for (flistp = file_list; flistp; flistp = flistp->next) {
1014 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1020 /* Copy the data from this entry. */
1021 nlistp->ea.flags = flistp->ea.flags;
1022 nlistp->ea.value = flistp->ea.value;
1025 nlistp->ea.flags = 0;
1026 ZERO_STRUCT(nlistp->ea.value);
1030 *total_ea_len = ea_list_size(name_list);
1034 /****************************************************************************
1035 Send the required number of replies back.
1036 We assume all fields other than the data fields are
1037 set correctly for the type of call.
1038 HACK ! Always assumes smb_setup field is zero.
1039 ****************************************************************************/
1041 void send_trans2_replies(connection_struct *conn,
1042 struct smb_request *req,
1050 /* As we are using a protocol > LANMAN1 then the max_send
1051 variable must have been set in the sessetupX call.
1052 This takes precedence over the max_xmit field in the
1053 global struct. These different max_xmit variables should
1054 be merged as this is now too confusing */
1056 int data_to_send = datasize;
1057 int params_to_send = paramsize;
1059 const char *pp = params;
1060 const char *pd = pdata;
1061 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1062 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1063 int data_alignment_offset = 0;
1064 bool overflow = False;
1065 struct smbXsrv_connection *xconn = req->xconn;
1066 int max_send = xconn->smb1.sessions.max_send;
1068 /* Modify the data_to_send and datasize and set the error if
1069 we're trying to send more than max_data_bytes. We still send
1070 the part of the packet(s) that fit. Strange, but needed
1073 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1074 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1075 max_data_bytes, datasize ));
1076 datasize = data_to_send = max_data_bytes;
1080 /* If there genuinely are no parameters or data to send just send the empty packet */
1082 if(params_to_send == 0 && data_to_send == 0) {
1083 reply_outbuf(req, 10, 0);
1084 if (NT_STATUS_V(status)) {
1087 ntstatus_to_dos(status, &eclass, &ecode);
1088 error_packet_set((char *)req->outbuf,
1089 eclass, ecode, status,
1092 show_msg((char *)req->outbuf);
1093 if (!srv_send_smb(xconn,
1094 (char *)req->outbuf,
1095 true, req->seqnum+1,
1096 IS_CONN_ENCRYPTED(conn),
1098 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1100 TALLOC_FREE(req->outbuf);
1104 /* When sending params and data ensure that both are nicely aligned */
1105 /* Only do this alignment when there is also data to send - else
1106 can cause NT redirector problems. */
1108 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1109 data_alignment_offset = 4 - (params_to_send % 4);
1111 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1112 /* The alignment_offset is to align the param bytes on an even byte
1113 boundary. NT 4.0 Beta needs this to work correctly. */
1115 useable_space = max_send - (smb_size
1118 + data_alignment_offset);
1120 if (useable_space < 0) {
1121 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1122 "= %d!!!", useable_space));
1123 exit_server_cleanly("send_trans2_replies: Not enough space");
1126 while (params_to_send || data_to_send) {
1127 /* Calculate whether we will totally or partially fill this packet */
1129 total_sent_thistime = params_to_send + data_to_send;
1131 /* We can never send more than useable_space */
1133 * Note that 'useable_space' does not include the alignment offsets,
1134 * but we must include the alignment offsets in the calculation of
1135 * the length of the data we send over the wire, as the alignment offsets
1136 * are sent here. Fix from Marc_Jacobsen@hp.com.
1139 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1141 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1142 + data_alignment_offset);
1144 /* Set total params and data to be sent */
1145 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1146 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1148 /* Calculate how many parameters and data we can fit into
1149 * this packet. Parameters get precedence
1152 params_sent_thistime = MIN(params_to_send,useable_space);
1153 data_sent_thistime = useable_space - params_sent_thistime;
1154 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1156 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1158 /* smb_proff is the offset from the start of the SMB header to the
1159 parameter bytes, however the first 4 bytes of outbuf are
1160 the Netbios over TCP header. Thus use smb_base() to subtract
1161 them from the calculation */
1163 SSVAL(req->outbuf,smb_proff,
1164 ((smb_buf(req->outbuf)+alignment_offset)
1165 - smb_base(req->outbuf)));
1167 if(params_sent_thistime == 0)
1168 SSVAL(req->outbuf,smb_prdisp,0);
1170 /* Absolute displacement of param bytes sent in this packet */
1171 SSVAL(req->outbuf,smb_prdisp,pp - params);
1173 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1174 if(data_sent_thistime == 0) {
1175 SSVAL(req->outbuf,smb_droff,0);
1176 SSVAL(req->outbuf,smb_drdisp, 0);
1178 /* The offset of the data bytes is the offset of the
1179 parameter bytes plus the number of parameters being sent this time */
1180 SSVAL(req->outbuf, smb_droff,
1181 ((smb_buf(req->outbuf)+alignment_offset)
1182 - smb_base(req->outbuf))
1183 + params_sent_thistime + data_alignment_offset);
1184 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1187 /* Initialize the padding for alignment */
1189 if (alignment_offset != 0) {
1190 memset(smb_buf(req->outbuf), 0, alignment_offset);
1193 /* Copy the param bytes into the packet */
1195 if(params_sent_thistime) {
1196 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1197 params_sent_thistime);
1200 /* Copy in the data bytes */
1201 if(data_sent_thistime) {
1202 if (data_alignment_offset != 0) {
1203 memset((smb_buf(req->outbuf)+alignment_offset+
1204 params_sent_thistime), 0,
1205 data_alignment_offset);
1207 memcpy(smb_buf(req->outbuf)+alignment_offset
1208 +params_sent_thistime+data_alignment_offset,
1209 pd,data_sent_thistime);
1212 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1213 params_sent_thistime, data_sent_thistime, useable_space));
1214 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1215 params_to_send, data_to_send, paramsize, datasize));
1218 error_packet_set((char *)req->outbuf,
1219 ERRDOS,ERRbufferoverflow,
1220 STATUS_BUFFER_OVERFLOW,
1222 } else if (NT_STATUS_V(status)) {
1225 ntstatus_to_dos(status, &eclass, &ecode);
1226 error_packet_set((char *)req->outbuf,
1227 eclass, ecode, status,
1231 /* Send the packet */
1232 show_msg((char *)req->outbuf);
1233 if (!srv_send_smb(xconn,
1234 (char *)req->outbuf,
1235 true, req->seqnum+1,
1236 IS_CONN_ENCRYPTED(conn),
1238 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1240 TALLOC_FREE(req->outbuf);
1242 pp += params_sent_thistime;
1243 pd += data_sent_thistime;
1245 params_to_send -= params_sent_thistime;
1246 data_to_send -= data_sent_thistime;
1249 if(params_to_send < 0 || data_to_send < 0) {
1250 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1251 params_to_send, data_to_send));
1259 /****************************************************************************
1260 Reply to a TRANSACT2_OPEN.
1261 ****************************************************************************/
1263 static void call_trans2open(connection_struct *conn,
1264 struct smb_request *req,
1265 char **pparams, int total_params,
1266 char **ppdata, int total_data,
1267 unsigned int max_data_bytes)
1269 struct smb_filename *smb_fname = NULL;
1270 char *params = *pparams;
1271 char *pdata = *ppdata;
1274 bool oplock_request;
1276 bool return_additional_info;
1285 int fattr=0,mtime=0;
1286 SMB_INO_T inode = 0;
1289 struct ea_list *ea_list = NULL;
1292 uint32_t access_mask;
1293 uint32_t share_mode;
1294 uint32_t create_disposition;
1295 uint32_t create_options = 0;
1296 uint32_t private_flags = 0;
1297 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1298 TALLOC_CTX *ctx = talloc_tos();
1301 * Ensure we have enough parameters to perform the operation.
1304 if (total_params < 29) {
1305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1309 flags = SVAL(params, 0);
1310 deny_mode = SVAL(params, 2);
1311 open_attr = SVAL(params,6);
1312 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1313 if (oplock_request) {
1314 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1318 return_additional_info = BITSETW(params,0);
1319 open_sattr = SVAL(params, 4);
1320 open_time = make_unix_date3(params+8);
1322 open_ofun = SVAL(params,12);
1323 open_size = IVAL(params,14);
1324 pname = ¶ms[28];
1327 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1331 if (req->posix_pathnames) {
1332 srvstr_get_path_posix(ctx,
1341 srvstr_get_path(ctx,
1350 if (!NT_STATUS_IS_OK(status)) {
1351 reply_nterror(req, status);
1355 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1356 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1357 (unsigned int)open_ofun, open_size));
1359 status = filename_convert(ctx,
1366 if (!NT_STATUS_IS_OK(status)) {
1367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1368 reply_botherror(req,
1369 NT_STATUS_PATH_NOT_COVERED,
1370 ERRSRV, ERRbadpath);
1373 reply_nterror(req, status);
1377 if (open_ofun == 0) {
1378 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1382 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1384 &access_mask, &share_mode,
1385 &create_disposition,
1388 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1392 /* Any data in this call is an EA list. */
1393 if (total_data && (total_data != 4)) {
1394 if (total_data < 10) {
1395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 if (IVAL(pdata,0) > total_data) {
1400 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1401 IVAL(pdata,0), (unsigned int)total_data));
1402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1406 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1413 if (!lp_ea_support(SNUM(conn))) {
1414 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1418 if (!req->posix_pathnames &&
1419 ea_list_has_invalid_name(ea_list)) {
1421 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1422 if(*pparams == NULL ) {
1423 reply_nterror(req, NT_STATUS_NO_MEMORY);
1427 memset(params, '\0', param_len);
1428 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1429 params, param_len, NULL, 0, max_data_bytes);
1434 status = SMB_VFS_CREATE_FILE(
1437 0, /* root_dir_fid */
1438 smb_fname, /* fname */
1439 access_mask, /* access_mask */
1440 share_mode, /* share_access */
1441 create_disposition, /* create_disposition*/
1442 create_options, /* create_options */
1443 open_attr, /* file_attributes */
1444 oplock_request, /* oplock_request */
1446 open_size, /* allocation_size */
1449 ea_list, /* ea_list */
1451 &smb_action, /* psbuf */
1452 NULL, NULL); /* create context */
1454 if (!NT_STATUS_IS_OK(status)) {
1455 if (open_was_deferred(req->xconn, req->mid)) {
1456 /* We have re-scheduled this call. */
1460 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1461 reply_openerror(req, status);
1465 fsp = fcb_or_dos_open(
1472 bool ok = defer_smb1_sharing_violation(req);
1476 reply_openerror(req, status);
1480 smb_action = FILE_WAS_OPENED;
1483 size = get_file_size_stat(&smb_fname->st);
1484 fattr = dos_mode(conn, smb_fname);
1485 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1486 inode = smb_fname->st.st_ex_ino;
1487 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1488 close_file(req, fsp, ERROR_CLOSE);
1489 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1493 /* Realloc the size of parameters and data we will return */
1494 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1495 if(*pparams == NULL ) {
1496 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 SSVAL(params,0,fsp->fnum);
1502 SSVAL(params,2,fattr);
1503 srv_put_dos_date2(params,4, mtime);
1504 SIVAL(params,8, (uint32_t)size);
1505 SSVAL(params,12,deny_mode);
1506 SSVAL(params,14,0); /* open_type - file or directory. */
1507 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1509 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1510 smb_action |= EXTENDED_OPLOCK_GRANTED;
1513 SSVAL(params,18,smb_action);
1516 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1518 SIVAL(params,20,inode);
1519 SSVAL(params,24,0); /* Padding. */
1521 uint32_t ea_size = estimate_ea_size(conn, fsp,
1523 SIVAL(params, 26, ea_size);
1525 SIVAL(params, 26, 0);
1528 /* Send the required number of replies */
1529 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1531 TALLOC_FREE(smb_fname);
1534 /*********************************************************
1535 Routine to check if a given string matches exactly.
1536 as a special case a mask of "." does NOT match. That
1537 is required for correct wildcard semantics
1538 Case can be significant or not.
1539 **********************************************************/
1541 static bool exact_match(bool has_wild,
1542 bool case_sensitive,
1546 if (mask[0] == '.' && mask[1] == 0) {
1554 if (case_sensitive) {
1555 return strcmp(str,mask)==0;
1557 return strcasecmp_m(str,mask) == 0;
1561 /****************************************************************************
1562 Return the filetype for UNIX extensions.
1563 ****************************************************************************/
1565 static uint32_t unix_filetype(mode_t mode)
1568 return UNIX_TYPE_FILE;
1569 else if(S_ISDIR(mode))
1570 return UNIX_TYPE_DIR;
1572 else if(S_ISLNK(mode))
1573 return UNIX_TYPE_SYMLINK;
1576 else if(S_ISCHR(mode))
1577 return UNIX_TYPE_CHARDEV;
1580 else if(S_ISBLK(mode))
1581 return UNIX_TYPE_BLKDEV;
1584 else if(S_ISFIFO(mode))
1585 return UNIX_TYPE_FIFO;
1588 else if(S_ISSOCK(mode))
1589 return UNIX_TYPE_SOCKET;
1592 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1593 return UNIX_TYPE_UNKNOWN;
1596 /****************************************************************************
1597 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1598 ****************************************************************************/
1600 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1601 const SMB_STRUCT_STAT *psbuf,
1603 enum perm_type ptype,
1608 if (perms == SMB_MODE_NO_CHANGE) {
1609 if (!VALID_STAT(*psbuf)) {
1610 return NT_STATUS_INVALID_PARAMETER;
1612 *ret_perms = psbuf->st_ex_mode;
1613 return NT_STATUS_OK;
1617 ret = wire_perms_to_unix(perms);
1619 if (ptype == PERM_NEW_FILE) {
1621 * "create mask"/"force create mode" are
1622 * only applied to new files, not existing ones.
1624 ret &= lp_create_mask(SNUM(conn));
1625 /* Add in force bits */
1626 ret |= lp_force_create_mode(SNUM(conn));
1627 } else if (ptype == PERM_NEW_DIR) {
1629 * "directory mask"/"force directory mode" are
1630 * only applied to new directories, not existing ones.
1632 ret &= lp_directory_mask(SNUM(conn));
1633 /* Add in force bits */
1634 ret |= lp_force_directory_mode(SNUM(conn));
1638 return NT_STATUS_OK;
1641 /****************************************************************************
1642 Needed to show the msdfs symlinks as directories. Modifies psbuf
1643 to be a directory if it's a msdfs link.
1644 ****************************************************************************/
1646 static bool check_msdfs_link(connection_struct *conn,
1647 struct smb_filename *smb_fname)
1649 int saved_errno = errno;
1650 if(lp_host_msdfs() &&
1651 lp_msdfs_root(SNUM(conn)) &&
1652 is_msdfs_link(conn, smb_fname)) {
1654 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1656 smb_fname->base_name));
1657 smb_fname->st.st_ex_mode =
1658 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1659 errno = saved_errno;
1662 errno = saved_errno;
1667 /****************************************************************************
1668 Get a level dependent lanman2 dir entry.
1669 ****************************************************************************/
1671 struct smbd_dirptr_lanman2_state {
1672 connection_struct *conn;
1673 uint32_t info_level;
1674 bool check_mangled_names;
1676 bool got_exact_match;
1679 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1685 struct smbd_dirptr_lanman2_state *state =
1686 (struct smbd_dirptr_lanman2_state *)private_data;
1688 char mangled_name[13]; /* mangled 8.3 name. */
1692 /* Mangle fname if it's an illegal name. */
1693 if (mangle_must_mangle(dname, state->conn->params)) {
1695 * Slow path - ensure we can push the original name as UCS2. If
1696 * not, then just don't return this name.
1700 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1701 uint8_t *tmp = talloc_array(talloc_tos(),
1705 status = srvstr_push(NULL,
1706 FLAGS2_UNICODE_STRINGS,
1715 if (!NT_STATUS_IS_OK(status)) {
1719 ok = name_to_8_3(dname, mangled_name,
1720 true, state->conn->params);
1724 fname = mangled_name;
1729 got_match = exact_match(state->has_wild,
1730 state->conn->case_sensitive,
1732 state->got_exact_match = got_match;
1734 got_match = mask_match(fname, mask,
1735 state->conn->case_sensitive);
1738 if(!got_match && state->check_mangled_names &&
1739 !mangle_is_8_3(fname, false, state->conn->params)) {
1741 * It turns out that NT matches wildcards against
1742 * both long *and* short names. This may explain some
1743 * of the wildcard wierdness from old DOS clients
1744 * that some people have been seeing.... JRA.
1746 /* Force the mangling into 8.3. */
1747 ok = name_to_8_3(fname, mangled_name,
1748 false, state->conn->params);
1753 got_match = exact_match(state->has_wild,
1754 state->conn->case_sensitive,
1755 mangled_name, mask);
1756 state->got_exact_match = got_match;
1758 got_match = mask_match(mangled_name, mask,
1759 state->conn->case_sensitive);
1767 *_fname = talloc_strdup(ctx, fname);
1768 if (*_fname == NULL) {
1775 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1777 struct smb_filename *smb_fname,
1781 struct smbd_dirptr_lanman2_state *state =
1782 (struct smbd_dirptr_lanman2_state *)private_data;
1783 bool ms_dfs_link = false;
1786 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1787 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1788 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1789 "Couldn't lstat [%s] (%s)\n",
1790 smb_fname_str_dbg(smb_fname),
1794 } else if (!VALID_STAT(smb_fname->st) &&
1795 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1796 /* Needed to show the msdfs symlinks as
1799 ms_dfs_link = check_msdfs_link(state->conn,
1802 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1803 "Couldn't stat [%s] (%s)\n",
1804 smb_fname_str_dbg(smb_fname),
1811 mode = dos_mode_msdfs(state->conn, smb_fname);
1812 } else if (get_dosmode) {
1813 mode = dos_mode(state->conn, smb_fname);
1820 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1821 connection_struct *conn,
1823 uint32_t info_level,
1824 struct ea_list *name_list,
1825 bool check_mangled_names,
1826 bool requires_resume_key,
1829 const struct smb_filename *smb_fname,
1830 int space_remaining,
1836 uint64_t *last_entry_off)
1838 char *p, *q, *pdata = *ppdata;
1840 uint64_t file_size = 0;
1841 uint64_t allocation_size = 0;
1842 uint64_t file_id = 0;
1844 struct timespec mdate_ts = {0};
1845 struct timespec adate_ts = {0};
1846 struct timespec cdate_ts = {0};
1847 struct timespec create_date_ts = {0};
1848 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1850 char *last_entry_ptr;
1855 struct readdir_attr_data *readdir_attr_data = NULL;
1857 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1858 file_size = get_file_size_stat(&smb_fname->st);
1860 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1862 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1869 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1871 mdate_ts = smb_fname->st.st_ex_mtime;
1872 adate_ts = smb_fname->st.st_ex_atime;
1873 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1874 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1876 if (lp_dos_filetime_resolution(SNUM(conn))) {
1877 dos_filetime_timespec(&create_date_ts);
1878 dos_filetime_timespec(&mdate_ts);
1879 dos_filetime_timespec(&adate_ts);
1880 dos_filetime_timespec(&cdate_ts);
1883 create_date = convert_timespec_to_time_t(create_date_ts);
1884 mdate = convert_timespec_to_time_t(mdate_ts);
1885 adate = convert_timespec_to_time_t(adate_ts);
1887 /* align the record */
1888 SMB_ASSERT(align >= 1);
1890 off = (int)PTR_DIFF(pdata, base_data);
1891 pad = (off + (align-1)) & ~(align-1);
1894 if (pad && pad > space_remaining) {
1895 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1896 "for padding (wanted %u, had %d)\n",
1899 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1903 /* initialize padding to 0 */
1905 memset(pdata, 0, pad);
1907 space_remaining -= pad;
1909 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1919 switch (info_level) {
1920 case SMB_FIND_INFO_STANDARD:
1921 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1922 if(requires_resume_key) {
1926 srv_put_dos_date2(p,0,create_date);
1927 srv_put_dos_date2(p,4,adate);
1928 srv_put_dos_date2(p,8,mdate);
1929 SIVAL(p,12,(uint32_t)file_size);
1930 SIVAL(p,16,(uint32_t)allocation_size);
1934 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1935 p += ucs2_align(base_data, p, 0);
1937 status = srvstr_push(base_data, flags2, p,
1938 fname, PTR_DIFF(end_data, p),
1939 STR_TERMINATE, &len);
1940 if (!NT_STATUS_IS_OK(status)) {
1943 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1945 SCVAL(nameptr, -1, len - 2);
1947 SCVAL(nameptr, -1, 0);
1951 SCVAL(nameptr, -1, len - 1);
1953 SCVAL(nameptr, -1, 0);
1959 case SMB_FIND_EA_SIZE:
1960 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1961 if (requires_resume_key) {
1965 srv_put_dos_date2(p,0,create_date);
1966 srv_put_dos_date2(p,4,adate);
1967 srv_put_dos_date2(p,8,mdate);
1968 SIVAL(p,12,(uint32_t)file_size);
1969 SIVAL(p,16,(uint32_t)allocation_size);
1972 unsigned int ea_size = estimate_ea_size(conn, NULL,
1974 SIVAL(p,22,ea_size); /* Extended attributes */
1978 status = srvstr_push(base_data, flags2,
1979 p, fname, PTR_DIFF(end_data, p),
1980 STR_TERMINATE | STR_NOALIGN, &len);
1981 if (!NT_STATUS_IS_OK(status)) {
1984 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1997 SCVAL(nameptr,0,len);
1999 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2002 case SMB_FIND_EA_LIST:
2004 struct ea_list *file_list = NULL;
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2009 return NT_STATUS_INVALID_PARAMETER;
2011 if (requires_resume_key) {
2015 srv_put_dos_date2(p,0,create_date);
2016 srv_put_dos_date2(p,4,adate);
2017 srv_put_dos_date2(p,8,mdate);
2018 SIVAL(p,12,(uint32_t)file_size);
2019 SIVAL(p,16,(uint32_t)allocation_size);
2021 p += 22; /* p now points to the EA area. */
2023 status = get_ea_list_from_file(ctx, conn, NULL,
2025 &ea_len, &file_list);
2026 if (!NT_STATUS_IS_OK(status)) {
2029 name_list = ea_list_union(name_list, file_list, &ea_len);
2031 /* We need to determine if this entry will fit in the space available. */
2032 /* Max string size is 255 bytes. */
2033 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2034 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2035 "(wanted %u, had %d)\n",
2036 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2038 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2041 /* Push the ea_data followed by the name. */
2042 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2044 status = srvstr_push(base_data, flags2,
2045 p + 1, fname, PTR_DIFF(end_data, p+1),
2046 STR_TERMINATE | STR_NOALIGN, &len);
2047 if (!NT_STATUS_IS_OK(status)) {
2050 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2063 SCVAL(nameptr,0,len);
2065 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2069 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2070 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2071 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2073 SIVAL(p,0,reskey); p += 4;
2074 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2075 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2076 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2077 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2078 SOFF_T(p,0,file_size); p += 8;
2079 SOFF_T(p,0,allocation_size); p += 8;
2080 SIVAL(p,0,mode); p += 4;
2081 q = p; p += 4; /* q is placeholder for name length. */
2082 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2083 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2085 unsigned int ea_size = estimate_ea_size(conn, NULL,
2087 SIVAL(p,0,ea_size); /* Extended attributes */
2090 /* Clear the short name buffer. This is
2091 * IMPORTANT as not doing so will trigger
2092 * a Win2k client bug. JRA.
2094 if (!was_8_3 && check_mangled_names) {
2095 char mangled_name[13]; /* mangled 8.3 name. */
2096 if (!name_to_8_3(fname,mangled_name,True,
2098 /* Error - mangle failed ! */
2099 memset(mangled_name,'\0',12);
2101 mangled_name[12] = 0;
2102 status = srvstr_push(base_data, flags2,
2103 p+2, mangled_name, 24,
2104 STR_UPPER|STR_UNICODE, &len);
2105 if (!NT_STATUS_IS_OK(status)) {
2109 memset(p + 2 + len,'\0',24 - len);
2116 status = srvstr_push(base_data, flags2, p,
2117 fname, PTR_DIFF(end_data, p),
2118 STR_TERMINATE_ASCII, &len);
2119 if (!NT_STATUS_IS_OK(status)) {
2125 len = PTR_DIFF(p, pdata);
2126 pad = (len + (align-1)) & ~(align-1);
2128 * offset to the next entry, the caller
2129 * will overwrite it for the last entry
2130 * that's why we always include the padding
2134 * set padding to zero
2137 memset(p, 0, pad - len);
2144 case SMB_FIND_FILE_DIRECTORY_INFO:
2145 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2147 SIVAL(p,0,reskey); p += 4;
2148 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2149 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2150 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2151 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2152 SOFF_T(p,0,file_size); p += 8;
2153 SOFF_T(p,0,allocation_size); p += 8;
2154 SIVAL(p,0,mode); p += 4;
2155 status = srvstr_push(base_data, flags2,
2156 p + 4, fname, PTR_DIFF(end_data, p+4),
2157 STR_TERMINATE_ASCII, &len);
2158 if (!NT_STATUS_IS_OK(status)) {
2164 len = PTR_DIFF(p, pdata);
2165 pad = (len + (align-1)) & ~(align-1);
2167 * offset to the next entry, the caller
2168 * will overwrite it for the last entry
2169 * that's why we always include the padding
2173 * set padding to zero
2176 memset(p, 0, pad - len);
2183 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2184 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2186 SIVAL(p,0,reskey); p += 4;
2187 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2188 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2189 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2190 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2191 SOFF_T(p,0,file_size); p += 8;
2192 SOFF_T(p,0,allocation_size); p += 8;
2193 SIVAL(p,0,mode); p += 4;
2194 q = p; p += 4; /* q is placeholder for name length. */
2195 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2196 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2198 unsigned int ea_size = estimate_ea_size(conn, NULL,
2200 SIVAL(p,0,ea_size); /* Extended attributes */
2203 status = srvstr_push(base_data, flags2, p,
2204 fname, PTR_DIFF(end_data, p),
2205 STR_TERMINATE_ASCII, &len);
2206 if (!NT_STATUS_IS_OK(status)) {
2212 len = PTR_DIFF(p, pdata);
2213 pad = (len + (align-1)) & ~(align-1);
2215 * offset to the next entry, the caller
2216 * will overwrite it for the last entry
2217 * that's why we always include the padding
2221 * set padding to zero
2224 memset(p, 0, pad - len);
2231 case SMB_FIND_FILE_NAMES_INFO:
2232 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2234 SIVAL(p,0,reskey); p += 4;
2236 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2237 acl on a dir (tridge) */
2238 status = srvstr_push(base_data, flags2, p,
2239 fname, PTR_DIFF(end_data, p),
2240 STR_TERMINATE_ASCII, &len);
2241 if (!NT_STATUS_IS_OK(status)) {
2247 len = PTR_DIFF(p, pdata);
2248 pad = (len + (align-1)) & ~(align-1);
2250 * offset to the next entry, the caller
2251 * will overwrite it for the last entry
2252 * that's why we always include the padding
2256 * set padding to zero
2259 memset(p, 0, pad - len);
2266 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2267 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2269 SIVAL(p,0,reskey); p += 4;
2270 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2271 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2272 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2273 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2274 SOFF_T(p,0,file_size); p += 8;
2275 SOFF_T(p,0,allocation_size); p += 8;
2276 SIVAL(p,0,mode); p += 4;
2277 q = p; p += 4; /* q is placeholder for name length. */
2278 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2279 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2281 unsigned int ea_size = estimate_ea_size(conn, NULL,
2283 SIVAL(p,0,ea_size); /* Extended attributes */
2286 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2287 SBVAL(p,0,file_id); p += 8;
2288 status = srvstr_push(base_data, flags2, p,
2289 fname, PTR_DIFF(end_data, p),
2290 STR_TERMINATE_ASCII, &len);
2291 if (!NT_STATUS_IS_OK(status)) {
2297 len = PTR_DIFF(p, pdata);
2298 pad = (len + (align-1)) & ~(align-1);
2300 * offset to the next entry, the caller
2301 * will overwrite it for the last entry
2302 * that's why we always include the padding
2306 * set padding to zero
2309 memset(p, 0, pad - len);
2316 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2317 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2318 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2320 SIVAL(p,0,reskey); p += 4;
2321 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2322 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2323 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2324 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2325 SOFF_T(p,0,file_size); p += 8;
2326 SOFF_T(p,0,allocation_size); p += 8;
2327 SIVAL(p,0,mode); p += 4;
2328 q = p; p += 4; /* q is placeholder for name length */
2329 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2330 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2331 } else if (readdir_attr_data &&
2332 readdir_attr_data->type == RDATTR_AAPL) {
2334 * OS X specific SMB2 extension negotiated via
2335 * AAPL create context: return max_access in
2338 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2340 unsigned int ea_size = estimate_ea_size(conn, NULL,
2342 SIVAL(p,0,ea_size); /* Extended attributes */
2346 if (readdir_attr_data &&
2347 readdir_attr_data->type == RDATTR_AAPL) {
2349 * OS X specific SMB2 extension negotiated via
2350 * AAPL create context: return resource fork
2351 * length and compressed FinderInfo in
2354 * According to documentation short_name_len
2355 * should be 0, but on the wire behaviour
2356 * shows its set to 24 by clients.
2360 /* Resourefork length */
2361 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2363 /* Compressed FinderInfo */
2364 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2365 } else if (!was_8_3 && check_mangled_names) {
2366 char mangled_name[13]; /* mangled 8.3 name. */
2367 if (!name_to_8_3(fname,mangled_name,True,
2369 /* Error - mangle failed ! */
2370 memset(mangled_name,'\0',12);
2372 mangled_name[12] = 0;
2373 status = srvstr_push(base_data, flags2,
2374 p+2, mangled_name, 24,
2375 STR_UPPER|STR_UNICODE, &len);
2376 if (!NT_STATUS_IS_OK(status)) {
2381 memset(p + 2 + len,'\0',24 - len);
2385 /* Clear the short name buffer. This is
2386 * IMPORTANT as not doing so will trigger
2387 * a Win2k client bug. JRA.
2394 if (readdir_attr_data &&
2395 readdir_attr_data->type == RDATTR_AAPL) {
2397 * OS X specific SMB2 extension negotiated via
2398 * AAPL create context: return UNIX mode in
2401 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2402 SSVAL(p, 0, aapl_mode);
2408 SBVAL(p,0,file_id); p += 8;
2409 status = srvstr_push(base_data, flags2, p,
2410 fname, PTR_DIFF(end_data, p),
2411 STR_TERMINATE_ASCII, &len);
2412 if (!NT_STATUS_IS_OK(status)) {
2418 len = PTR_DIFF(p, pdata);
2419 pad = (len + (align-1)) & ~(align-1);
2421 * offset to the next entry, the caller
2422 * will overwrite it for the last entry
2423 * that's why we always include the padding
2427 * set padding to zero
2430 memset(p, 0, pad - len);
2437 /* CIFS UNIX Extension. */
2439 case SMB_FIND_FILE_UNIX:
2440 case SMB_FIND_FILE_UNIX_INFO2:
2442 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2444 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2446 if (info_level == SMB_FIND_FILE_UNIX) {
2447 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2448 p = store_file_unix_basic(conn, p,
2449 NULL, &smb_fname->st);
2450 status = srvstr_push(base_data, flags2, p,
2451 fname, PTR_DIFF(end_data, p),
2452 STR_TERMINATE, &len);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2458 p = store_file_unix_basic_info2(conn, p,
2459 NULL, &smb_fname->st);
2462 status = srvstr_push(base_data, flags2, p, fname,
2463 PTR_DIFF(end_data, p), 0, &len);
2464 if (!NT_STATUS_IS_OK(status)) {
2467 SIVAL(nameptr, 0, len);
2472 len = PTR_DIFF(p, pdata);
2473 pad = (len + (align-1)) & ~(align-1);
2475 * offset to the next entry, the caller
2476 * will overwrite it for the last entry
2477 * that's why we always include the padding
2481 * set padding to zero
2484 memset(p, 0, pad - len);
2489 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2494 return NT_STATUS_INVALID_LEVEL;
2497 if (PTR_DIFF(p,pdata) > space_remaining) {
2498 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2499 "(wanted %u, had %d)\n",
2500 (unsigned int)PTR_DIFF(p,pdata),
2502 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2505 /* Setup the last entry pointer, as an offset from base_data */
2506 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2507 /* Advance the data pointer to the next slot */
2510 return NT_STATUS_OK;
2513 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2514 connection_struct *conn,
2515 struct dptr_struct *dirptr,
2517 const char *path_mask,
2520 int requires_resume_key,
2529 int space_remaining,
2530 struct smb_filename **_smb_fname,
2531 bool *got_exact_match,
2532 int *_last_entry_off,
2533 struct ea_list *name_list,
2534 struct file_id *file_id)
2537 const char *mask = NULL;
2538 long prev_dirpos = 0;
2541 struct smb_filename *smb_fname = NULL;
2542 struct smbd_dirptr_lanman2_state state;
2544 uint64_t last_entry_off = 0;
2546 enum mangled_names_options mangled_names;
2547 bool marshall_with_83_names;
2549 mangled_names = lp_mangled_names(conn->params);
2553 state.info_level = info_level;
2554 if (mangled_names != MANGLED_NAMES_NO) {
2555 state.check_mangled_names = true;
2557 state.has_wild = dptr_has_wild(dirptr);
2558 state.got_exact_match = false;
2560 *got_exact_match = false;
2562 p = strrchr_m(path_mask,'/');
2573 ok = smbd_dirptr_get_entry(ctx,
2580 smbd_dirptr_lanman2_match_fn,
2581 smbd_dirptr_lanman2_mode_fn,
2588 return NT_STATUS_END_OF_FILE;
2591 *got_exact_match = state.got_exact_match;
2593 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2595 status = smbd_marshall_dir_entry(ctx,
2600 marshall_with_83_names,
2601 requires_resume_key,
2612 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2613 DEBUG(1,("Conversion error: illegal character: %s\n",
2614 smb_fname_str_dbg(smb_fname)));
2617 if (file_id != NULL) {
2618 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2621 if (!NT_STATUS_IS_OK(status) &&
2622 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2624 TALLOC_FREE(smb_fname);
2629 if (_smb_fname != NULL) {
2630 struct smb_filename *name = NULL;
2632 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2634 TALLOC_FREE(smb_fname);
2636 return NT_STATUS_NO_MEMORY;
2641 TALLOC_FREE(smb_fname);
2644 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2645 dptr_SeekDir(dirptr, prev_dirpos);
2649 *_last_entry_off = last_entry_off;
2650 return NT_STATUS_OK;
2653 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2654 connection_struct *conn,
2655 struct dptr_struct *dirptr,
2657 const char *path_mask,
2660 bool requires_resume_key,
2666 int space_remaining,
2667 bool *got_exact_match,
2668 int *last_entry_off,
2669 struct ea_list *name_list)
2672 const bool do_pad = true;
2674 if (info_level >= 1 && info_level <= 3) {
2675 /* No alignment on earlier info levels. */
2679 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2680 path_mask, dirtype, info_level,
2681 requires_resume_key, dont_descend, ask_sharemode,
2682 true, align, do_pad,
2683 ppdata, base_data, end_data,
2687 last_entry_off, name_list, NULL);
2690 /****************************************************************************
2691 Reply to a TRANS2_FINDFIRST.
2692 ****************************************************************************/
2694 static void call_trans2findfirst(connection_struct *conn,
2695 struct smb_request *req,
2696 char **pparams, int total_params,
2697 char **ppdata, int total_data,
2698 unsigned int max_data_bytes)
2700 /* We must be careful here that we don't return more than the
2701 allowed number of data bytes. If this means returning fewer than
2702 maxentries then so be it. We assume that the redirector has
2703 enough room for the fixed number of parameter bytes it has
2705 struct smb_filename *smb_dname = NULL;
2706 char *params = *pparams;
2707 char *pdata = *ppdata;
2711 uint16_t findfirst_flags;
2712 bool close_after_first;
2714 bool requires_resume_key;
2716 char *directory = NULL;
2719 int last_entry_off=0;
2723 bool finished = False;
2724 bool dont_descend = False;
2725 bool out_of_space = False;
2726 int space_remaining;
2727 bool mask_contains_wcard = False;
2728 struct ea_list *ea_list = NULL;
2729 NTSTATUS ntstatus = NT_STATUS_OK;
2730 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2731 struct smbd_server_connection *sconn = req->sconn;
2732 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2733 ucf_flags_from_smb_request(req);
2734 bool backup_priv = false;
2735 bool as_root = false;
2736 files_struct *fsp = NULL;
2737 const struct loadparm_substitution *lp_sub =
2738 loadparm_s3_global_substitution();
2741 if (total_params < 13) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2746 dirtype = SVAL(params,0);
2747 maxentries = SVAL(params,2);
2748 findfirst_flags = SVAL(params,4);
2749 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2750 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2751 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2752 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2753 security_token_has_privilege(get_current_nttok(conn),
2756 info_level = SVAL(params,6);
2758 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2759 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2760 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2762 info_level, max_data_bytes));
2765 /* W2K3 seems to treat zero as 1. */
2769 switch (info_level) {
2770 case SMB_FIND_INFO_STANDARD:
2771 case SMB_FIND_EA_SIZE:
2772 case SMB_FIND_EA_LIST:
2773 case SMB_FIND_FILE_DIRECTORY_INFO:
2774 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2775 case SMB_FIND_FILE_NAMES_INFO:
2776 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2777 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2778 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2780 case SMB_FIND_FILE_UNIX:
2781 case SMB_FIND_FILE_UNIX_INFO2:
2782 /* Always use filesystem for UNIX mtime query. */
2783 ask_sharemode = false;
2784 if (!lp_unix_extensions()) {
2785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2788 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2791 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2795 if (req->posix_pathnames) {
2796 srvstr_get_path_wcard_posix(talloc_tos(),
2804 &mask_contains_wcard);
2806 srvstr_get_path_wcard(talloc_tos(),
2814 &mask_contains_wcard);
2816 if (!NT_STATUS_IS_OK(ntstatus)) {
2817 reply_nterror(req, ntstatus);
2824 ntstatus = filename_convert_with_privilege(talloc_tos(),
2829 &mask_contains_wcard,
2832 ntstatus = filename_convert(talloc_tos(), conn,
2836 &mask_contains_wcard,
2840 if (!NT_STATUS_IS_OK(ntstatus)) {
2841 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2842 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2843 ERRSRV, ERRbadpath);
2846 reply_nterror(req, ntstatus);
2850 mask = get_original_lcomp(talloc_tos(),
2855 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 directory = smb_dname->base_name;
2861 p = strrchr_m(directory,'/');
2863 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2864 if((directory[0] == '.') && (directory[1] == '\0')) {
2865 mask = talloc_strdup(talloc_tos(),"*");
2867 reply_nterror(req, NT_STATUS_NO_MEMORY);
2870 mask_contains_wcard = True;
2876 if (p == NULL || p == directory) {
2877 /* Ensure we don't have a directory name of "". */
2878 directory = talloc_strdup(talloc_tos(), ".");
2880 reply_nterror(req, NT_STATUS_NO_MEMORY);
2883 /* Ensure smb_dname->base_name matches. */
2884 smb_dname->base_name = directory;
2887 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2889 if (info_level == SMB_FIND_EA_LIST) {
2892 if (total_data < 4) {
2893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2897 ea_size = IVAL(pdata,0);
2898 if (ea_size != total_data) {
2899 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2900 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2905 if (!lp_ea_support(SNUM(conn))) {
2906 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2910 /* Pull out the list of names. */
2911 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2918 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2923 *ppdata = (char *)SMB_REALLOC(
2924 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2925 if(*ppdata == NULL ) {
2926 reply_nterror(req, NT_STATUS_NO_MEMORY);
2930 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2932 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2935 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2936 /* Realloc the params space */
2937 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2938 if (*pparams == NULL) {
2939 reply_nterror(req, NT_STATUS_NO_MEMORY);
2945 * As we've cut off the last component from
2946 * smb_fname we need to re-stat smb_dname
2947 * so FILE_OPEN disposition knows the directory
2950 if (req->posix_pathnames) {
2951 ret = SMB_VFS_LSTAT(conn, smb_dname);
2953 ret = SMB_VFS_STAT(conn, smb_dname);
2957 ntstatus = map_nt_error_from_unix(errno);
2958 reply_nterror(req, ntstatus);
2963 * Open an fsp on this directory for the dptr.
2965 ntstatus = SMB_VFS_CREATE_FILE(
2968 0, /* root_dir_fid */
2969 smb_dname, /* dname */
2970 FILE_LIST_DIRECTORY, /* access_mask */
2972 FILE_SHARE_WRITE, /* share_access */
2973 FILE_OPEN, /* create_disposition*/
2974 FILE_DIRECTORY_FILE, /* create_options */
2975 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2976 NO_OPLOCK, /* oplock_request */
2978 0, /* allocation_size */
2979 0, /* private_flags */
2984 NULL, /* in_context */
2985 NULL);/* out_context */
2987 if (!NT_STATUS_IS_OK(ntstatus)) {
2988 DBG_ERR("failed to open directory %s\n",
2989 smb_fname_str_dbg(smb_dname));
2990 reply_nterror(req, ntstatus);
2994 /* Save the wildcard match and attribs we are using on this directory -
2995 needed as lanman2 assumes these are being saved between calls */
2997 ntstatus = dptr_create(conn,
3004 mask_contains_wcard,
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 bool mask_contains_wcard = False;
3209 char *resume_name = NULL;
3210 const char *mask = NULL;
3211 const char *directory = NULL;
3215 int i, last_entry_off=0;
3216 bool finished = False;
3217 bool dont_descend = False;
3218 bool out_of_space = False;
3219 int space_remaining;
3220 struct ea_list *ea_list = NULL;
3221 NTSTATUS ntstatus = NT_STATUS_OK;
3222 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3223 TALLOC_CTX *ctx = talloc_tos();
3224 struct smbd_server_connection *sconn = req->sconn;
3225 bool backup_priv = false;
3226 bool as_root = false;
3227 files_struct *fsp = NULL;
3228 const struct loadparm_substitution *lp_sub =
3229 loadparm_s3_global_substitution();
3231 if (total_params < 13) {
3232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3236 dptr_num = SVAL(params,0);
3237 maxentries = SVAL(params,2);
3238 info_level = SVAL(params,4);
3239 resume_key = IVAL(params,6);
3240 findnext_flags = SVAL(params,10);
3241 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3242 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3243 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3244 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3246 if (!continue_bit) {
3247 /* We only need resume_name if continue_bit is zero. */
3248 if (req->posix_pathnames) {
3249 srvstr_get_path_wcard_posix(ctx,
3257 &mask_contains_wcard);
3259 srvstr_get_path_wcard(ctx,
3267 &mask_contains_wcard);
3269 if (!NT_STATUS_IS_OK(ntstatus)) {
3270 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3271 complain (it thinks we're asking for the directory above the shared
3272 path or an invalid name). Catch this as the resume name is only compared, never used in
3273 a file access. JRA. */
3274 srvstr_pull_talloc(ctx, params, req->flags2,
3275 &resume_name, params+12,
3279 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3280 reply_nterror(req, ntstatus);
3286 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3288 resume_key = %d resume name = %s continue=%d level = %d\n",
3289 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3290 requires_resume_key, resume_key,
3291 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3294 /* W2K3 seems to treat zero as 1. */
3298 switch (info_level) {
3299 case SMB_FIND_INFO_STANDARD:
3300 case SMB_FIND_EA_SIZE:
3301 case SMB_FIND_EA_LIST:
3302 case SMB_FIND_FILE_DIRECTORY_INFO:
3303 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3304 case SMB_FIND_FILE_NAMES_INFO:
3305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3306 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3307 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3309 case SMB_FIND_FILE_UNIX:
3310 case SMB_FIND_FILE_UNIX_INFO2:
3311 /* Always use filesystem for UNIX mtime query. */
3312 ask_sharemode = false;
3313 if (!lp_unix_extensions()) {
3314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3323 if (info_level == SMB_FIND_EA_LIST) {
3326 if (total_data < 4) {
3327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3331 ea_size = IVAL(pdata,0);
3332 if (ea_size != total_data) {
3333 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3334 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3339 if (!lp_ea_support(SNUM(conn))) {
3340 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3344 /* Pull out the list of names. */
3345 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3352 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3357 *ppdata = (char *)SMB_REALLOC(
3358 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3359 if(*ppdata == NULL) {
3360 reply_nterror(req, NT_STATUS_NO_MEMORY);
3365 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3368 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3371 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3372 /* Realloc the params space */
3373 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3374 if(*pparams == NULL ) {
3375 reply_nterror(req, NT_STATUS_NO_MEMORY);
3381 /* Check that the dptr is valid */
3382 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3384 reply_nterror(req, STATUS_NO_MORE_FILES);
3388 directory = dptr_path(sconn, dptr_num);
3390 /* Get the wildcard mask from the dptr */
3391 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3392 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3393 reply_nterror(req, STATUS_NO_MORE_FILES);
3397 /* Get the attr mask from the dptr */
3398 dirtype = dptr_attr(sconn, dptr_num);
3400 backup_priv = dptr_get_priv(fsp->dptr);
3402 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3403 "backup_priv = %d\n",
3404 dptr_num, mask, dirtype,
3406 dptr_TellDir(fsp->dptr),
3409 /* We don't need to check for VOL here as this is returned by
3410 a different TRANS2 call. */
3412 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3413 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3414 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3415 dont_descend = True;
3418 space_remaining = max_data_bytes;
3419 out_of_space = False;
3427 * Seek to the correct position. We no longer use the resume key but
3428 * depend on the last file name instead.
3431 if(!continue_bit && resume_name && *resume_name) {
3434 long current_pos = 0;
3436 * Remember, name_to_8_3 is called by
3437 * get_lanman2_dir_entry(), so the resume name
3438 * could be mangled. Ensure we check the unmangled name.
3441 if (mangle_is_mangled(resume_name, conn->params)) {
3442 char *new_resume_name = NULL;
3443 mangle_lookup_name_from_8_3(ctx,
3447 if (new_resume_name) {
3448 resume_name = new_resume_name;
3453 * Fix for NT redirector problem triggered by resume key indexes
3454 * changing between directory scans. We now return a resume key of 0
3455 * and instead look for the filename to continue from (also given
3456 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3457 * findfirst/findnext (as is usual) then the directory pointer
3458 * should already be at the correct place.
3461 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3462 } /* end if resume_name && !continue_bit */
3464 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3465 bool got_exact_match = False;
3467 /* this is a heuristic to avoid seeking the fsp->dptr except when
3468 absolutely necessary. It allows for a filename of about 40 chars */
3469 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3470 out_of_space = True;
3473 ntstatus = get_lanman2_dir_entry(ctx,
3477 mask,dirtype,info_level,
3478 requires_resume_key,dont_descend,
3483 &last_entry_off, ea_list);
3484 if (NT_STATUS_EQUAL(ntstatus,
3485 NT_STATUS_ILLEGAL_CHARACTER)) {
3487 * Bad character conversion on name. Ignore this
3492 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3493 out_of_space = true;
3495 finished = !NT_STATUS_IS_OK(ntstatus);
3499 if (!finished && !out_of_space)
3503 * As an optimisation if we know we aren't looking
3504 * for a wildcard name (ie. the name matches the wildcard exactly)
3505 * then we can finish on any (first) match.
3506 * This speeds up large directory searches. JRA.
3512 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3515 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3516 smb_fn_name(req->cmd),
3517 mask, directory, dirtype, numentries ) );
3519 /* Check if we can close the fsp->dptr */
3520 if(close_after_request || (finished && close_if_end)) {
3521 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3523 close_file(NULL, fsp, NORMAL_CLOSE);
3531 /* Set up the return parameter block */
3532 SSVAL(params,0,numentries);
3533 SSVAL(params,2,finished);
3534 SSVAL(params,4,0); /* Never an EA error */
3535 SSVAL(params,6,last_entry_off);
3537 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3543 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3545 const struct loadparm_substitution *lp_sub =
3546 loadparm_s3_global_substitution();
3548 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3552 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3554 SMB_ASSERT(extended_info != NULL);
3556 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3557 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3558 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3559 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3560 #ifdef SAMBA_VERSION_REVISION
3561 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3563 extended_info->samba_subversion = 0;
3564 #ifdef SAMBA_VERSION_RC_RELEASE
3565 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3567 #ifdef SAMBA_VERSION_PRE_RELEASE
3568 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3571 #ifdef SAMBA_VERSION_VENDOR_PATCH
3572 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3574 extended_info->samba_gitcommitdate = 0;
3575 #ifdef SAMBA_VERSION_COMMIT_TIME
3576 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3579 memset(extended_info->samba_version_string, 0,
3580 sizeof(extended_info->samba_version_string));
3582 snprintf (extended_info->samba_version_string,
3583 sizeof(extended_info->samba_version_string),
3584 "%s", samba_version_string());
3587 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3588 connection_struct *conn,
3589 TALLOC_CTX *mem_ctx,
3590 uint16_t info_level,
3592 unsigned int max_data_bytes,
3593 size_t *fixed_portion,
3594 struct smb_filename *fname,
3598 const struct loadparm_substitution *lp_sub =
3599 loadparm_s3_global_substitution();
3600 char *pdata, *end_data;
3603 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3604 int snum = SNUM(conn);
3605 const char *fstype = lp_fstype(SNUM(conn));
3606 const char *filename = NULL;
3607 const uint64_t bytes_per_sector = 512;
3608 uint32_t additional_flags = 0;
3609 struct smb_filename smb_fname;
3611 NTSTATUS status = NT_STATUS_OK;
3614 if (fname == NULL || fname->base_name == NULL) {
3617 filename = fname->base_name;
3621 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3622 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3623 "info level (0x%x) on IPC$.\n",
3624 (unsigned int)info_level));
3625 return NT_STATUS_ACCESS_DENIED;
3629 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3631 ZERO_STRUCT(smb_fname);
3632 smb_fname.base_name = discard_const_p(char, filename);
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_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4482 NT_STATUS_NOT_SUPPORTED);
4486 if (xconn->smb1.echo_handler.trusted_fde) {
4487 DEBUG( 2,("call_trans2setfsinfo: "
4488 "request transport encryption disabled"
4489 "with 'fork echo handler = yes'\n"));
4492 NT_STATUS_NOT_SUPPORTED);
4496 DEBUG( 4,("call_trans2setfsinfo: "
4497 "request transport encryption.\n"));
4499 status = srv_request_encryption_setup(conn,
4500 (unsigned char **)ppdata,
4502 (unsigned char **)pparams,
4505 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4506 !NT_STATUS_IS_OK(status)) {
4507 reply_nterror(req, status);
4511 send_trans2_replies(conn, req,
4519 if (NT_STATUS_IS_OK(status)) {
4520 /* Server-side transport
4521 * encryption is now *on*. */
4522 status = srv_encryption_start(conn);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 char *reason = talloc_asprintf(talloc_tos(),
4525 "Failure in setting "
4526 "up encrypted transport: %s",
4528 exit_server_cleanly(reason);
4534 case SMB_FS_QUOTA_INFORMATION:
4538 .data = (uint8_t *)pdata,
4539 .length = total_data
4541 files_struct *fsp = NULL;
4542 fsp = file_fsp(req, SVAL(params,0));
4544 status = smb_set_fsquota(conn,
4548 if (!NT_STATUS_IS_OK(status)) {
4549 reply_nterror(req, status);
4555 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4557 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4563 * sending this reply works fine,
4564 * but I'm not sure it's the same
4565 * like windows do...
4568 reply_outbuf(req, 10, 0);
4571 #if defined(HAVE_POSIX_ACLS)
4572 /****************************************************************************
4573 Utility function to count the number of entries in a POSIX acl.
4574 ****************************************************************************/
4576 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4578 unsigned int ace_count = 0;
4579 int entry_id = SMB_ACL_FIRST_ENTRY;
4580 SMB_ACL_ENTRY_T entry;
4582 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4584 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4585 entry_id = SMB_ACL_NEXT_ENTRY;
4592 /****************************************************************************
4593 Utility function to marshall a POSIX acl into wire format.
4594 ****************************************************************************/
4596 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4598 int entry_id = SMB_ACL_FIRST_ENTRY;
4599 SMB_ACL_ENTRY_T entry;
4601 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4602 SMB_ACL_TAG_T tagtype;
4603 SMB_ACL_PERMSET_T permset;
4604 unsigned char perms = 0;
4605 unsigned int own_grp;
4608 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4609 entry_id = SMB_ACL_NEXT_ENTRY;
4612 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4613 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4617 if (sys_acl_get_permset(entry, &permset) == -1) {
4618 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4622 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4623 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4624 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4626 SCVAL(pdata,1,perms);
4629 case SMB_ACL_USER_OBJ:
4630 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4631 own_grp = (unsigned int)pst->st_ex_uid;
4632 SIVAL(pdata,2,own_grp);
4637 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4639 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4642 own_grp = (unsigned int)*puid;
4643 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4644 SIVAL(pdata,2,own_grp);
4648 case SMB_ACL_GROUP_OBJ:
4649 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4650 own_grp = (unsigned int)pst->st_ex_gid;
4651 SIVAL(pdata,2,own_grp);
4656 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4658 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4661 own_grp = (unsigned int)*pgid;
4662 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4663 SIVAL(pdata,2,own_grp);
4668 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4669 SIVAL(pdata,2,0xFFFFFFFF);
4670 SIVAL(pdata,6,0xFFFFFFFF);
4673 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4674 SIVAL(pdata,2,0xFFFFFFFF);
4675 SIVAL(pdata,6,0xFFFFFFFF);
4678 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4681 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4688 /****************************************************************************
4689 Store the FILE_UNIX_BASIC info.
4690 ****************************************************************************/
4692 static char *store_file_unix_basic(connection_struct *conn,
4695 const SMB_STRUCT_STAT *psbuf)
4699 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4700 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4702 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4705 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4708 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4709 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4710 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4713 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4717 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4721 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4724 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4725 devno = psbuf->st_ex_rdev;
4727 devno = psbuf->st_ex_dev;
4730 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4734 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4738 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4741 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4745 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4752 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4753 * the chflags(2) (or equivalent) flags.
4755 * XXX: this really should be behind the VFS interface. To do this, we would
4756 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4757 * Each VFS module could then implement its own mapping as appropriate for the
4758 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4760 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4764 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4768 { UF_IMMUTABLE, EXT_IMMUTABLE },
4772 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4776 { UF_HIDDEN, EXT_HIDDEN },
4779 /* Do not remove. We need to guarantee that this array has at least one
4780 * entry to build on HP-UX.
4786 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4787 uint32_t *smb_fflags, uint32_t *smb_fmask)
4791 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4792 *smb_fmask |= info2_flags_map[i].smb_fflag;
4793 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4794 *smb_fflags |= info2_flags_map[i].smb_fflag;
4799 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4800 const uint32_t smb_fflags,
4801 const uint32_t smb_fmask,
4804 uint32_t max_fmask = 0;
4807 *stat_fflags = psbuf->st_ex_flags;
4809 /* For each flags requested in smb_fmask, check the state of the
4810 * corresponding flag in smb_fflags and set or clear the matching
4814 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4815 max_fmask |= info2_flags_map[i].smb_fflag;
4816 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4817 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4818 *stat_fflags |= info2_flags_map[i].stat_fflag;
4820 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4825 /* If smb_fmask is asking to set any bits that are not supported by
4826 * our flag mappings, we should fail.
4828 if ((smb_fmask & max_fmask) != smb_fmask) {
4836 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4837 * of file flags and birth (create) time.
4839 static char *store_file_unix_basic_info2(connection_struct *conn,
4842 const SMB_STRUCT_STAT *psbuf)
4844 uint32_t file_flags = 0;
4845 uint32_t flags_mask = 0;
4847 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4849 /* Create (birth) time 64 bit */
4850 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4853 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4854 SIVAL(pdata, 0, file_flags); /* flags */
4855 SIVAL(pdata, 4, flags_mask); /* mask */
4861 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4862 const struct stream_struct *streams,
4864 unsigned int max_data_bytes,
4865 unsigned int *data_size)
4868 unsigned int ofs = 0;
4870 if (max_data_bytes < 32) {
4871 return NT_STATUS_INFO_LENGTH_MISMATCH;
4874 for (i = 0; i < num_streams; i++) {
4875 unsigned int next_offset;
4877 smb_ucs2_t *namebuf;
4879 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4880 streams[i].name, &namelen) ||
4883 return NT_STATUS_INVALID_PARAMETER;
4887 * name_buf is now null-terminated, we need to marshall as not
4894 * We cannot overflow ...
4896 if ((ofs + 24 + namelen) > max_data_bytes) {
4897 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4899 TALLOC_FREE(namebuf);
4900 return STATUS_BUFFER_OVERFLOW;
4903 SIVAL(data, ofs+4, namelen);
4904 SOFF_T(data, ofs+8, streams[i].size);
4905 SOFF_T(data, ofs+16, streams[i].alloc_size);
4906 memcpy(data+ofs+24, namebuf, namelen);
4907 TALLOC_FREE(namebuf);
4909 next_offset = ofs + 24 + namelen;
4911 if (i == num_streams-1) {
4912 SIVAL(data, ofs, 0);
4915 unsigned int align = ndr_align_size(next_offset, 8);
4917 if ((next_offset + align) > max_data_bytes) {
4918 DEBUG(10, ("refusing to overflow align "
4919 "reply at stream %u\n",
4921 TALLOC_FREE(namebuf);
4922 return STATUS_BUFFER_OVERFLOW;
4925 memset(data+next_offset, 0, align);
4926 next_offset += align;
4928 SIVAL(data, ofs, next_offset - ofs);
4935 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4939 return NT_STATUS_OK;
4942 #if defined(HAVE_POSIX_ACLS)
4943 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4944 struct smb_request *req,
4946 struct smb_filename *smb_fname,
4948 unsigned int data_size_in,
4949 unsigned int *pdata_size_out)
4951 SMB_ACL_T file_acl = NULL;
4952 SMB_ACL_T def_acl = NULL;
4953 uint16_t num_file_acls = 0;
4954 uint16_t num_def_acls = 0;
4955 unsigned int size_needed = 0;
4958 bool close_fsp = false;
4961 * Ensure we always operate on a file descriptor, not just
4965 uint32_t access_mask = SEC_STD_READ_CONTROL|
4966 FILE_READ_ATTRIBUTES|
4967 FILE_WRITE_ATTRIBUTES;
4969 status = get_posix_fsp(conn,
4975 if (!NT_STATUS_IS_OK(status)) {
4981 SMB_ASSERT(fsp != NULL);
4983 status = refuse_symlink(conn,
4986 if (!NT_STATUS_IS_OK(status)) {
4990 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4993 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4994 DBG_INFO("ACLs not implemented on "
4995 "filesystem containing %s\n",
4997 status = NT_STATUS_NOT_IMPLEMENTED;
5001 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5003 * We can only have default POSIX ACLs on
5006 if (!fsp->is_directory) {
5007 DBG_INFO("Non-directory open %s\n",
5009 status = NT_STATUS_INVALID_HANDLE;
5012 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5014 SMB_ACL_TYPE_DEFAULT,
5016 def_acl = free_empty_sys_acl(conn, def_acl);
5019 num_file_acls = count_acl_entries(conn, file_acl);
5020 num_def_acls = count_acl_entries(conn, def_acl);
5023 if (num_file_acls + num_def_acls < num_file_acls) {
5024 status = NT_STATUS_INVALID_PARAMETER;
5028 size_needed = num_file_acls + num_def_acls;
5031 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5032 * than UINT_MAX, so check by division.
5034 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5035 status = NT_STATUS_INVALID_PARAMETER;
5039 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5040 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5041 status = NT_STATUS_INVALID_PARAMETER;
5044 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5046 if ( data_size_in < size_needed) {
5047 DBG_INFO("data_size too small (%u) need %u\n",
5050 status = NT_STATUS_BUFFER_TOO_SMALL;
5054 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5055 SSVAL(pdata,2,num_file_acls);
5056 SSVAL(pdata,4,num_def_acls);
5057 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5059 ok = marshall_posix_acl(conn,
5064 status = NT_STATUS_INTERNAL_ERROR;
5067 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5069 ok = marshall_posix_acl(conn,
5074 status = NT_STATUS_INTERNAL_ERROR;
5078 *pdata_size_out = size_needed;
5079 status = NT_STATUS_OK;
5085 * Ensure the stat struct in smb_fname is up to
5086 * date. Structure copy.
5088 smb_fname->st = fsp->fsp_name->st;
5089 (void)close_file(req, fsp, NORMAL_CLOSE);
5093 TALLOC_FREE(file_acl);
5094 TALLOC_FREE(def_acl);
5099 /****************************************************************************
5100 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5101 ****************************************************************************/
5103 static void call_trans2qpipeinfo(connection_struct *conn,
5104 struct smb_request *req,
5105 unsigned int tran_call,
5106 char **pparams, int total_params,
5107 char **ppdata, int total_data,
5108 unsigned int max_data_bytes)
5110 char *params = *pparams;
5111 char *pdata = *ppdata;
5112 unsigned int data_size = 0;
5113 unsigned int param_size = 2;
5114 uint16_t info_level;
5118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5122 if (total_params < 4) {
5123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127 fsp = file_fsp(req, SVAL(params,0));
5128 if (!fsp_is_np(fsp)) {
5129 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5133 info_level = SVAL(params,2);
5135 *pparams = (char *)SMB_REALLOC(*pparams,2);
5136 if (*pparams == NULL) {
5137 reply_nterror(req, NT_STATUS_NO_MEMORY);
5142 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5147 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5148 if (*ppdata == NULL ) {
5149 reply_nterror(req, NT_STATUS_NO_MEMORY);
5154 switch (info_level) {
5155 case SMB_FILE_STANDARD_INFORMATION:
5157 SOFF_T(pdata,0,4096LL);
5164 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5168 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5174 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5175 TALLOC_CTX *mem_ctx,
5176 struct smb_request *req,
5177 uint16_t info_level,
5179 struct smb_filename *smb_fname,
5180 bool delete_pending,
5181 struct timespec write_time_ts,
5182 struct ea_list *ea_list,
5183 int lock_data_count,
5186 unsigned int max_data_bytes,
5187 size_t *fixed_portion,
5189 unsigned int *pdata_size)
5191 char *pdata = *ppdata;
5192 char *dstart, *dend;
5193 unsigned int data_size;
5194 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5195 time_t create_time, mtime, atime, c_time;
5196 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5203 uint64_t file_size = 0;
5205 uint64_t allocation_size = 0;
5206 uint64_t file_id = 0;
5207 uint32_t access_mask = 0;
5210 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5211 return NT_STATUS_INVALID_LEVEL;
5214 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5215 smb_fname_str_dbg(smb_fname),
5217 info_level, max_data_bytes));
5219 mode = dos_mode(conn, smb_fname);
5220 nlink = psbuf->st_ex_nlink;
5222 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5226 if ((nlink > 0) && delete_pending) {
5230 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5231 return NT_STATUS_INVALID_PARAMETER;
5234 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5235 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5236 if (*ppdata == NULL) {
5237 return NT_STATUS_NO_MEMORY;
5241 dend = dstart + data_size - 1;
5243 if (!is_omit_timespec(&write_time_ts) &&
5244 !INFO_LEVEL_IS_UNIX(info_level))
5246 update_stat_ex_mtime(psbuf, write_time_ts);
5249 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5250 mtime_ts = psbuf->st_ex_mtime;
5251 atime_ts = psbuf->st_ex_atime;
5252 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5254 if (lp_dos_filetime_resolution(SNUM(conn))) {
5255 dos_filetime_timespec(&create_time_ts);
5256 dos_filetime_timespec(&mtime_ts);
5257 dos_filetime_timespec(&atime_ts);
5258 dos_filetime_timespec(&ctime_ts);
5261 create_time = convert_timespec_to_time_t(create_time_ts);
5262 mtime = convert_timespec_to_time_t(mtime_ts);
5263 atime = convert_timespec_to_time_t(atime_ts);
5264 c_time = convert_timespec_to_time_t(ctime_ts);
5266 p = strrchr_m(smb_fname->base_name,'/');
5268 base_name = smb_fname->base_name;
5272 /* NT expects the name to be in an exact form of the *full*
5273 filename. See the trans2 torture test */
5274 if (ISDOT(base_name)) {
5275 dos_fname = talloc_strdup(mem_ctx, "\\");
5277 return NT_STATUS_NO_MEMORY;
5280 dos_fname = talloc_asprintf(mem_ctx,
5282 smb_fname->base_name);
5284 return NT_STATUS_NO_MEMORY;
5286 if (is_ntfs_stream_smb_fname(smb_fname)) {
5287 dos_fname = talloc_asprintf(dos_fname, "%s",
5288 smb_fname->stream_name);
5290 return NT_STATUS_NO_MEMORY;
5294 string_replace(dos_fname, '/', '\\');
5297 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5300 /* Do we have this path open ? */
5302 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5303 fsp1 = file_find_di_first(conn->sconn, fileid);
5304 if (fsp1 && fsp1->initial_allocation_size) {
5305 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5309 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5310 file_size = get_file_size_stat(psbuf);
5314 pos = fsp->fh->position_information;
5318 access_mask = fsp->access_mask;
5320 /* GENERIC_EXECUTE mapping from Windows */
5321 access_mask = 0x12019F;
5324 /* This should be an index number - looks like
5327 I think this causes us to fail the IFSKIT
5328 BasicFileInformationTest. -tpot */
5329 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5333 switch (info_level) {
5334 case SMB_INFO_STANDARD:
5335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5337 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5338 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5339 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5340 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5341 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5342 SSVAL(pdata,l1_attrFile,mode);
5345 case SMB_INFO_QUERY_EA_SIZE:
5347 unsigned int ea_size =
5348 estimate_ea_size(conn, fsp,
5350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5352 srv_put_dos_date2(pdata,0,create_time);
5353 srv_put_dos_date2(pdata,4,atime);
5354 srv_put_dos_date2(pdata,8,mtime); /* write time */
5355 SIVAL(pdata,12,(uint32_t)file_size);
5356 SIVAL(pdata,16,(uint32_t)allocation_size);
5357 SSVAL(pdata,20,mode);
5358 SIVAL(pdata,22,ea_size);
5362 case SMB_INFO_IS_NAME_VALID:
5363 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5365 /* os/2 needs this ? really ?*/
5366 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5368 /* This is only reached for qpathinfo */
5372 case SMB_INFO_QUERY_EAS_FROM_LIST:
5374 size_t total_ea_len = 0;
5375 struct ea_list *ea_file_list = NULL;
5376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5379 get_ea_list_from_file(mem_ctx, conn, fsp,
5381 &total_ea_len, &ea_file_list);
5382 if (!NT_STATUS_IS_OK(status)) {
5386 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5388 if (!ea_list || (total_ea_len > data_size)) {
5390 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5394 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5398 case SMB_INFO_QUERY_ALL_EAS:
5400 /* We have data_size bytes to put EA's into. */
5401 size_t total_ea_len = 0;
5402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5404 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5406 &total_ea_len, &ea_list);
5407 if (!NT_STATUS_IS_OK(status)) {
5411 if (!ea_list || (total_ea_len > data_size)) {
5413 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5417 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5421 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5423 /* This is FileFullEaInformation - 0xF which maps to
5424 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5426 /* We have data_size bytes to put EA's into. */
5427 size_t total_ea_len = 0;
5428 struct ea_list *ea_file_list = NULL;
5430 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5432 /*TODO: add filtering and index handling */
5435 get_ea_list_from_file(mem_ctx, conn, fsp,
5437 &total_ea_len, &ea_file_list);
5438 if (!NT_STATUS_IS_OK(status)) {
5441 if (!ea_file_list) {
5442 return NT_STATUS_NO_EAS_ON_FILE;
5445 status = fill_ea_chained_buffer(mem_ctx,
5449 conn, ea_file_list);
5450 if (!NT_STATUS_IS_OK(status)) {
5456 case SMB_FILE_BASIC_INFORMATION:
5457 case SMB_QUERY_FILE_BASIC_INFO:
5459 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5461 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5467 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5468 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5469 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5470 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5471 SIVAL(pdata,32,mode);
5473 DEBUG(5,("SMB_QFBI - "));
5474 DEBUG(5,("create: %s ", ctime(&create_time)));
5475 DEBUG(5,("access: %s ", ctime(&atime)));
5476 DEBUG(5,("write: %s ", ctime(&mtime)));
5477 DEBUG(5,("change: %s ", ctime(&c_time)));
5478 DEBUG(5,("mode: %x\n", mode));
5479 *fixed_portion = data_size;
5482 case SMB_FILE_STANDARD_INFORMATION:
5483 case SMB_QUERY_FILE_STANDARD_INFO:
5485 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5487 SOFF_T(pdata,0,allocation_size);
5488 SOFF_T(pdata,8,file_size);
5489 SIVAL(pdata,16,nlink);
5490 SCVAL(pdata,20,delete_pending?1:0);
5491 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5492 SSVAL(pdata,22,0); /* Padding. */
5493 *fixed_portion = 24;
5496 case SMB_FILE_EA_INFORMATION:
5497 case SMB_QUERY_FILE_EA_INFO:
5499 unsigned int ea_size =
5500 estimate_ea_size(conn, fsp, smb_fname);
5501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5504 SIVAL(pdata,0,ea_size);
5508 /* Get the 8.3 name - used if NT SMB was negotiated. */
5509 case SMB_QUERY_FILE_ALT_NAME_INFO:
5510 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5512 char mangled_name[13];
5513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5514 if (!name_to_8_3(base_name,mangled_name,
5515 True,conn->params)) {
5516 return NT_STATUS_NO_MEMORY;
5518 status = srvstr_push(dstart, flags2,
5519 pdata+4, mangled_name,
5520 PTR_DIFF(dend, pdata+4),
5522 if (!NT_STATUS_IS_OK(status)) {
5525 data_size = 4 + len;
5531 case SMB_QUERY_FILE_NAME_INFO:
5534 this must be *exactly* right for ACLs on mapped drives to work
5536 status = srvstr_push(dstart, flags2,
5538 PTR_DIFF(dend, pdata+4),
5540 if (!NT_STATUS_IS_OK(status)) {
5543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5544 data_size = 4 + len;
5549 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5551 char *nfname = NULL;
5553 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5554 return NT_STATUS_INVALID_LEVEL;
5557 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5558 if (nfname == NULL) {
5559 return NT_STATUS_NO_MEMORY;
5562 if (ISDOT(nfname)) {
5565 string_replace(nfname, '/', '\\');
5567 if (smb_fname->stream_name != NULL) {
5568 const char *s = smb_fname->stream_name;
5569 const char *e = NULL;
5572 SMB_ASSERT(s[0] != '\0');
5575 * smb_fname->stream_name is in form
5576 * of ':StrEam:$DATA', but we should only
5577 * append ':StrEam' here.
5580 e = strchr(&s[1], ':');
5586 nfname = talloc_strndup_append(nfname, s, n);
5587 if (nfname == NULL) {
5588 return NT_STATUS_NO_MEMORY;
5592 status = srvstr_push(dstart, flags2,
5594 PTR_DIFF(dend, pdata+4),
5596 if (!NT_STATUS_IS_OK(status)) {
5599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5600 data_size = 4 + len;
5606 case SMB_FILE_ALLOCATION_INFORMATION:
5607 case SMB_QUERY_FILE_ALLOCATION_INFO:
5608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5610 SOFF_T(pdata,0,allocation_size);
5613 case SMB_FILE_END_OF_FILE_INFORMATION:
5614 case SMB_QUERY_FILE_END_OF_FILEINFO:
5615 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5617 SOFF_T(pdata,0,file_size);
5620 case SMB_QUERY_FILE_ALL_INFO:
5621 case SMB_FILE_ALL_INFORMATION:
5623 unsigned int ea_size =
5624 estimate_ea_size(conn, fsp, smb_fname);
5625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5626 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5627 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5628 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5629 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5630 SIVAL(pdata,32,mode);
5631 SIVAL(pdata,36,0); /* padding. */
5633 SOFF_T(pdata,0,allocation_size);
5634 SOFF_T(pdata,8,file_size);
5635 SIVAL(pdata,16,nlink);
5636 SCVAL(pdata,20,delete_pending);
5637 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5640 SIVAL(pdata,0,ea_size);
5641 pdata += 4; /* EA info */
5642 status = srvstr_push(dstart, flags2,
5644 PTR_DIFF(dend, pdata+4),
5646 if (!NT_STATUS_IS_OK(status)) {
5651 data_size = PTR_DIFF(pdata,(*ppdata));
5652 *fixed_portion = 10;
5656 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5658 unsigned int ea_size =
5659 estimate_ea_size(conn, fsp, smb_fname);
5660 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5661 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5662 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5663 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5664 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5665 SIVAL(pdata, 0x20, mode);
5666 SIVAL(pdata, 0x24, 0); /* padding. */
5667 SBVAL(pdata, 0x28, allocation_size);
5668 SBVAL(pdata, 0x30, file_size);
5669 SIVAL(pdata, 0x38, nlink);
5670 SCVAL(pdata, 0x3C, delete_pending);
5671 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5672 SSVAL(pdata, 0x3E, 0); /* padding */
5673 SBVAL(pdata, 0x40, file_id);
5674 SIVAL(pdata, 0x48, ea_size);
5675 SIVAL(pdata, 0x4C, access_mask);
5676 SBVAL(pdata, 0x50, pos);
5677 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5678 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5682 status = srvstr_push(dstart, flags2,
5684 PTR_DIFF(dend, pdata+4),
5686 if (!NT_STATUS_IS_OK(status)) {
5691 data_size = PTR_DIFF(pdata,(*ppdata));
5692 *fixed_portion = 104;
5695 case SMB_FILE_INTERNAL_INFORMATION:
5697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5698 SBVAL(pdata, 0, file_id);
5703 case SMB_FILE_ACCESS_INFORMATION:
5704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5705 SIVAL(pdata, 0, access_mask);
5710 case SMB_FILE_NAME_INFORMATION:
5711 /* Pathname with leading '\'. */
5714 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5716 SIVAL(pdata,0,byte_len);
5717 data_size = 4 + byte_len;
5721 case SMB_FILE_DISPOSITION_INFORMATION:
5722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5724 SCVAL(pdata,0,delete_pending);
5728 case SMB_FILE_POSITION_INFORMATION:
5729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5731 SOFF_T(pdata,0,pos);
5735 case SMB_FILE_MODE_INFORMATION:
5736 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5737 SIVAL(pdata,0,mode);
5742 case SMB_FILE_ALIGNMENT_INFORMATION:
5743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5744 SIVAL(pdata,0,0); /* No alignment needed. */
5750 * NT4 server just returns "invalid query" to this - if we try
5751 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5754 /* The first statement above is false - verified using Thursby
5755 * client against NT4 -- gcolley.
5757 case SMB_QUERY_FILE_STREAM_INFO:
5758 case SMB_FILE_STREAM_INFORMATION: {
5759 unsigned int num_streams = 0;
5760 struct stream_struct *streams = NULL;
5762 DEBUG(10,("smbd_do_qfilepathinfo: "
5763 "SMB_FILE_STREAM_INFORMATION\n"));
5765 if (is_ntfs_stream_smb_fname(smb_fname)) {
5766 return NT_STATUS_INVALID_PARAMETER;
5769 status = vfs_streaminfo(conn,
5776 if (!NT_STATUS_IS_OK(status)) {
5777 DEBUG(10, ("could not get stream info: %s\n",
5778 nt_errstr(status)));
5782 status = marshall_stream_info(num_streams, streams,
5783 pdata, max_data_bytes,
5786 if (!NT_STATUS_IS_OK(status)) {
5787 DEBUG(10, ("marshall_stream_info failed: %s\n",
5788 nt_errstr(status)));
5789 TALLOC_FREE(streams);
5793 TALLOC_FREE(streams);
5795 *fixed_portion = 32;
5799 case SMB_QUERY_COMPRESSION_INFO:
5800 case SMB_FILE_COMPRESSION_INFORMATION:
5801 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5802 SOFF_T(pdata,0,file_size);
5803 SIVAL(pdata,8,0); /* ??? */
5804 SIVAL(pdata,12,0); /* ??? */
5806 *fixed_portion = 16;
5809 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5810 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5811 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5812 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5813 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5814 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5815 SOFF_T(pdata,32,allocation_size);
5816 SOFF_T(pdata,40,file_size);
5817 SIVAL(pdata,48,mode);
5818 SIVAL(pdata,52,0); /* ??? */
5820 *fixed_portion = 56;
5823 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5824 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5825 SIVAL(pdata,0,mode);
5832 * CIFS UNIX Extensions.
5835 case SMB_QUERY_FILE_UNIX_BASIC:
5837 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5838 data_size = PTR_DIFF(pdata,(*ppdata));
5840 DEBUG(4,("smbd_do_qfilepathinfo: "
5841 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5842 dump_data(4, (uint8_t *)(*ppdata), data_size);
5846 case SMB_QUERY_FILE_UNIX_INFO2:
5848 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5849 data_size = PTR_DIFF(pdata,(*ppdata));
5853 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5855 for (i=0; i<100; i++)
5856 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5862 case SMB_QUERY_FILE_UNIX_LINK:
5865 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5868 return NT_STATUS_NO_MEMORY;
5871 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5873 if(!S_ISLNK(psbuf->st_ex_mode)) {
5874 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5877 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5879 link_len = SMB_VFS_READLINKAT(conn,
5885 if (link_len == -1) {
5886 return map_nt_error_from_unix(errno);
5888 buffer[link_len] = 0;
5889 status = srvstr_push(dstart, flags2,
5891 PTR_DIFF(dend, pdata),
5892 STR_TERMINATE, &len);
5893 if (!NT_STATUS_IS_OK(status)) {
5897 data_size = PTR_DIFF(pdata,(*ppdata));
5902 #if defined(HAVE_POSIX_ACLS)
5903 case SMB_QUERY_POSIX_ACL:
5905 status = smb_query_posix_acl(conn,
5912 if (!NT_STATUS_IS_OK(status)) {
5920 case SMB_QUERY_POSIX_LOCK:
5925 enum brl_type lock_type;
5927 /* We need an open file with a real fd for this. */
5928 if (!fsp || fsp->fh->fd == -1) {
5929 return NT_STATUS_INVALID_LEVEL;
5932 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5937 case POSIX_LOCK_TYPE_READ:
5938 lock_type = READ_LOCK;
5940 case POSIX_LOCK_TYPE_WRITE:
5941 lock_type = WRITE_LOCK;
5943 case POSIX_LOCK_TYPE_UNLOCK:
5945 /* There's no point in asking for an unlock... */
5946 return NT_STATUS_INVALID_PARAMETER;
5949 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5950 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5951 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5953 status = query_lock(fsp,
5960 if (ERROR_WAS_LOCK_DENIED(status)) {
5961 /* Here we need to report who has it locked... */
5962 data_size = POSIX_LOCK_DATA_SIZE;
5964 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5965 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5966 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5967 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5968 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5970 } else if (NT_STATUS_IS_OK(status)) {
5971 /* For success we just return a copy of what we sent
5972 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5973 data_size = POSIX_LOCK_DATA_SIZE;
5974 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5975 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5983 return NT_STATUS_INVALID_LEVEL;
5986 *pdata_size = data_size;
5987 return NT_STATUS_OK;
5990 /****************************************************************************
5991 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5992 file name or file id).
5993 ****************************************************************************/
5995 static void call_trans2qfilepathinfo(connection_struct *conn,
5996 struct smb_request *req,
5997 unsigned int tran_call,
5998 char **pparams, int total_params,
5999 char **ppdata, int total_data,
6000 unsigned int max_data_bytes)
6002 char *params = *pparams;
6003 char *pdata = *ppdata;
6004 uint16_t info_level;
6005 unsigned int data_size = 0;
6006 unsigned int param_size = 2;
6007 struct smb_filename *smb_fname = NULL;
6008 bool delete_pending = False;
6009 struct timespec write_time_ts;
6010 files_struct *fsp = NULL;
6011 struct file_id fileid;
6012 struct ea_list *ea_list = NULL;
6013 int lock_data_count = 0;
6014 char *lock_data = NULL;
6015 size_t fixed_portion;
6016 NTSTATUS status = NT_STATUS_OK;
6019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6023 ZERO_STRUCT(write_time_ts);
6025 if (tran_call == TRANSACT2_QFILEINFO) {
6026 if (total_params < 4) {
6027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6032 call_trans2qpipeinfo(conn, req, tran_call,
6033 pparams, total_params,
6039 fsp = file_fsp(req, SVAL(params,0));
6040 info_level = SVAL(params,2);
6042 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6044 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6049 /* Initial check for valid fsp ptr. */
6050 if (!check_fsp_open(conn, req, fsp)) {
6054 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6055 if (smb_fname == NULL) {
6056 reply_nterror(req, NT_STATUS_NO_MEMORY);
6060 if(fsp->fake_file_handle) {
6062 * This is actually for the QUOTA_FAKE_FILE --metze
6065 /* We know this name is ok, it's already passed the checks. */
6067 } else if(fsp->fh->fd == -1) {
6069 * This is actually a QFILEINFO on a directory
6070 * handle (returned from an NT SMB). NT5.0 seems
6071 * to do this call. JRA.
6074 if (INFO_LEVEL_IS_UNIX(info_level)) {
6075 /* Always do lstat for UNIX calls. */
6076 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6077 DEBUG(3,("call_trans2qfilepathinfo: "
6078 "SMB_VFS_LSTAT of %s failed "
6080 smb_fname_str_dbg(smb_fname),
6083 map_nt_error_from_unix(errno));
6086 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6087 DEBUG(3,("call_trans2qfilepathinfo: "
6088 "SMB_VFS_STAT of %s failed (%s)\n",
6089 smb_fname_str_dbg(smb_fname),
6092 map_nt_error_from_unix(errno));
6096 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6097 fileid = vfs_file_id_from_sbuf(
6098 conn, &smb_fname->st);
6099 get_file_infos(fileid, fsp->name_hash,
6105 * Original code - this is an open file.
6107 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6108 DEBUG(3, ("fstat of %s failed (%s)\n",
6109 fsp_fnum_dbg(fsp), strerror(errno)));
6111 map_nt_error_from_unix(errno));
6114 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6115 fileid = vfs_file_id_from_sbuf(
6116 conn, &smb_fname->st);
6117 get_file_infos(fileid, fsp->name_hash,
6126 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6129 if (total_params < 7) {
6130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6134 info_level = SVAL(params,0);
6136 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6138 if (INFO_LEVEL_IS_UNIX(info_level)) {
6139 if (!lp_unix_extensions()) {
6140 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6143 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6144 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6145 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6146 req->posix_pathnames) {
6147 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6151 if (req->posix_pathnames) {
6152 srvstr_get_path_posix(req,
6161 srvstr_get_path(req,
6170 if (!NT_STATUS_IS_OK(status)) {
6171 reply_nterror(req, status);
6175 status = filename_convert(req,
6182 if (!NT_STATUS_IS_OK(status)) {
6183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6184 reply_botherror(req,
6185 NT_STATUS_PATH_NOT_COVERED,
6186 ERRSRV, ERRbadpath);
6189 reply_nterror(req, status);
6193 /* If this is a stream, check if there is a delete_pending. */
6194 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6195 && is_ntfs_stream_smb_fname(smb_fname)) {
6196 struct smb_filename *smb_fname_base;
6198 /* Create an smb_filename with stream_name == NULL. */
6199 smb_fname_base = synthetic_smb_fname(
6201 smb_fname->base_name,
6205 if (smb_fname_base == NULL) {
6206 reply_nterror(req, NT_STATUS_NO_MEMORY);
6210 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6211 /* Always do lstat for UNIX calls. */
6212 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6213 DEBUG(3,("call_trans2qfilepathinfo: "
6214 "SMB_VFS_LSTAT of %s failed "
6216 smb_fname_str_dbg(smb_fname_base),
6218 TALLOC_FREE(smb_fname_base);
6220 map_nt_error_from_unix(errno));
6224 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6225 DEBUG(3,("call_trans2qfilepathinfo: "
6226 "fileinfo of %s failed "
6228 smb_fname_str_dbg(smb_fname_base),
6230 TALLOC_FREE(smb_fname_base);
6232 map_nt_error_from_unix(errno));
6237 status = file_name_hash(conn,
6238 smb_fname_str_dbg(smb_fname_base),
6240 if (!NT_STATUS_IS_OK(status)) {
6241 TALLOC_FREE(smb_fname_base);
6242 reply_nterror(req, status);
6246 fileid = vfs_file_id_from_sbuf(conn,
6247 &smb_fname_base->st);
6248 TALLOC_FREE(smb_fname_base);
6249 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6250 if (delete_pending) {
6251 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6256 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6257 /* Always do lstat for UNIX calls. */
6258 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6259 DEBUG(3,("call_trans2qfilepathinfo: "
6260 "SMB_VFS_LSTAT of %s failed (%s)\n",
6261 smb_fname_str_dbg(smb_fname),
6264 map_nt_error_from_unix(errno));
6269 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6270 DEBUG(3,("call_trans2qfilepathinfo: "
6271 "SMB_VFS_STAT of %s failed (%s)\n",
6272 smb_fname_str_dbg(smb_fname),
6275 map_nt_error_from_unix(errno));
6280 status = file_name_hash(conn,
6281 smb_fname_str_dbg(smb_fname),
6283 if (!NT_STATUS_IS_OK(status)) {
6284 reply_nterror(req, status);
6288 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6289 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6290 get_file_infos(fileid, name_hash, &delete_pending,
6294 if (delete_pending) {
6295 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6300 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6301 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6303 info_level,tran_call,total_data));
6305 /* Pull out any data sent here before we realloc. */
6306 switch (info_level) {
6307 case SMB_INFO_QUERY_EAS_FROM_LIST:
6309 /* Pull any EA list from the data portion. */
6312 if (total_data < 4) {
6314 req, NT_STATUS_INVALID_PARAMETER);
6317 ea_size = IVAL(pdata,0);
6319 if (total_data > 0 && ea_size != total_data) {
6320 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6321 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6323 req, NT_STATUS_INVALID_PARAMETER);
6327 if (!lp_ea_support(SNUM(conn))) {
6328 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6332 /* Pull out the list of names. */
6333 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6336 req, NT_STATUS_INVALID_PARAMETER);
6342 case SMB_QUERY_POSIX_LOCK:
6344 if (fsp == NULL || fsp->fh->fd == -1) {
6345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6349 if (total_data != POSIX_LOCK_DATA_SIZE) {
6351 req, NT_STATUS_INVALID_PARAMETER);
6355 /* Copy the lock range data. */
6356 lock_data = (char *)talloc_memdup(
6357 req, pdata, total_data);
6359 reply_nterror(req, NT_STATUS_NO_MEMORY);
6362 lock_data_count = total_data;
6368 *pparams = (char *)SMB_REALLOC(*pparams,2);
6369 if (*pparams == NULL) {
6370 reply_nterror(req, NT_STATUS_NO_MEMORY);
6377 * draft-leach-cifs-v1-spec-02.txt
6378 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6381 * The requested information is placed in the Data portion of the
6382 * transaction response. For the information levels greater than 0x100,
6383 * the transaction response has 1 parameter word which should be
6384 * ignored by the client.
6386 * However Windows only follows this rule for the IS_NAME_VALID call.
6388 switch (info_level) {
6389 case SMB_INFO_IS_NAME_VALID:
6394 if ((info_level & 0xFF00) == 0xFF00) {
6396 * We use levels that start with 0xFF00
6397 * internally to represent SMB2 specific levels
6399 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6403 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6405 delete_pending, write_time_ts,
6407 lock_data_count, lock_data,
6408 req->flags2, max_data_bytes,
6410 ppdata, &data_size);
6411 if (!NT_STATUS_IS_OK(status)) {
6412 if (open_was_deferred(req->xconn, req->mid)) {
6413 /* We have re-scheduled this call. */
6416 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6417 bool ok = defer_smb1_sharing_violation(req);
6422 reply_nterror(req, status);
6425 if (fixed_portion > max_data_bytes) {
6426 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6430 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6436 /****************************************************************************
6437 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6439 ****************************************************************************/
6441 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6442 connection_struct *conn,
6443 struct smb_request *req,
6444 bool overwrite_if_exists,
6445 const struct smb_filename *smb_fname_old,
6446 struct smb_filename *smb_fname_new)
6448 NTSTATUS status = NT_STATUS_OK;
6452 /* source must already exist. */
6453 if (!VALID_STAT(smb_fname_old->st)) {
6454 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6457 if (VALID_STAT(smb_fname_new->st)) {
6458 if (overwrite_if_exists) {
6459 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6460 return NT_STATUS_FILE_IS_A_DIRECTORY;
6462 status = unlink_internals(conn,
6464 FILE_ATTRIBUTE_NORMAL,
6467 if (!NT_STATUS_IS_OK(status)) {
6471 /* Disallow if newname already exists. */
6472 return NT_STATUS_OBJECT_NAME_COLLISION;
6476 /* No links from a directory. */
6477 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6478 return NT_STATUS_FILE_IS_A_DIRECTORY;
6481 /* Setting a hardlink to/from a stream isn't currently supported. */
6482 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6484 DBG_DEBUG("Old name has streams\n");
6485 return NT_STATUS_INVALID_PARAMETER;
6487 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6489 DBG_DEBUG("New name has streams\n");
6490 return NT_STATUS_INVALID_PARAMETER;
6493 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6494 smb_fname_old->base_name, smb_fname_new->base_name));
6496 ret = SMB_VFS_LINKAT(conn,
6504 status = map_nt_error_from_unix(errno);
6505 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6506 nt_errstr(status), smb_fname_old->base_name,
6507 smb_fname_new->base_name));
6512 /****************************************************************************
6513 Deal with setting the time from any of the setfilepathinfo functions.
6514 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6515 calling this function.
6516 ****************************************************************************/
6518 NTSTATUS smb_set_file_time(connection_struct *conn,
6520 const struct smb_filename *smb_fname,
6521 struct smb_file_time *ft,
6522 bool setting_write_time)
6524 struct smb_filename smb_fname_base;
6525 struct timeval_buf tbuf[4];
6527 FILE_NOTIFY_CHANGE_LAST_ACCESS
6528 |FILE_NOTIFY_CHANGE_LAST_WRITE
6529 |FILE_NOTIFY_CHANGE_CREATION;
6531 if (!VALID_STAT(smb_fname->st)) {
6532 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6535 /* get some defaults (no modifications) if any info is zero or -1. */
6536 if (is_omit_timespec(&ft->create_time)) {
6537 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6540 if (is_omit_timespec(&ft->atime)) {
6541 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6544 if (is_omit_timespec(&ft->mtime)) {
6545 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6548 if (!setting_write_time) {
6549 /* ft->mtime comes from change time, not write time. */
6550 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6553 /* Ensure the resolution is the correct for
6554 * what we can store on this filesystem. */
6556 round_timespec(conn->ts_res, &ft->create_time);
6557 round_timespec(conn->ts_res, &ft->ctime);
6558 round_timespec(conn->ts_res, &ft->atime);
6559 round_timespec(conn->ts_res, &ft->mtime);
6561 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6562 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6563 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6564 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6565 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6566 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6567 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6568 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6570 if (setting_write_time) {
6572 * This was a Windows setfileinfo on an open file.
6573 * NT does this a lot. We also need to
6574 * set the time here, as it can be read by
6575 * FindFirst/FindNext and with the patch for bug #2045
6576 * in smbd/fileio.c it ensures that this timestamp is
6577 * kept sticky even after a write. We save the request
6578 * away and will set it on file close and after a write. JRA.
6581 DBG_DEBUG("setting pending modtime to %s\n",
6582 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6585 if (fsp->base_fsp) {
6586 set_sticky_write_time_fsp(fsp->base_fsp,
6589 set_sticky_write_time_fsp(fsp, ft->mtime);
6592 set_sticky_write_time_path(
6593 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6598 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6600 /* Always call ntimes on the base, even if a stream was passed in. */
6601 smb_fname_base = *smb_fname;
6602 smb_fname_base.stream_name = NULL;
6604 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6605 return map_nt_error_from_unix(errno);
6608 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6609 smb_fname->base_name);
6610 return NT_STATUS_OK;
6613 /****************************************************************************
6614 Deal with setting the dosmode from any of the setfilepathinfo functions.
6615 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6616 done before calling this function.
6617 ****************************************************************************/
6619 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6620 const struct smb_filename *smb_fname,
6623 struct smb_filename *smb_fname_base;
6626 if (!VALID_STAT(smb_fname->st)) {
6627 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6630 /* Always operate on the base_name, even if a stream was passed in. */
6631 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6632 smb_fname->base_name,
6636 if (smb_fname_base == NULL) {
6637 return NT_STATUS_NO_MEMORY;
6641 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6642 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6644 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6648 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6650 /* check the mode isn't different, before changing it */
6651 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6652 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6653 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6654 (unsigned int)dosmode));
6656 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6658 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6660 smb_fname_str_dbg(smb_fname_base),
6662 status = map_nt_error_from_unix(errno);
6666 status = NT_STATUS_OK;
6668 TALLOC_FREE(smb_fname_base);
6672 /****************************************************************************
6673 Deal with setting the size from any of the setfilepathinfo functions.
6674 ****************************************************************************/
6676 static NTSTATUS smb_set_file_size(connection_struct *conn,
6677 struct smb_request *req,
6679 const struct smb_filename *smb_fname,
6680 const SMB_STRUCT_STAT *psbuf,
6682 bool fail_after_createfile)
6684 NTSTATUS status = NT_STATUS_OK;
6685 struct smb_filename *smb_fname_tmp = NULL;
6686 files_struct *new_fsp = NULL;
6688 if (!VALID_STAT(*psbuf)) {
6689 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6692 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6694 get_file_size_stat(psbuf));
6696 if (size == get_file_size_stat(psbuf)) {
6698 return NT_STATUS_OK;
6700 if (!fsp->modified) {
6701 return NT_STATUS_OK;
6703 trigger_write_time_update_immediate(fsp);
6704 return NT_STATUS_OK;
6707 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6708 smb_fname_str_dbg(smb_fname), (double)size));
6710 if (fsp && fsp->fh->fd != -1) {
6711 /* Handle based call. */
6712 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6713 return NT_STATUS_ACCESS_DENIED;
6716 if (vfs_set_filelen(fsp, size) == -1) {
6717 return map_nt_error_from_unix(errno);
6719 trigger_write_time_update_immediate(fsp);
6720 return NT_STATUS_OK;
6723 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6724 if (smb_fname_tmp == NULL) {
6725 return NT_STATUS_NO_MEMORY;
6728 smb_fname_tmp->st = *psbuf;
6730 status = SMB_VFS_CREATE_FILE(
6733 0, /* root_dir_fid */
6734 smb_fname_tmp, /* fname */
6735 FILE_WRITE_DATA, /* access_mask */
6736 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6738 FILE_OPEN, /* create_disposition*/
6739 0, /* create_options */
6740 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6741 0, /* oplock_request */
6743 0, /* allocation_size */
6744 0, /* private_flags */
6747 &new_fsp, /* result */
6749 NULL, NULL); /* create context */
6751 TALLOC_FREE(smb_fname_tmp);
6753 if (!NT_STATUS_IS_OK(status)) {
6754 /* NB. We check for open_was_deferred in the caller. */
6758 /* See RAW-SFILEINFO-END-OF-FILE */
6759 if (fail_after_createfile) {
6760 close_file(req, new_fsp,NORMAL_CLOSE);
6761 return NT_STATUS_INVALID_LEVEL;
6764 if (vfs_set_filelen(new_fsp, size) == -1) {
6765 status = map_nt_error_from_unix(errno);
6766 close_file(req, new_fsp,NORMAL_CLOSE);
6770 trigger_write_time_update_immediate(new_fsp);
6771 close_file(req, new_fsp,NORMAL_CLOSE);
6772 return NT_STATUS_OK;
6775 /****************************************************************************
6776 Deal with SMB_INFO_SET_EA.
6777 ****************************************************************************/
6779 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6783 const struct smb_filename *smb_fname)
6785 struct ea_list *ea_list = NULL;
6786 TALLOC_CTX *ctx = NULL;
6787 NTSTATUS status = NT_STATUS_OK;
6789 if (total_data < 10) {
6791 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6792 length. They seem to have no effect. Bug #3212. JRA */
6794 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6795 /* We're done. We only get EA info in this call. */
6796 return NT_STATUS_OK;
6799 return NT_STATUS_INVALID_PARAMETER;
6802 if (IVAL(pdata,0) > total_data) {
6803 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6804 IVAL(pdata,0), (unsigned int)total_data));
6805 return NT_STATUS_INVALID_PARAMETER;
6809 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6811 return NT_STATUS_INVALID_PARAMETER;
6814 status = set_ea(conn, fsp, smb_fname, ea_list);
6819 /****************************************************************************
6820 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6821 ****************************************************************************/
6823 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6828 struct ea_list *ea_list = NULL;
6832 return NT_STATUS_INVALID_HANDLE;
6835 if (!lp_ea_support(SNUM(conn))) {
6836 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6837 "EA's not supported.\n",
6838 (unsigned int)total_data));
6839 return NT_STATUS_EAS_NOT_SUPPORTED;
6842 if (total_data < 10) {
6843 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6845 (unsigned int)total_data));
6846 return NT_STATUS_INVALID_PARAMETER;
6849 ea_list = read_nttrans_ea_list(talloc_tos(),
6854 return NT_STATUS_INVALID_PARAMETER;
6857 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6859 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6860 smb_fname_str_dbg(fsp->fsp_name),
6861 nt_errstr(status) ));
6867 /****************************************************************************
6868 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6869 ****************************************************************************/
6871 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6875 struct smb_filename *smb_fname)
6877 NTSTATUS status = NT_STATUS_OK;
6878 bool delete_on_close;
6879 uint32_t dosmode = 0;
6881 if (total_data < 1) {
6882 return NT_STATUS_INVALID_PARAMETER;
6886 return NT_STATUS_INVALID_HANDLE;
6889 delete_on_close = (CVAL(pdata,0) ? True : False);
6890 dosmode = dos_mode(conn, smb_fname);
6892 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6893 "delete_on_close = %u\n",
6894 smb_fname_str_dbg(smb_fname),
6895 (unsigned int)dosmode,
6896 (unsigned int)delete_on_close ));
6898 if (delete_on_close) {
6899 status = can_set_delete_on_close(fsp, dosmode);
6900 if (!NT_STATUS_IS_OK(status)) {
6905 /* The set is across all open files on this dev/inode pair. */
6906 if (!set_delete_on_close(fsp, delete_on_close,
6907 conn->session_info->security_token,
6908 conn->session_info->unix_token)) {
6909 return NT_STATUS_ACCESS_DENIED;
6911 return NT_STATUS_OK;
6914 /****************************************************************************
6915 Deal with SMB_FILE_POSITION_INFORMATION.
6916 ****************************************************************************/
6918 static NTSTATUS smb_file_position_information(connection_struct *conn,
6923 uint64_t position_information;
6925 if (total_data < 8) {
6926 return NT_STATUS_INVALID_PARAMETER;
6930 /* Ignore on pathname based set. */
6931 return NT_STATUS_OK;
6934 position_information = (uint64_t)IVAL(pdata,0);
6935 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6937 DEBUG(10,("smb_file_position_information: Set file position "
6938 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6939 (double)position_information));
6940 fsp->fh->position_information = position_information;
6941 return NT_STATUS_OK;
6944 /****************************************************************************
6945 Deal with SMB_FILE_MODE_INFORMATION.
6946 ****************************************************************************/
6948 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6954 if (total_data < 4) {
6955 return NT_STATUS_INVALID_PARAMETER;
6957 mode = IVAL(pdata,0);
6958 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6959 return NT_STATUS_INVALID_PARAMETER;
6961 return NT_STATUS_OK;
6964 /****************************************************************************
6965 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6966 ****************************************************************************/
6968 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6969 struct smb_request *req,
6972 const struct smb_filename *new_smb_fname)
6974 char *link_target = NULL;
6975 TALLOC_CTX *ctx = talloc_tos();
6978 /* Set a symbolic link. */
6979 /* Don't allow this if follow links is false. */
6981 if (total_data == 0) {
6982 return NT_STATUS_INVALID_PARAMETER;
6985 if (!lp_follow_symlinks(SNUM(conn))) {
6986 return NT_STATUS_ACCESS_DENIED;
6989 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6990 total_data, STR_TERMINATE);
6993 return NT_STATUS_INVALID_PARAMETER;
6996 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6997 new_smb_fname->base_name, link_target ));
6999 ret = SMB_VFS_SYMLINKAT(conn,
7004 return map_nt_error_from_unix(errno);
7007 return NT_STATUS_OK;
7010 /****************************************************************************
7011 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7012 ****************************************************************************/
7014 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7015 struct smb_request *req,
7016 const char *pdata, int total_data,
7017 struct smb_filename *smb_fname_new)
7019 char *oldname = NULL;
7020 struct smb_filename *smb_fname_old = NULL;
7021 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7022 TALLOC_CTX *ctx = talloc_tos();
7023 NTSTATUS status = NT_STATUS_OK;
7025 /* Set a hard link. */
7026 if (total_data == 0) {
7027 return NT_STATUS_INVALID_PARAMETER;
7030 if (req->posix_pathnames) {
7031 srvstr_get_path_posix(ctx,
7040 srvstr_get_path(ctx,
7049 if (!NT_STATUS_IS_OK(status)) {
7053 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7054 smb_fname_str_dbg(smb_fname_new), oldname));
7056 status = filename_convert(ctx,
7063 if (!NT_STATUS_IS_OK(status)) {
7067 return hardlink_internals(ctx, conn, req, false,
7068 smb_fname_old, smb_fname_new);
7071 /****************************************************************************
7072 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7073 ****************************************************************************/
7075 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7076 struct smb_request *req,
7080 struct smb_filename *smb_fname_src)
7084 char *newname = NULL;
7085 struct smb_filename *smb_fname_dst = NULL;
7086 const char *dst_original_lcomp = NULL;
7087 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7088 NTSTATUS status = NT_STATUS_OK;
7089 TALLOC_CTX *ctx = talloc_tos();
7092 return NT_STATUS_INVALID_HANDLE;
7095 if (total_data < 20) {
7096 return NT_STATUS_INVALID_PARAMETER;
7099 overwrite = (CVAL(pdata,0) ? True : False);
7100 len = IVAL(pdata,16);
7102 if (len > (total_data - 20) || (len == 0)) {
7103 return NT_STATUS_INVALID_PARAMETER;
7106 if (req->posix_pathnames) {
7107 srvstr_get_path_posix(ctx,
7116 srvstr_get_path(ctx,
7125 if (!NT_STATUS_IS_OK(status)) {
7129 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7132 status = filename_convert(ctx,
7139 if (!NT_STATUS_IS_OK(status)) {
7143 if (fsp->base_fsp) {
7144 /* newname must be a stream name. */
7145 if (newname[0] != ':') {
7146 return NT_STATUS_NOT_SUPPORTED;
7149 /* Create an smb_fname to call rename_internals_fsp() with. */
7150 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7151 fsp->base_fsp->fsp_name->base_name,
7154 fsp->base_fsp->fsp_name->flags);
7155 if (smb_fname_dst == NULL) {
7156 status = NT_STATUS_NO_MEMORY;
7162 * Set the original last component, since
7163 * rename_internals_fsp() requires it.
7165 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7169 if (dst_original_lcomp == NULL) {
7170 status = NT_STATUS_NO_MEMORY;
7174 DEBUG(10,("smb2_file_rename_information: "
7175 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7176 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7177 smb_fname_str_dbg(smb_fname_dst)));
7178 status = rename_internals_fsp(conn,
7182 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7186 TALLOC_FREE(smb_fname_dst);
7190 static NTSTATUS smb_file_link_information(connection_struct *conn,
7191 struct smb_request *req,
7195 struct smb_filename *smb_fname_src)
7199 char *newname = NULL;
7200 struct smb_filename *smb_fname_dst = NULL;
7201 NTSTATUS status = NT_STATUS_OK;
7202 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7203 TALLOC_CTX *ctx = talloc_tos();
7206 return NT_STATUS_INVALID_HANDLE;
7209 if (total_data < 20) {
7210 return NT_STATUS_INVALID_PARAMETER;
7213 overwrite = (CVAL(pdata,0) ? true : false);
7214 len = IVAL(pdata,16);
7216 if (len > (total_data - 20) || (len == 0)) {
7217 return NT_STATUS_INVALID_PARAMETER;
7220 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7221 srvstr_get_path_posix(ctx,
7229 ucf_flags |= UCF_POSIX_PATHNAMES;
7231 srvstr_get_path(ctx,
7240 if (!NT_STATUS_IS_OK(status)) {
7244 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7247 status = filename_convert(ctx,
7254 if (!NT_STATUS_IS_OK(status)) {
7258 if (fsp->base_fsp) {
7259 /* No stream names. */
7260 return NT_STATUS_NOT_SUPPORTED;
7263 DEBUG(10,("smb_file_link_information: "
7264 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7265 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7266 smb_fname_str_dbg(smb_fname_dst)));
7267 status = hardlink_internals(ctx,
7274 TALLOC_FREE(smb_fname_dst);
7278 /****************************************************************************
7279 Deal with SMB_FILE_RENAME_INFORMATION.
7280 ****************************************************************************/
7282 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7283 struct smb_request *req,
7287 struct smb_filename *smb_fname_src)
7292 char *newname = NULL;
7293 struct smb_filename *smb_fname_dst = NULL;
7294 const char *dst_original_lcomp = NULL;
7295 bool dest_has_wcard = False;
7296 NTSTATUS status = NT_STATUS_OK;
7298 TALLOC_CTX *ctx = talloc_tos();
7300 if (total_data < 13) {
7301 return NT_STATUS_INVALID_PARAMETER;
7304 overwrite = (CVAL(pdata,0) ? True : False);
7305 root_fid = IVAL(pdata,4);
7306 len = IVAL(pdata,8);
7308 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7309 return NT_STATUS_INVALID_PARAMETER;
7312 if (req->posix_pathnames) {
7313 srvstr_get_path_wcard_posix(ctx,
7323 srvstr_get_path_wcard(ctx,
7333 if (!NT_STATUS_IS_OK(status)) {
7337 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7340 /* Check the new name has no '/' characters. */
7341 if (strchr_m(newname, '/')) {
7342 return NT_STATUS_NOT_SUPPORTED;
7345 if (fsp && fsp->base_fsp) {
7346 /* newname must be a stream name. */
7347 if (newname[0] != ':') {
7348 return NT_STATUS_NOT_SUPPORTED;
7351 /* Create an smb_fname to call rename_internals_fsp() with. */
7352 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7353 fsp->base_fsp->fsp_name->base_name,
7356 fsp->base_fsp->fsp_name->flags);
7357 if (smb_fname_dst == NULL) {
7358 status = NT_STATUS_NO_MEMORY;
7363 * Get the original last component, since
7364 * rename_internals_fsp() requires it.
7366 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7370 if (dst_original_lcomp == NULL) {
7371 status = NT_STATUS_NO_MEMORY;
7377 * Build up an smb_fname_dst based on the filename passed in.
7378 * We basically just strip off the last component, and put on
7379 * the newname instead.
7381 char *base_name = NULL;
7382 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7384 if (dest_has_wcard) {
7385 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7388 /* newname must *not* be a stream name. */
7389 if (newname[0] == ':') {
7390 return NT_STATUS_NOT_SUPPORTED;
7394 * Strip off the last component (filename) of the path passed
7397 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7399 return NT_STATUS_NO_MEMORY;
7401 p = strrchr_m(base_name, '/');
7405 base_name = talloc_strdup(ctx, "");
7407 return NT_STATUS_NO_MEMORY;
7410 /* Append the new name. */
7411 base_name = talloc_asprintf_append(base_name,
7415 return NT_STATUS_NO_MEMORY;
7418 status = filename_convert(ctx,
7426 /* If an error we expect this to be
7427 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7429 if (!NT_STATUS_IS_OK(status)) {
7430 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7434 /* Create an smb_fname to call rename_internals_fsp() */
7435 smb_fname_dst = synthetic_smb_fname(ctx,
7439 smb_fname_src->flags);
7440 if (smb_fname_dst == NULL) {
7441 status = NT_STATUS_NO_MEMORY;
7445 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7449 if (dst_original_lcomp == NULL) {
7450 status = NT_STATUS_NO_MEMORY;
7456 DEBUG(10,("smb_file_rename_information: "
7457 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7458 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7459 smb_fname_str_dbg(smb_fname_dst)));
7460 status = rename_internals_fsp(conn,
7467 DEBUG(10,("smb_file_rename_information: "
7468 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7469 smb_fname_str_dbg(smb_fname_src),
7470 smb_fname_str_dbg(smb_fname_dst)));
7471 status = rename_internals(ctx,
7481 FILE_WRITE_ATTRIBUTES);
7484 TALLOC_FREE(smb_fname_dst);
7488 /****************************************************************************
7489 Deal with SMB_SET_POSIX_ACL.
7490 ****************************************************************************/
7492 #if defined(HAVE_POSIX_ACLS)
7493 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7494 struct smb_request *req,
7498 const struct smb_filename *smb_fname)
7500 uint16_t posix_acl_version;
7501 uint16_t num_file_acls;
7502 uint16_t num_def_acls;
7503 bool valid_file_acls = true;
7504 bool valid_def_acls = true;
7506 unsigned int size_needed;
7507 unsigned int total_data;
7508 bool close_fsp = false;
7510 if (total_data_in < 0) {
7511 status = NT_STATUS_INVALID_PARAMETER;
7515 total_data = total_data_in;
7517 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7518 status = NT_STATUS_INVALID_PARAMETER;
7521 posix_acl_version = SVAL(pdata,0);
7522 num_file_acls = SVAL(pdata,2);
7523 num_def_acls = SVAL(pdata,4);
7525 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7526 valid_file_acls = false;
7530 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7531 valid_def_acls = false;
7535 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7536 status = NT_STATUS_INVALID_PARAMETER;
7541 if (num_file_acls + num_def_acls < num_file_acls) {
7542 status = NT_STATUS_INVALID_PARAMETER;
7546 size_needed = num_file_acls + num_def_acls;
7549 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7550 * than UINT_MAX, so check by division.
7552 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7553 status = NT_STATUS_INVALID_PARAMETER;
7557 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7558 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7559 status = NT_STATUS_INVALID_PARAMETER;
7562 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7564 if (total_data < size_needed) {
7565 status = NT_STATUS_INVALID_PARAMETER;
7570 * Ensure we always operate on a file descriptor, not just
7574 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7576 SEC_STD_READ_CONTROL|
7577 FILE_READ_ATTRIBUTES|
7578 FILE_WRITE_ATTRIBUTES;
7580 status = get_posix_fsp(conn,
7586 if (!NT_STATUS_IS_OK(status)) {
7592 /* Here we know fsp != NULL */
7593 SMB_ASSERT(fsp != NULL);
7595 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7596 if (!NT_STATUS_IS_OK(status)) {
7600 /* If we have a default acl, this *must* be a directory. */
7601 if (valid_def_acls && !fsp->is_directory) {
7602 DBG_INFO("Can't set default acls on "
7603 "non-directory %s\n",
7605 return NT_STATUS_INVALID_HANDLE;
7608 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7609 "num_def_acls = %"PRIu16"\n",
7614 /* Move pdata to the start of the file ACL entries. */
7615 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7617 if (valid_file_acls) {
7618 status = set_unix_posix_acl(conn,
7622 if (!NT_STATUS_IS_OK(status)) {
7627 /* Move pdata to the start of the default ACL entries. */
7628 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7630 if (valid_def_acls) {
7631 status = set_unix_posix_default_acl(conn,
7635 if (!NT_STATUS_IS_OK(status)) {
7640 status = NT_STATUS_OK;
7645 (void)close_file(req, fsp, NORMAL_CLOSE);
7652 /****************************************************************************
7653 Deal with SMB_SET_POSIX_LOCK.
7654 ****************************************************************************/
7656 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7658 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7659 struct smb_request *req,
7664 struct tevent_req *subreq = NULL;
7665 struct smbd_lock_element *lck = NULL;
7669 bool blocking_lock = False;
7670 enum brl_type lock_type;
7672 NTSTATUS status = NT_STATUS_OK;
7674 if (fsp == NULL || fsp->fh->fd == -1) {
7675 return NT_STATUS_INVALID_HANDLE;
7678 if (total_data != POSIX_LOCK_DATA_SIZE) {
7679 return NT_STATUS_INVALID_PARAMETER;
7682 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7683 case POSIX_LOCK_TYPE_READ:
7684 lock_type = READ_LOCK;
7686 case POSIX_LOCK_TYPE_WRITE:
7687 /* Return the right POSIX-mappable error code for files opened read-only. */
7688 if (!fsp->fsp_flags.can_write) {
7689 return NT_STATUS_INVALID_HANDLE;
7691 lock_type = WRITE_LOCK;
7693 case POSIX_LOCK_TYPE_UNLOCK:
7694 lock_type = UNLOCK_LOCK;
7697 return NT_STATUS_INVALID_PARAMETER;
7700 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7701 case POSIX_LOCK_FLAG_NOWAIT:
7702 blocking_lock = false;
7704 case POSIX_LOCK_FLAG_WAIT:
7705 blocking_lock = true;
7708 return NT_STATUS_INVALID_PARAMETER;
7711 if (!lp_blocking_locks(SNUM(conn))) {
7712 blocking_lock = False;
7715 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7716 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7717 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7718 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7719 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7721 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7722 "count = %"PRIu64", offset = %"PRIu64"\n",
7724 (unsigned int)lock_type,
7729 if (lock_type == UNLOCK_LOCK) {
7730 struct smbd_lock_element l = {
7731 .req_guid = smbd_request_guid(req, 0),
7733 .brltype = UNLOCK_LOCK,
7737 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7741 lck = talloc(req, struct smbd_lock_element);
7743 return NT_STATUS_NO_MEMORY;
7746 *lck = (struct smbd_lock_element) {
7747 .req_guid = smbd_request_guid(req, 0),
7749 .brltype = lock_type,
7754 subreq = smbd_smb1_do_locks_send(
7759 blocking_lock ? UINT32_MAX : 0,
7760 true, /* large_offset */
7764 if (subreq == NULL) {
7766 return NT_STATUS_NO_MEMORY;
7768 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7769 return NT_STATUS_EVENT_PENDING;
7772 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7774 struct smb_request *req = NULL;
7778 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7781 status = smbd_smb1_do_locks_recv(subreq);
7782 TALLOC_FREE(subreq);
7784 if (NT_STATUS_IS_OK(status)) {
7785 char params[2] = {0};
7786 /* Fake up max_data_bytes here - we know it fits. */
7787 send_trans2_replies(
7797 reply_nterror(req, status);
7800 (char *)req->outbuf,
7803 IS_CONN_ENCRYPTED(req->conn),
7806 exit_server_cleanly("smb_set_posix_lock_done: "
7807 "srv_send_smb failed.");
7815 /****************************************************************************
7816 Deal with SMB_SET_FILE_BASIC_INFO.
7817 ****************************************************************************/
7819 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7823 const struct smb_filename *smb_fname)
7825 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7826 struct smb_file_time ft;
7827 uint32_t dosmode = 0;
7828 NTSTATUS status = NT_STATUS_OK;
7830 init_smb_file_time(&ft);
7832 if (total_data < 36) {
7833 return NT_STATUS_INVALID_PARAMETER;
7836 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7837 if (!NT_STATUS_IS_OK(status)) {
7841 /* Set the attributes */
7842 dosmode = IVAL(pdata,32);
7843 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7844 if (!NT_STATUS_IS_OK(status)) {
7849 ft.create_time = pull_long_date_full_timespec(pdata);
7852 ft.atime = pull_long_date_full_timespec(pdata+8);
7855 ft.mtime = pull_long_date_full_timespec(pdata+16);
7858 ft.ctime = pull_long_date_full_timespec(pdata+24);
7860 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7861 smb_fname_str_dbg(smb_fname)));
7863 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7864 if (!NT_STATUS_IS_OK(status)) {
7868 if (fsp != NULL && fsp->modified) {
7869 trigger_write_time_update_immediate(fsp);
7871 return NT_STATUS_OK;
7874 /****************************************************************************
7875 Deal with SMB_INFO_STANDARD.
7876 ****************************************************************************/
7878 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7882 const struct smb_filename *smb_fname)
7885 struct smb_file_time ft;
7887 init_smb_file_time(&ft);
7889 if (total_data < 12) {
7890 return NT_STATUS_INVALID_PARAMETER;
7894 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7896 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7898 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7900 DEBUG(10,("smb_set_info_standard: file %s\n",
7901 smb_fname_str_dbg(smb_fname)));
7903 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7904 if (!NT_STATUS_IS_OK(status)) {
7908 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7909 if (!NT_STATUS_IS_OK(status)) {
7913 if (fsp != NULL && fsp->modified) {
7914 trigger_write_time_update_immediate(fsp);
7916 return NT_STATUS_OK;
7919 /****************************************************************************
7920 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7921 ****************************************************************************/
7923 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7924 struct smb_request *req,
7928 struct smb_filename *smb_fname)
7930 uint64_t allocation_size = 0;
7931 NTSTATUS status = NT_STATUS_OK;
7932 files_struct *new_fsp = NULL;
7934 if (!VALID_STAT(smb_fname->st)) {
7935 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7938 if (total_data < 8) {
7939 return NT_STATUS_INVALID_PARAMETER;
7942 allocation_size = (uint64_t)IVAL(pdata,0);
7943 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7944 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7945 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7946 (double)allocation_size));
7948 if (allocation_size) {
7949 allocation_size = smb_roundup(conn, allocation_size);
7952 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7953 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7954 (double)allocation_size));
7956 if (fsp && fsp->fh->fd != -1) {
7957 /* Open file handle. */
7958 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7959 return NT_STATUS_ACCESS_DENIED;
7962 /* Only change if needed. */
7963 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7964 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7965 return map_nt_error_from_unix(errno);
7968 /* But always update the time. */
7970 * This is equivalent to a write. Ensure it's seen immediately
7971 * if there are no pending writes.
7973 trigger_write_time_update_immediate(fsp);
7974 return NT_STATUS_OK;
7977 /* Pathname or stat or directory file. */
7978 status = SMB_VFS_CREATE_FILE(
7981 0, /* root_dir_fid */
7982 smb_fname, /* fname */
7983 FILE_WRITE_DATA, /* access_mask */
7984 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7986 FILE_OPEN, /* create_disposition*/
7987 0, /* create_options */
7988 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7989 0, /* oplock_request */
7991 0, /* allocation_size */
7992 0, /* private_flags */
7995 &new_fsp, /* result */
7997 NULL, NULL); /* create context */
7999 if (!NT_STATUS_IS_OK(status)) {
8000 /* NB. We check for open_was_deferred in the caller. */
8004 /* Only change if needed. */
8005 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8006 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8007 status = map_nt_error_from_unix(errno);
8008 close_file(req, new_fsp, NORMAL_CLOSE);
8013 /* Changing the allocation size should set the last mod time. */
8015 * This is equivalent to a write. Ensure it's seen immediately
8016 * if there are no pending writes.
8018 trigger_write_time_update_immediate(new_fsp);
8019 close_file(req, new_fsp, NORMAL_CLOSE);
8020 return NT_STATUS_OK;
8023 /****************************************************************************
8024 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8025 ****************************************************************************/
8027 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8028 struct smb_request *req,
8032 const struct smb_filename *smb_fname,
8033 bool fail_after_createfile)
8037 if (total_data < 8) {
8038 return NT_STATUS_INVALID_PARAMETER;
8041 size = IVAL(pdata,0);
8042 size |= (((off_t)IVAL(pdata,4)) << 32);
8043 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8044 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8047 return smb_set_file_size(conn, req,
8052 fail_after_createfile);
8055 /****************************************************************************
8056 Allow a UNIX info mknod.
8057 ****************************************************************************/
8059 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8062 const struct smb_filename *smb_fname)
8064 uint32_t file_type = IVAL(pdata,56);
8065 #if defined(HAVE_MAKEDEV)
8066 uint32_t dev_major = IVAL(pdata,60);
8067 uint32_t dev_minor = IVAL(pdata,68);
8069 SMB_DEV_T dev = (SMB_DEV_T)0;
8070 uint32_t raw_unixmode = IVAL(pdata,84);
8075 if (total_data < 100) {
8076 return NT_STATUS_INVALID_PARAMETER;
8079 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8080 PERM_NEW_FILE, &unixmode);
8081 if (!NT_STATUS_IS_OK(status)) {
8085 #if defined(HAVE_MAKEDEV)
8086 dev = makedev(dev_major, dev_minor);
8089 switch (file_type) {
8090 /* We can't create other objects here. */
8091 case UNIX_TYPE_FILE:
8093 case UNIX_TYPE_SYMLINK:
8094 return NT_STATUS_ACCESS_DENIED;
8095 #if defined(S_IFIFO)
8096 case UNIX_TYPE_FIFO:
8097 unixmode |= S_IFIFO;
8100 #if defined(S_IFSOCK)
8101 case UNIX_TYPE_SOCKET:
8102 unixmode |= S_IFSOCK;
8105 #if defined(S_IFCHR)
8106 case UNIX_TYPE_CHARDEV:
8107 /* This is only allowed for root. */
8108 if (get_current_uid(conn) != sec_initial_uid()) {
8109 return NT_STATUS_ACCESS_DENIED;
8111 unixmode |= S_IFCHR;
8114 #if defined(S_IFBLK)
8115 case UNIX_TYPE_BLKDEV:
8116 if (get_current_uid(conn) != sec_initial_uid()) {
8117 return NT_STATUS_ACCESS_DENIED;
8119 unixmode |= S_IFBLK;
8123 return NT_STATUS_INVALID_PARAMETER;
8126 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8127 "%.0f mode 0%o for file %s\n", (double)dev,
8128 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8130 /* Ok - do the mknod. */
8131 ret = SMB_VFS_MKNODAT(conn,
8138 return map_nt_error_from_unix(errno);
8141 /* If any of the other "set" calls fail we
8142 * don't want to end up with a half-constructed mknod.
8145 if (lp_inherit_permissions(SNUM(conn))) {
8147 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8149 return NT_STATUS_NO_MEMORY;
8151 inherit_access_posix_acl(conn, parent, smb_fname,
8153 TALLOC_FREE(parent);
8156 return NT_STATUS_OK;
8159 /****************************************************************************
8160 Deal with SMB_SET_FILE_UNIX_BASIC.
8161 ****************************************************************************/
8163 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8164 struct smb_request *req,
8168 const struct smb_filename *smb_fname)
8170 struct smb_file_time ft;
8171 uint32_t raw_unixmode;
8174 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8175 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8176 NTSTATUS status = NT_STATUS_OK;
8177 enum perm_type ptype;
8178 files_struct *all_fsps = NULL;
8179 bool modify_mtime = true;
8181 SMB_STRUCT_STAT sbuf;
8183 init_smb_file_time(&ft);
8185 if (total_data < 100) {
8186 return NT_STATUS_INVALID_PARAMETER;
8189 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8190 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8191 size=IVAL(pdata,0); /* first 8 Bytes are size */
8192 size |= (((off_t)IVAL(pdata,4)) << 32);
8195 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8196 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8197 set_owner = (uid_t)IVAL(pdata,40);
8198 set_grp = (gid_t)IVAL(pdata,48);
8199 raw_unixmode = IVAL(pdata,84);
8201 if (VALID_STAT(smb_fname->st)) {
8202 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8203 ptype = PERM_EXISTING_DIR;
8205 ptype = PERM_EXISTING_FILE;
8208 ptype = PERM_NEW_FILE;
8211 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8213 if (!NT_STATUS_IS_OK(status)) {
8217 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8218 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8219 smb_fname_str_dbg(smb_fname), (double)size,
8220 (unsigned int)set_owner, (unsigned int)set_grp,
8221 (int)raw_unixmode));
8223 sbuf = smb_fname->st;
8225 if (!VALID_STAT(sbuf)) {
8227 * The only valid use of this is to create character and block
8228 * devices, and named pipes. This is deprecated (IMHO) and
8229 * a new info level should be used for mknod. JRA.
8232 return smb_unix_mknod(conn,
8239 /* Horrible backwards compatibility hack as an old server bug
8240 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8244 size = get_file_size_stat(&sbuf);
8249 * Deal with the UNIX specific mode set.
8252 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8255 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8256 "setting mode 0%o for file %s\n",
8257 (unsigned int)unixmode,
8258 smb_fname_str_dbg(smb_fname)));
8259 if (fsp && fsp->fh->fd != -1) {
8260 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8262 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8265 return map_nt_error_from_unix(errno);
8270 * Deal with the UNIX specific uid set.
8273 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8274 (sbuf.st_ex_uid != set_owner)) {
8277 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8278 "changing owner %u for path %s\n",
8279 (unsigned int)set_owner,
8280 smb_fname_str_dbg(smb_fname)));
8282 if (fsp && fsp->fh->fd != -1) {
8283 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8286 * UNIX extensions calls must always operate
8289 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8290 set_owner, (gid_t)-1);
8294 status = map_nt_error_from_unix(errno);
8300 * Deal with the UNIX specific gid set.
8303 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8304 (sbuf.st_ex_gid != set_grp)) {
8307 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8308 "changing group %u for file %s\n",
8309 (unsigned int)set_grp,
8310 smb_fname_str_dbg(smb_fname)));
8311 if (fsp && fsp->fh->fd != -1) {
8312 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8315 * UNIX extensions calls must always operate
8318 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8322 status = map_nt_error_from_unix(errno);
8327 /* Deal with any size changes. */
8329 if (S_ISREG(sbuf.st_ex_mode)) {
8330 status = smb_set_file_size(conn, req,
8336 if (!NT_STATUS_IS_OK(status)) {
8341 /* Deal with any time changes. */
8342 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8343 /* No change, don't cancel anything. */
8347 id = vfs_file_id_from_sbuf(conn, &sbuf);
8348 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8349 all_fsps = file_find_di_next(all_fsps)) {
8351 * We're setting the time explicitly for UNIX.
8352 * Cancel any pending changes over all handles.
8354 all_fsps->fsp_flags.update_write_time_on_close = false;
8355 TALLOC_FREE(all_fsps->update_write_time_event);
8359 * Override the "setting_write_time"
8360 * parameter here as it almost does what
8361 * we need. Just remember if we modified
8362 * mtime and send the notify ourselves.
8364 if (is_omit_timespec(&ft.mtime)) {
8365 modify_mtime = false;
8368 status = smb_set_file_time(conn,
8374 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8375 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8380 /****************************************************************************
8381 Deal with SMB_SET_FILE_UNIX_INFO2.
8382 ****************************************************************************/
8384 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8385 struct smb_request *req,
8389 const struct smb_filename *smb_fname)
8392 uint32_t smb_fflags;
8395 if (total_data < 116) {
8396 return NT_STATUS_INVALID_PARAMETER;
8399 /* Start by setting all the fields that are common between UNIX_BASIC
8402 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8404 if (!NT_STATUS_IS_OK(status)) {
8408 smb_fflags = IVAL(pdata, 108);
8409 smb_fmask = IVAL(pdata, 112);
8411 /* NB: We should only attempt to alter the file flags if the client
8412 * sends a non-zero mask.
8414 if (smb_fmask != 0) {
8415 int stat_fflags = 0;
8417 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8418 smb_fmask, &stat_fflags)) {
8419 /* Client asked to alter a flag we don't understand. */
8420 return NT_STATUS_INVALID_PARAMETER;
8423 if (fsp && fsp->fh->fd != -1) {
8424 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8425 return NT_STATUS_NOT_SUPPORTED;
8427 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8428 stat_fflags) != 0) {
8429 return map_nt_error_from_unix(errno);
8434 /* XXX: need to add support for changing the create_time here. You
8435 * can do this for paths on Darwin with setattrlist(2). The right way
8436 * to hook this up is probably by extending the VFS utimes interface.
8439 return NT_STATUS_OK;
8442 /****************************************************************************
8443 Create a directory with POSIX semantics.
8444 ****************************************************************************/
8446 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8447 struct smb_request *req,
8450 struct smb_filename *smb_fname,
8451 int *pdata_return_size)
8453 NTSTATUS status = NT_STATUS_OK;
8454 uint32_t raw_unixmode = 0;
8455 mode_t unixmode = (mode_t)0;
8456 files_struct *fsp = NULL;
8457 uint16_t info_level_return = 0;
8459 char *pdata = *ppdata;
8460 struct smb2_create_blobs *posx = NULL;
8462 if (total_data < 18) {
8463 return NT_STATUS_INVALID_PARAMETER;
8466 raw_unixmode = IVAL(pdata,8);
8467 /* Next 4 bytes are not yet defined. */
8469 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8470 PERM_NEW_DIR, &unixmode);
8471 if (!NT_STATUS_IS_OK(status)) {
8475 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8476 if (!NT_STATUS_IS_OK(status)) {
8477 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8482 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8483 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8485 status = SMB_VFS_CREATE_FILE(
8488 0, /* root_dir_fid */
8489 smb_fname, /* fname */
8490 FILE_READ_ATTRIBUTES, /* access_mask */
8491 FILE_SHARE_NONE, /* share_access */
8492 FILE_CREATE, /* create_disposition*/
8493 FILE_DIRECTORY_FILE, /* create_options */
8494 0, /* file_attributes */
8495 0, /* oplock_request */
8497 0, /* allocation_size */
8498 0, /* private_flags */
8503 posx, /* in_context_blobs */
8504 NULL); /* out_context_blobs */
8508 if (NT_STATUS_IS_OK(status)) {
8509 close_file(req, fsp, NORMAL_CLOSE);
8512 info_level_return = SVAL(pdata,16);
8514 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8515 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8516 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8517 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8519 *pdata_return_size = 12;
8522 /* Realloc the data size */
8523 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8524 if (*ppdata == NULL) {
8525 *pdata_return_size = 0;
8526 return NT_STATUS_NO_MEMORY;
8530 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8531 SSVAL(pdata,2,0); /* No fnum. */
8532 SIVAL(pdata,4,info); /* Was directory created. */
8534 switch (info_level_return) {
8535 case SMB_QUERY_FILE_UNIX_BASIC:
8536 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8537 SSVAL(pdata,10,0); /* Padding. */
8538 store_file_unix_basic(conn, pdata + 12, fsp,
8541 case SMB_QUERY_FILE_UNIX_INFO2:
8542 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8543 SSVAL(pdata,10,0); /* Padding. */
8544 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8548 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8549 SSVAL(pdata,10,0); /* Padding. */
8556 /****************************************************************************
8557 Open/Create a file with POSIX semantics.
8558 ****************************************************************************/
8560 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8561 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8563 static NTSTATUS smb_posix_open(connection_struct *conn,
8564 struct smb_request *req,
8567 struct smb_filename *smb_fname,
8568 int *pdata_return_size)
8570 bool extended_oplock_granted = False;
8571 char *pdata = *ppdata;
8573 uint32_t wire_open_mode = 0;
8574 uint32_t raw_unixmode = 0;
8575 uint32_t attributes = 0;
8576 uint32_t create_disp = 0;
8577 uint32_t access_mask = 0;
8578 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8579 NTSTATUS status = NT_STATUS_OK;
8580 mode_t unixmode = (mode_t)0;
8581 files_struct *fsp = NULL;
8582 int oplock_request = 0;
8584 uint16_t info_level_return = 0;
8585 struct smb2_create_blobs *posx = NULL;
8587 if (total_data < 18) {
8588 return NT_STATUS_INVALID_PARAMETER;
8591 flags = IVAL(pdata,0);
8592 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8593 if (oplock_request) {
8594 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8597 wire_open_mode = IVAL(pdata,4);
8599 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8600 return smb_posix_mkdir(conn, req,
8607 switch (wire_open_mode & SMB_ACCMODE) {
8609 access_mask = SMB_O_RDONLY_MAPPING;
8612 access_mask = SMB_O_WRONLY_MAPPING;
8615 access_mask = (SMB_O_RDONLY_MAPPING|
8616 SMB_O_WRONLY_MAPPING);
8619 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8620 (unsigned int)wire_open_mode ));
8621 return NT_STATUS_INVALID_PARAMETER;
8624 wire_open_mode &= ~SMB_ACCMODE;
8626 /* First take care of O_CREAT|O_EXCL interactions. */
8627 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8628 case (SMB_O_CREAT | SMB_O_EXCL):
8629 /* File exists fail. File not exist create. */
8630 create_disp = FILE_CREATE;
8633 /* File exists open. File not exist create. */
8634 create_disp = FILE_OPEN_IF;
8637 /* O_EXCL on its own without O_CREAT is undefined.
8638 We deliberately ignore it as some versions of
8639 Linux CIFSFS can send a bare O_EXCL on the
8640 wire which other filesystems in the kernel
8641 ignore. See bug 9519 for details. */
8646 /* File exists open. File not exist fail. */
8647 create_disp = FILE_OPEN;
8650 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8651 (unsigned int)wire_open_mode ));
8652 return NT_STATUS_INVALID_PARAMETER;
8655 /* Next factor in the effects of O_TRUNC. */
8656 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8658 if (wire_open_mode & SMB_O_TRUNC) {
8659 switch (create_disp) {
8661 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8662 /* Leave create_disp alone as
8663 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8665 /* File exists fail. File not exist create. */
8668 /* SMB_O_CREAT | SMB_O_TRUNC */
8669 /* File exists overwrite. File not exist create. */
8670 create_disp = FILE_OVERWRITE_IF;
8674 /* File exists overwrite. File not exist fail. */
8675 create_disp = FILE_OVERWRITE;
8678 /* Cannot get here. */
8679 smb_panic("smb_posix_open: logic error");
8680 return NT_STATUS_INVALID_PARAMETER;
8684 raw_unixmode = IVAL(pdata,8);
8685 /* Next 4 bytes are not yet defined. */
8687 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8688 (VALID_STAT(smb_fname->st) ?
8689 PERM_EXISTING_FILE : PERM_NEW_FILE),
8692 if (!NT_STATUS_IS_OK(status)) {
8696 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8697 if (!NT_STATUS_IS_OK(status)) {
8698 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8703 if (wire_open_mode & SMB_O_SYNC) {
8704 create_options |= FILE_WRITE_THROUGH;
8706 if (wire_open_mode & SMB_O_APPEND) {
8707 access_mask |= FILE_APPEND_DATA;
8709 if (wire_open_mode & SMB_O_DIRECT) {
8710 attributes |= FILE_FLAG_NO_BUFFERING;
8713 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8714 VALID_STAT_OF_DIR(smb_fname->st)) {
8715 if (access_mask != SMB_O_RDONLY_MAPPING) {
8716 return NT_STATUS_FILE_IS_A_DIRECTORY;
8718 create_options &= ~FILE_NON_DIRECTORY_FILE;
8719 create_options |= FILE_DIRECTORY_FILE;
8722 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8723 smb_fname_str_dbg(smb_fname),
8724 (unsigned int)wire_open_mode,
8725 (unsigned int)unixmode ));
8727 status = SMB_VFS_CREATE_FILE(
8730 0, /* root_dir_fid */
8731 smb_fname, /* fname */
8732 access_mask, /* access_mask */
8733 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8735 create_disp, /* create_disposition*/
8736 create_options, /* create_options */
8737 attributes, /* file_attributes */
8738 oplock_request, /* oplock_request */
8740 0, /* allocation_size */
8741 0, /* private_flags */
8746 posx, /* in_context_blobs */
8747 NULL); /* out_context_blobs */
8751 if (!NT_STATUS_IS_OK(status)) {
8755 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8756 extended_oplock_granted = True;
8759 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8760 extended_oplock_granted = True;
8763 info_level_return = SVAL(pdata,16);
8765 /* Allocate the correct return size. */
8767 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8768 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8769 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8770 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8772 *pdata_return_size = 12;
8775 /* Realloc the data size */
8776 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8777 if (*ppdata == NULL) {
8778 close_file(req, fsp, ERROR_CLOSE);
8779 *pdata_return_size = 0;
8780 return NT_STATUS_NO_MEMORY;
8784 if (extended_oplock_granted) {
8785 if (flags & REQUEST_BATCH_OPLOCK) {
8786 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8788 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8790 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8791 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8793 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8796 SSVAL(pdata,2,fsp->fnum);
8797 SIVAL(pdata,4,info); /* Was file created etc. */
8799 switch (info_level_return) {
8800 case SMB_QUERY_FILE_UNIX_BASIC:
8801 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8802 SSVAL(pdata,10,0); /* padding. */
8803 store_file_unix_basic(conn, pdata + 12, fsp,
8806 case SMB_QUERY_FILE_UNIX_INFO2:
8807 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8808 SSVAL(pdata,10,0); /* padding. */
8809 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8813 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8814 SSVAL(pdata,10,0); /* padding. */
8817 return NT_STATUS_OK;
8820 /****************************************************************************
8821 Delete a file with POSIX semantics.
8822 ****************************************************************************/
8824 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8825 struct smb_request *req,
8828 struct smb_filename *smb_fname)
8830 NTSTATUS status = NT_STATUS_OK;
8831 files_struct *fsp = NULL;
8835 int create_options = 0;
8836 struct share_mode_lock *lck = NULL;
8837 bool other_nonposix_opens;
8838 struct smb2_create_blobs *posx = NULL;
8840 if (total_data < 2) {
8841 return NT_STATUS_INVALID_PARAMETER;
8844 flags = SVAL(pdata,0);
8846 if (!VALID_STAT(smb_fname->st)) {
8847 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8850 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8851 !VALID_STAT_OF_DIR(smb_fname->st)) {
8852 return NT_STATUS_NOT_A_DIRECTORY;
8855 DEBUG(10,("smb_posix_unlink: %s %s\n",
8856 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8857 smb_fname_str_dbg(smb_fname)));
8859 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8860 create_options |= FILE_DIRECTORY_FILE;
8863 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8864 if (!NT_STATUS_IS_OK(status)) {
8865 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8870 status = SMB_VFS_CREATE_FILE(
8873 0, /* root_dir_fid */
8874 smb_fname, /* fname */
8875 DELETE_ACCESS, /* access_mask */
8876 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8878 FILE_OPEN, /* create_disposition*/
8879 create_options, /* create_options */
8880 0, /* file_attributes */
8881 0, /* oplock_request */
8883 0, /* allocation_size */
8884 0, /* private_flags */
8889 posx, /* in_context_blobs */
8890 NULL); /* out_context_blobs */
8894 if (!NT_STATUS_IS_OK(status)) {
8899 * Don't lie to client. If we can't really delete due to
8900 * non-POSIX opens return SHARING_VIOLATION.
8903 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8905 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8906 "lock for file %s\n", fsp_str_dbg(fsp)));
8907 close_file(req, fsp, NORMAL_CLOSE);
8908 return NT_STATUS_INVALID_PARAMETER;
8911 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8912 if (other_nonposix_opens) {
8913 /* Fail with sharing violation. */
8915 close_file(req, fsp, NORMAL_CLOSE);
8916 return NT_STATUS_SHARING_VIOLATION;
8920 * Set the delete on close.
8922 status = smb_set_file_disposition_info(conn,
8930 if (!NT_STATUS_IS_OK(status)) {
8931 close_file(req, fsp, NORMAL_CLOSE);
8934 return close_file(req, fsp, NORMAL_CLOSE);
8937 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8938 struct smb_request *req,
8939 TALLOC_CTX *mem_ctx,
8940 uint16_t info_level,
8942 struct smb_filename *smb_fname,
8943 char **ppdata, int total_data,
8946 char *pdata = *ppdata;
8947 NTSTATUS status = NT_STATUS_OK;
8948 int data_return_size = 0;
8952 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8953 return NT_STATUS_INVALID_LEVEL;
8956 if (!CAN_WRITE(conn)) {
8957 /* Allow POSIX opens. The open path will deny
8958 * any non-readonly opens. */
8959 if (info_level != SMB_POSIX_PATH_OPEN) {
8960 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8964 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8965 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8967 info_level, total_data));
8969 switch (info_level) {
8971 case SMB_INFO_STANDARD:
8973 status = smb_set_info_standard(conn,
8981 case SMB_INFO_SET_EA:
8983 status = smb_info_set_ea(conn,
8991 case SMB_SET_FILE_BASIC_INFO:
8992 case SMB_FILE_BASIC_INFORMATION:
8994 status = smb_set_file_basic_info(conn,
9002 case SMB_FILE_ALLOCATION_INFORMATION:
9003 case SMB_SET_FILE_ALLOCATION_INFO:
9005 status = smb_set_file_allocation_info(conn, req,
9013 case SMB_FILE_END_OF_FILE_INFORMATION:
9014 case SMB_SET_FILE_END_OF_FILE_INFO:
9017 * XP/Win7 both fail after the createfile with
9018 * SMB_SET_FILE_END_OF_FILE_INFO but not
9019 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9020 * The level is known here, so pass it down
9024 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9026 status = smb_set_file_end_of_file_info(conn, req,
9035 case SMB_FILE_DISPOSITION_INFORMATION:
9036 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9039 /* JRA - We used to just ignore this on a path ?
9040 * Shouldn't this be invalid level on a pathname
9043 if (tran_call != TRANSACT2_SETFILEINFO) {
9044 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9047 status = smb_set_file_disposition_info(conn,
9055 case SMB_FILE_POSITION_INFORMATION:
9057 status = smb_file_position_information(conn,
9064 case SMB_FILE_FULL_EA_INFORMATION:
9066 status = smb_set_file_full_ea_info(conn,
9073 /* From tridge Samba4 :
9074 * MODE_INFORMATION in setfileinfo (I have no
9075 * idea what "mode information" on a file is - it takes a value of 0,
9076 * 2, 4 or 6. What could it be?).
9079 case SMB_FILE_MODE_INFORMATION:
9081 status = smb_file_mode_information(conn,
9087 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9088 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9089 case SMB_FILE_SHORT_NAME_INFORMATION:
9090 return NT_STATUS_NOT_SUPPORTED;
9093 * CIFS UNIX extensions.
9096 case SMB_SET_FILE_UNIX_BASIC:
9098 status = smb_set_file_unix_basic(conn, req,
9106 case SMB_SET_FILE_UNIX_INFO2:
9108 status = smb_set_file_unix_info2(conn, req,
9116 case SMB_SET_FILE_UNIX_LINK:
9119 /* We must have a pathname for this. */
9120 return NT_STATUS_INVALID_LEVEL;
9122 status = smb_set_file_unix_link(conn, req, pdata,
9123 total_data, smb_fname);
9127 case SMB_SET_FILE_UNIX_HLINK:
9130 /* We must have a pathname for this. */
9131 return NT_STATUS_INVALID_LEVEL;
9133 status = smb_set_file_unix_hlink(conn, req,
9139 case SMB_FILE_RENAME_INFORMATION:
9141 status = smb_file_rename_information(conn, req,
9147 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9149 /* SMB2 rename information. */
9150 status = smb2_file_rename_information(conn, req,
9156 case SMB_FILE_LINK_INFORMATION:
9158 status = smb_file_link_information(conn, req,
9164 #if defined(HAVE_POSIX_ACLS)
9165 case SMB_SET_POSIX_ACL:
9167 status = smb_set_posix_acl(conn,
9177 case SMB_SET_POSIX_LOCK:
9180 return NT_STATUS_INVALID_LEVEL;
9182 status = smb_set_posix_lock(conn, req,
9183 pdata, total_data, fsp);
9187 case SMB_POSIX_PATH_OPEN:
9190 /* We must have a pathname for this. */
9191 return NT_STATUS_INVALID_LEVEL;
9194 status = smb_posix_open(conn, req,
9202 case SMB_POSIX_PATH_UNLINK:
9205 /* We must have a pathname for this. */
9206 return NT_STATUS_INVALID_LEVEL;
9209 status = smb_posix_unlink(conn, req,
9217 return NT_STATUS_INVALID_LEVEL;
9220 if (!NT_STATUS_IS_OK(status)) {
9224 *ret_data_size = data_return_size;
9225 return NT_STATUS_OK;
9228 /****************************************************************************
9229 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9230 ****************************************************************************/
9232 static void call_trans2setfilepathinfo(connection_struct *conn,
9233 struct smb_request *req,
9234 unsigned int tran_call,
9235 char **pparams, int total_params,
9236 char **ppdata, int total_data,
9237 unsigned int max_data_bytes)
9239 char *params = *pparams;
9240 char *pdata = *ppdata;
9241 uint16_t info_level;
9242 struct smb_filename *smb_fname = NULL;
9243 files_struct *fsp = NULL;
9244 NTSTATUS status = NT_STATUS_OK;
9245 int data_return_size = 0;
9248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9252 if (tran_call == TRANSACT2_SETFILEINFO) {
9253 if (total_params < 4) {
9254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9258 fsp = file_fsp(req, SVAL(params,0));
9259 /* Basic check for non-null fsp. */
9260 if (!check_fsp_open(conn, req, fsp)) {
9263 info_level = SVAL(params,2);
9265 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9266 if (smb_fname == NULL) {
9267 reply_nterror(req, NT_STATUS_NO_MEMORY);
9271 if(fsp->fh->fd == -1) {
9273 * This is actually a SETFILEINFO on a directory
9274 * handle (returned from an NT SMB). NT5.0 seems
9275 * to do this call. JRA.
9277 if (INFO_LEVEL_IS_UNIX(info_level)) {
9278 /* Always do lstat for UNIX calls. */
9279 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9280 DEBUG(3,("call_trans2setfilepathinfo: "
9281 "SMB_VFS_LSTAT of %s failed "
9283 smb_fname_str_dbg(smb_fname),
9285 reply_nterror(req, map_nt_error_from_unix(errno));
9289 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9290 DEBUG(3,("call_trans2setfilepathinfo: "
9291 "fileinfo of %s failed (%s)\n",
9292 smb_fname_str_dbg(smb_fname),
9294 reply_nterror(req, map_nt_error_from_unix(errno));
9298 } else if (fsp->print_file) {
9300 * Doing a DELETE_ON_CLOSE should cancel a print job.
9302 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9303 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9305 DEBUG(3,("call_trans2setfilepathinfo: "
9306 "Cancelling print job (%s)\n",
9310 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9316 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9321 * Original code - this is an open file.
9323 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9324 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9325 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9327 reply_nterror(req, map_nt_error_from_unix(errno));
9333 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9336 if (total_params < 7) {
9337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9341 info_level = SVAL(params,0);
9342 if (req->posix_pathnames) {
9343 srvstr_get_path_posix(req,
9352 srvstr_get_path(req,
9361 if (!NT_STATUS_IS_OK(status)) {
9362 reply_nterror(req, status);
9366 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9367 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9368 info_level == SMB_FILE_RENAME_INFORMATION ||
9369 info_level == SMB_POSIX_PATH_OPEN ||
9370 info_level == SMB_POSIX_PATH_UNLINK) {
9371 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9374 status = filename_convert(req, conn,
9380 if (!NT_STATUS_IS_OK(status)) {
9381 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9382 reply_botherror(req,
9383 NT_STATUS_PATH_NOT_COVERED,
9384 ERRSRV, ERRbadpath);
9387 reply_nterror(req, status);
9391 if (INFO_LEVEL_IS_UNIX(info_level)) {
9393 * For CIFS UNIX extensions the target name may not exist.
9396 /* Always do lstat for UNIX calls. */
9397 SMB_VFS_LSTAT(conn, smb_fname);
9399 } else if (!VALID_STAT(smb_fname->st) &&
9400 SMB_VFS_STAT(conn, smb_fname)) {
9401 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9403 smb_fname_str_dbg(smb_fname),
9405 reply_nterror(req, map_nt_error_from_unix(errno));
9410 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9411 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9413 info_level,total_data));
9415 /* Realloc the parameter size */
9416 *pparams = (char *)SMB_REALLOC(*pparams,2);
9417 if (*pparams == NULL) {
9418 reply_nterror(req, NT_STATUS_NO_MEMORY);
9425 status = smbd_do_setfilepathinfo(conn, req, req,
9431 if (!NT_STATUS_IS_OK(status)) {
9432 if (open_was_deferred(req->xconn, req->mid)) {
9433 /* We have re-scheduled this call. */
9436 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9437 bool ok = defer_smb1_sharing_violation(req);
9442 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9443 /* We have re-scheduled this call. */
9446 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9447 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9448 ERRSRV, ERRbadpath);
9451 if (info_level == SMB_POSIX_PATH_OPEN) {
9452 reply_openerror(req, status);
9457 * Invalid EA name needs to return 2 param bytes,
9458 * not a zero-length error packet.
9460 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9461 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9464 reply_nterror(req, status);
9469 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9475 /****************************************************************************
9476 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9477 ****************************************************************************/
9479 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9480 char **pparams, int total_params,
9481 char **ppdata, int total_data,
9482 unsigned int max_data_bytes)
9484 struct smb_filename *smb_dname = NULL;
9485 char *params = *pparams;
9486 char *pdata = *ppdata;
9487 char *directory = NULL;
9488 NTSTATUS status = NT_STATUS_OK;
9489 struct ea_list *ea_list = NULL;
9490 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9491 TALLOC_CTX *ctx = talloc_tos();
9493 if (!CAN_WRITE(conn)) {
9494 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9498 if (total_params < 5) {
9499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9503 if (req->posix_pathnames) {
9504 srvstr_get_path_posix(ctx,
9513 srvstr_get_path(ctx,
9522 if (!NT_STATUS_IS_OK(status)) {
9523 reply_nterror(req, status);
9527 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9529 status = filename_convert(ctx,
9537 if (!NT_STATUS_IS_OK(status)) {
9538 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9539 reply_botherror(req,
9540 NT_STATUS_PATH_NOT_COVERED,
9541 ERRSRV, ERRbadpath);
9544 reply_nterror(req, status);
9549 * OS/2 workplace shell seems to send SET_EA requests of "null"
9550 * length (4 bytes containing IVAL 4).
9551 * They seem to have no effect. Bug #3212. JRA.
9554 if (total_data && (total_data != 4)) {
9555 /* Any data in this call is an EA list. */
9556 if (total_data < 10) {
9557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9561 if (IVAL(pdata,0) > total_data) {
9562 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9563 IVAL(pdata,0), (unsigned int)total_data));
9564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9568 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9575 if (!lp_ea_support(SNUM(conn))) {
9576 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9580 /* If total_data == 4 Windows doesn't care what values
9581 * are placed in that field, it just ignores them.
9582 * The System i QNTC IBM SMB client puts bad values here,
9583 * so ignore them. */
9585 status = create_directory(conn, req, smb_dname);
9587 if (!NT_STATUS_IS_OK(status)) {
9588 reply_nterror(req, status);
9592 /* Try and set any given EA. */
9594 status = set_ea(conn, NULL, smb_dname, ea_list);
9595 if (!NT_STATUS_IS_OK(status)) {
9596 reply_nterror(req, status);
9601 /* Realloc the parameter and data sizes */
9602 *pparams = (char *)SMB_REALLOC(*pparams,2);
9603 if(*pparams == NULL) {
9604 reply_nterror(req, NT_STATUS_NO_MEMORY);
9611 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9614 TALLOC_FREE(smb_dname);
9618 /****************************************************************************
9619 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9620 We don't actually do this - we just send a null response.
9621 ****************************************************************************/
9623 static void call_trans2findnotifyfirst(connection_struct *conn,
9624 struct smb_request *req,
9625 char **pparams, int total_params,
9626 char **ppdata, int total_data,
9627 unsigned int max_data_bytes)
9629 char *params = *pparams;
9630 uint16_t info_level;
9632 if (total_params < 6) {
9633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9637 info_level = SVAL(params,4);
9638 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9640 switch (info_level) {
9645 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9649 /* Realloc the parameter and data sizes */
9650 *pparams = (char *)SMB_REALLOC(*pparams,6);
9651 if (*pparams == NULL) {
9652 reply_nterror(req, NT_STATUS_NO_MEMORY);
9657 SSVAL(params,0,fnf_handle);
9658 SSVAL(params,2,0); /* No changes */
9659 SSVAL(params,4,0); /* No EA errors */
9666 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9671 /****************************************************************************
9672 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9673 changes). Currently this does nothing.
9674 ****************************************************************************/
9676 static void call_trans2findnotifynext(connection_struct *conn,
9677 struct smb_request *req,
9678 char **pparams, int total_params,
9679 char **ppdata, int total_data,
9680 unsigned int max_data_bytes)
9682 char *params = *pparams;
9684 DEBUG(3,("call_trans2findnotifynext\n"));
9686 /* Realloc the parameter and data sizes */
9687 *pparams = (char *)SMB_REALLOC(*pparams,4);
9688 if (*pparams == NULL) {
9689 reply_nterror(req, NT_STATUS_NO_MEMORY);
9694 SSVAL(params,0,0); /* No changes */
9695 SSVAL(params,2,0); /* No EA errors */
9697 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9702 /****************************************************************************
9703 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9704 ****************************************************************************/
9706 static void call_trans2getdfsreferral(connection_struct *conn,
9707 struct smb_request *req,
9708 char **pparams, int total_params,
9709 char **ppdata, int total_data,
9710 unsigned int max_data_bytes)
9712 char *params = *pparams;
9713 char *pathname = NULL;
9715 int max_referral_level;
9716 NTSTATUS status = NT_STATUS_OK;
9717 TALLOC_CTX *ctx = talloc_tos();
9719 DEBUG(10,("call_trans2getdfsreferral\n"));
9721 if (total_params < 3) {
9722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9726 max_referral_level = SVAL(params,0);
9728 if(!lp_host_msdfs()) {
9729 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9733 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9734 total_params - 2, STR_TERMINATE);
9736 reply_nterror(req, NT_STATUS_NOT_FOUND);
9739 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9740 ppdata,&status)) < 0) {
9741 reply_nterror(req, status);
9745 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9746 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9747 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9752 #define LMCAT_SPL 0x53
9753 #define LMFUNC_GETJOBID 0x60
9755 /****************************************************************************
9756 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9757 ****************************************************************************/
9759 static void call_trans2ioctl(connection_struct *conn,
9760 struct smb_request *req,
9761 char **pparams, int total_params,
9762 char **ppdata, int total_data,
9763 unsigned int max_data_bytes)
9765 const struct loadparm_substitution *lp_sub =
9766 loadparm_s3_global_substitution();
9767 char *pdata = *ppdata;
9768 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9772 /* check for an invalid fid before proceeding */
9775 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9779 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9780 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9781 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9782 if (*ppdata == NULL) {
9783 reply_nterror(req, NT_STATUS_NO_MEMORY);
9788 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9789 CAN ACCEPT THIS IN UNICODE. JRA. */
9792 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9794 status = srvstr_push(pdata, req->flags2, pdata + 2,
9795 lp_netbios_name(), 15,
9796 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9797 if (!NT_STATUS_IS_OK(status)) {
9798 reply_nterror(req, status);
9801 status = srvstr_push(pdata, req->flags2, pdata+18,
9802 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9803 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9804 if (!NT_STATUS_IS_OK(status)) {
9805 reply_nterror(req, status);
9808 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9813 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9814 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9817 /****************************************************************************
9818 Reply to a SMBfindclose (stop trans2 directory search).
9819 ****************************************************************************/
9821 void reply_findclose(struct smb_request *req)
9824 struct smbd_server_connection *sconn = req->sconn;
9825 files_struct *fsp = NULL;
9827 START_PROFILE(SMBfindclose);
9830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9831 END_PROFILE(SMBfindclose);
9835 dptr_num = SVALS(req->vwv+0, 0);
9837 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9840 * OS/2 seems to use -1 to indicate "close all directories"
9841 * This has to mean on this specific connection struct.
9843 if (dptr_num == -1) {
9844 dptr_closecnum(req->conn);
9846 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9849 close_file(NULL, fsp, NORMAL_CLOSE);
9854 reply_outbuf(req, 0, 0);
9856 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9858 END_PROFILE(SMBfindclose);
9862 /****************************************************************************
9863 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9864 ****************************************************************************/
9866 void reply_findnclose(struct smb_request *req)
9870 START_PROFILE(SMBfindnclose);
9873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9874 END_PROFILE(SMBfindnclose);
9878 dptr_num = SVAL(req->vwv+0, 0);
9880 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9882 /* We never give out valid handles for a
9883 findnotifyfirst - so any dptr_num is ok here.
9886 reply_outbuf(req, 0, 0);
9888 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9890 END_PROFILE(SMBfindnclose);
9894 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9895 struct trans_state *state)
9897 if (get_Protocol() >= PROTOCOL_NT1) {
9898 req->flags2 |= 0x40; /* IS_LONG_NAME */
9899 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9902 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9903 if (state->call != TRANSACT2_QFSINFO &&
9904 state->call != TRANSACT2_SETFSINFO) {
9905 DEBUG(0,("handle_trans2: encryption required "
9907 (unsigned int)state->call));
9908 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9913 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9915 /* Now we must call the relevant TRANS2 function */
9916 switch(state->call) {
9917 case TRANSACT2_OPEN:
9919 START_PROFILE(Trans2_open);
9920 call_trans2open(conn, req,
9921 &state->param, state->total_param,
9922 &state->data, state->total_data,
9923 state->max_data_return);
9924 END_PROFILE(Trans2_open);
9928 case TRANSACT2_FINDFIRST:
9930 START_PROFILE(Trans2_findfirst);
9931 call_trans2findfirst(conn, req,
9932 &state->param, state->total_param,
9933 &state->data, state->total_data,
9934 state->max_data_return);
9935 END_PROFILE(Trans2_findfirst);
9939 case TRANSACT2_FINDNEXT:
9941 START_PROFILE(Trans2_findnext);
9942 call_trans2findnext(conn, req,
9943 &state->param, state->total_param,
9944 &state->data, state->total_data,
9945 state->max_data_return);
9946 END_PROFILE(Trans2_findnext);
9950 case TRANSACT2_QFSINFO:
9952 START_PROFILE(Trans2_qfsinfo);
9953 call_trans2qfsinfo(conn, req,
9954 &state->param, state->total_param,
9955 &state->data, state->total_data,
9956 state->max_data_return);
9957 END_PROFILE(Trans2_qfsinfo);
9961 case TRANSACT2_SETFSINFO:
9963 START_PROFILE(Trans2_setfsinfo);
9964 call_trans2setfsinfo(conn, req,
9965 &state->param, state->total_param,
9966 &state->data, state->total_data,
9967 state->max_data_return);
9968 END_PROFILE(Trans2_setfsinfo);
9972 case TRANSACT2_QPATHINFO:
9973 case TRANSACT2_QFILEINFO:
9975 START_PROFILE(Trans2_qpathinfo);
9976 call_trans2qfilepathinfo(conn, req, state->call,
9977 &state->param, state->total_param,
9978 &state->data, state->total_data,
9979 state->max_data_return);
9980 END_PROFILE(Trans2_qpathinfo);
9984 case TRANSACT2_SETPATHINFO:
9985 case TRANSACT2_SETFILEINFO:
9987 START_PROFILE(Trans2_setpathinfo);
9988 call_trans2setfilepathinfo(conn, req, state->call,
9989 &state->param, state->total_param,
9990 &state->data, state->total_data,
9991 state->max_data_return);
9992 END_PROFILE(Trans2_setpathinfo);
9996 case TRANSACT2_FINDNOTIFYFIRST:
9998 START_PROFILE(Trans2_findnotifyfirst);
9999 call_trans2findnotifyfirst(conn, req,
10000 &state->param, state->total_param,
10001 &state->data, state->total_data,
10002 state->max_data_return);
10003 END_PROFILE(Trans2_findnotifyfirst);
10007 case TRANSACT2_FINDNOTIFYNEXT:
10009 START_PROFILE(Trans2_findnotifynext);
10010 call_trans2findnotifynext(conn, req,
10011 &state->param, state->total_param,
10012 &state->data, state->total_data,
10013 state->max_data_return);
10014 END_PROFILE(Trans2_findnotifynext);
10018 case TRANSACT2_MKDIR:
10020 START_PROFILE(Trans2_mkdir);
10021 call_trans2mkdir(conn, req,
10022 &state->param, state->total_param,
10023 &state->data, state->total_data,
10024 state->max_data_return);
10025 END_PROFILE(Trans2_mkdir);
10029 case TRANSACT2_GET_DFS_REFERRAL:
10031 START_PROFILE(Trans2_get_dfs_referral);
10032 call_trans2getdfsreferral(conn, req,
10033 &state->param, state->total_param,
10034 &state->data, state->total_data,
10035 state->max_data_return);
10036 END_PROFILE(Trans2_get_dfs_referral);
10040 case TRANSACT2_IOCTL:
10042 START_PROFILE(Trans2_ioctl);
10043 call_trans2ioctl(conn, req,
10044 &state->param, state->total_param,
10045 &state->data, state->total_data,
10046 state->max_data_return);
10047 END_PROFILE(Trans2_ioctl);
10052 /* Error in request */
10053 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10054 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10058 /****************************************************************************
10059 Reply to a SMBtrans2.
10060 ****************************************************************************/
10062 void reply_trans2(struct smb_request *req)
10064 connection_struct *conn = req->conn;
10065 unsigned int dsoff;
10066 unsigned int dscnt;
10067 unsigned int psoff;
10068 unsigned int pscnt;
10069 unsigned int tran_call;
10070 struct trans_state *state;
10073 START_PROFILE(SMBtrans2);
10075 if (req->wct < 14) {
10076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10077 END_PROFILE(SMBtrans2);
10081 dsoff = SVAL(req->vwv+12, 0);
10082 dscnt = SVAL(req->vwv+11, 0);
10083 psoff = SVAL(req->vwv+10, 0);
10084 pscnt = SVAL(req->vwv+9, 0);
10085 tran_call = SVAL(req->vwv+14, 0);
10087 result = allow_new_trans(conn->pending_trans, req->mid);
10088 if (!NT_STATUS_IS_OK(result)) {
10089 DEBUG(2, ("Got invalid trans2 request: %s\n",
10090 nt_errstr(result)));
10091 reply_nterror(req, result);
10092 END_PROFILE(SMBtrans2);
10096 if (IS_IPC(conn)) {
10097 switch (tran_call) {
10098 /* List the allowed trans2 calls on IPC$ */
10099 case TRANSACT2_OPEN:
10100 case TRANSACT2_GET_DFS_REFERRAL:
10101 case TRANSACT2_QFILEINFO:
10102 case TRANSACT2_QFSINFO:
10103 case TRANSACT2_SETFSINFO:
10106 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10107 END_PROFILE(SMBtrans2);
10112 if ((state = talloc(conn, struct trans_state)) == NULL) {
10113 DEBUG(0, ("talloc failed\n"));
10114 reply_nterror(req, NT_STATUS_NO_MEMORY);
10115 END_PROFILE(SMBtrans2);
10119 state->cmd = SMBtrans2;
10121 state->mid = req->mid;
10122 state->vuid = req->vuid;
10123 state->setup_count = SVAL(req->vwv+13, 0);
10124 state->setup = NULL;
10125 state->total_param = SVAL(req->vwv+0, 0);
10126 state->param = NULL;
10127 state->total_data = SVAL(req->vwv+1, 0);
10128 state->data = NULL;
10129 state->max_param_return = SVAL(req->vwv+2, 0);
10130 state->max_data_return = SVAL(req->vwv+3, 0);
10131 state->max_setup_return = SVAL(req->vwv+4, 0);
10132 state->close_on_completion = BITSETW(req->vwv+5, 0);
10133 state->one_way = BITSETW(req->vwv+5, 1);
10135 state->call = tran_call;
10137 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10138 is so as a sanity check */
10139 if (state->setup_count != 1) {
10141 * Need to have rc=0 for ioctl to get job id for OS/2.
10142 * Network printing will fail if function is not successful.
10143 * Similar function in reply.c will be used if protocol
10144 * is LANMAN1.0 instead of LM1.2X002.
10145 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10146 * outbuf doesn't have to be set(only job id is used).
10148 if ( (state->setup_count == 4)
10149 && (tran_call == TRANSACT2_IOCTL)
10150 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10151 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10152 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10154 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10155 DEBUG(2,("Transaction is %d\n",tran_call));
10156 TALLOC_FREE(state);
10157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10158 END_PROFILE(SMBtrans2);
10163 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10166 if (state->total_data) {
10168 if (trans_oob(state->total_data, 0, dscnt)
10169 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10173 /* Can't use talloc here, the core routines do realloc on the
10174 * params and data. */
10175 state->data = (char *)SMB_MALLOC(state->total_data);
10176 if (state->data == NULL) {
10177 DEBUG(0,("reply_trans2: data malloc fail for %u "
10178 "bytes !\n", (unsigned int)state->total_data));
10179 TALLOC_FREE(state);
10180 reply_nterror(req, NT_STATUS_NO_MEMORY);
10181 END_PROFILE(SMBtrans2);
10185 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10188 if (state->total_param) {
10190 if (trans_oob(state->total_param, 0, pscnt)
10191 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10195 /* Can't use talloc here, the core routines do realloc on the
10196 * params and data. */
10197 state->param = (char *)SMB_MALLOC(state->total_param);
10198 if (state->param == NULL) {
10199 DEBUG(0,("reply_trans: param malloc fail for %u "
10200 "bytes !\n", (unsigned int)state->total_param));
10201 SAFE_FREE(state->data);
10202 TALLOC_FREE(state);
10203 reply_nterror(req, NT_STATUS_NO_MEMORY);
10204 END_PROFILE(SMBtrans2);
10208 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10211 state->received_data = dscnt;
10212 state->received_param = pscnt;
10214 if ((state->received_param == state->total_param) &&
10215 (state->received_data == state->total_data)) {
10217 handle_trans2(conn, req, state);
10219 SAFE_FREE(state->data);
10220 SAFE_FREE(state->param);
10221 TALLOC_FREE(state);
10222 END_PROFILE(SMBtrans2);
10226 DLIST_ADD(conn->pending_trans, state);
10228 /* We need to send an interim response then receive the rest
10229 of the parameter/data bytes */
10230 reply_outbuf(req, 0, 0);
10231 show_msg((char *)req->outbuf);
10232 END_PROFILE(SMBtrans2);
10237 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10238 SAFE_FREE(state->data);
10239 SAFE_FREE(state->param);
10240 TALLOC_FREE(state);
10241 END_PROFILE(SMBtrans2);
10242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10246 /****************************************************************************
10247 Reply to a SMBtranss2
10248 ****************************************************************************/
10250 void reply_transs2(struct smb_request *req)
10252 connection_struct *conn = req->conn;
10253 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10254 struct trans_state *state;
10256 START_PROFILE(SMBtranss2);
10258 show_msg((const char *)req->inbuf);
10260 /* Windows clients expect all replies to
10261 a transact secondary (SMBtranss2 0x33)
10262 to have a command code of transact
10263 (SMBtrans2 0x32). See bug #8989
10264 and also [MS-CIFS] section 2.2.4.47.2
10267 req->cmd = SMBtrans2;
10269 if (req->wct < 8) {
10270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10271 END_PROFILE(SMBtranss2);
10275 for (state = conn->pending_trans; state != NULL;
10276 state = state->next) {
10277 if (state->mid == req->mid) {
10282 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10284 END_PROFILE(SMBtranss2);
10288 /* Revise state->total_param and state->total_data in case they have
10289 changed downwards */
10291 if (SVAL(req->vwv+0, 0) < state->total_param)
10292 state->total_param = SVAL(req->vwv+0, 0);
10293 if (SVAL(req->vwv+1, 0) < state->total_data)
10294 state->total_data = SVAL(req->vwv+1, 0);
10296 pcnt = SVAL(req->vwv+2, 0);
10297 poff = SVAL(req->vwv+3, 0);
10298 pdisp = SVAL(req->vwv+4, 0);
10300 dcnt = SVAL(req->vwv+5, 0);
10301 doff = SVAL(req->vwv+6, 0);
10302 ddisp = SVAL(req->vwv+7, 0);
10304 state->received_param += pcnt;
10305 state->received_data += dcnt;
10307 if ((state->received_data > state->total_data) ||
10308 (state->received_param > state->total_param))
10312 if (trans_oob(state->total_param, pdisp, pcnt)
10313 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10316 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10320 if (trans_oob(state->total_data, ddisp, dcnt)
10321 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10324 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10327 if ((state->received_param < state->total_param) ||
10328 (state->received_data < state->total_data)) {
10329 END_PROFILE(SMBtranss2);
10333 handle_trans2(conn, req, state);
10335 DLIST_REMOVE(conn->pending_trans, state);
10336 SAFE_FREE(state->data);
10337 SAFE_FREE(state->param);
10338 TALLOC_FREE(state);
10340 END_PROFILE(SMBtranss2);
10345 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10346 DLIST_REMOVE(conn->pending_trans, state);
10347 SAFE_FREE(state->data);
10348 SAFE_FREE(state->param);
10349 TALLOC_FREE(state);
10350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10351 END_PROFILE(SMBtranss2);