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 path.
196 ********************************************************************/
198 static NTSTATUS check_access(connection_struct *conn,
199 struct files_struct *dirfsp,
200 const struct smb_filename *smb_fname,
201 uint32_t access_mask)
203 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
204 return smbd_check_access_rights(conn,
211 /********************************************************************
212 Roundup a value to the nearest allocation roundup size boundary.
213 Only do this for Windows clients.
214 ********************************************************************/
216 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
218 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
220 /* Only roundup for Windows clients. */
221 enum remote_arch_types ra_type = get_remote_arch();
222 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
223 val = SMB_ROUNDUP(val,rval);
228 /****************************************************************************
229 Utility functions for dealing with extended attributes.
230 ****************************************************************************/
232 /****************************************************************************
233 Refuse to allow clients to overwrite our private xattrs.
234 ****************************************************************************/
236 bool samba_private_attr_name(const char *unix_ea_name)
238 static const char * const prohibited_ea_names[] = {
239 SAMBA_POSIX_INHERITANCE_EA_NAME,
240 SAMBA_XATTR_DOS_ATTRIB,
248 for (i = 0; prohibited_ea_names[i]; i++) {
249 if (strequal( prohibited_ea_names[i], unix_ea_name))
252 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
253 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
259 /****************************************************************************
260 Get one EA value. Fill in a struct ea_struct.
261 ****************************************************************************/
263 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
264 connection_struct *conn,
266 const struct smb_filename *smb_fname,
268 struct ea_struct *pea)
270 /* Get the value of this xattr. Max size is 64k. */
271 size_t attr_size = 256;
277 val = talloc_realloc(mem_ctx, val, char, attr_size);
279 return NT_STATUS_NO_MEMORY;
282 if (fsp && fsp->fh->fd != -1) {
283 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
285 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
286 ea_name, val, attr_size);
289 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
295 return map_nt_error_from_unix(errno);
298 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
299 dump_data(10, (uint8_t *)val, sizeret);
302 if (strnequal(ea_name, "user.", 5)) {
303 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
305 pea->name = talloc_strdup(mem_ctx, ea_name);
307 if (pea->name == NULL) {
309 return NT_STATUS_NO_MEMORY;
311 pea->value.data = (unsigned char *)val;
312 pea->value.length = (size_t)sizeret;
316 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
317 connection_struct *conn,
319 const struct smb_filename *smb_fname,
324 /* Get a list of all xattrs. Max namesize is 64k. */
325 size_t ea_namelist_size = 1024;
326 char *ea_namelist = smallbuf;
327 char *to_free = NULL;
332 ssize_t sizeret = -1;
340 status = refuse_symlink(conn, fsp, smb_fname);
341 if (!NT_STATUS_IS_OK(status)) {
343 * Just return no EA's on a symlink.
348 if (fsp && fsp->fh->fd != -1) {
349 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
352 sizeret = SMB_VFS_LISTXATTR(conn,
358 if ((sizeret == -1) && (errno == ERANGE)) {
359 ea_namelist_size = 65536;
360 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
361 if (ea_namelist == NULL) {
362 return NT_STATUS_NO_MEMORY;
364 to_free = ea_namelist;
366 if (fsp && fsp->fh->fd != -1) {
367 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
370 sizeret = SMB_VFS_LISTXATTR(conn,
378 status = map_nt_error_from_unix(errno);
379 TALLOC_FREE(to_free);
383 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
386 TALLOC_FREE(to_free);
391 * Ensure the result is 0-terminated
394 if (ea_namelist[sizeret-1] != '\0') {
395 TALLOC_FREE(to_free);
396 return NT_STATUS_INTERNAL_ERROR;
404 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
408 *pnum_names = num_names;
410 if (pnames == NULL) {
411 TALLOC_FREE(to_free);
415 names = talloc_array(mem_ctx, char *, num_names);
417 DEBUG(0, ("talloc failed\n"));
418 TALLOC_FREE(to_free);
419 return NT_STATUS_NO_MEMORY;
422 if (ea_namelist == smallbuf) {
423 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
424 if (ea_namelist == NULL) {
426 return NT_STATUS_NO_MEMORY;
429 talloc_steal(names, ea_namelist);
431 ea_namelist = talloc_realloc(names, ea_namelist, char,
433 if (ea_namelist == NULL) {
435 return NT_STATUS_NO_MEMORY;
441 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
442 names[num_names++] = p;
450 /****************************************************************************
451 Return a linked list of the total EA's. Plus the total size
452 ****************************************************************************/
454 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
455 connection_struct *conn,
457 const struct smb_filename *smb_fname,
458 size_t *pea_total_len,
459 struct ea_list **ea_list)
461 /* Get a list of all xattrs. Max namesize is 64k. */
464 struct ea_list *ea_list_head = NULL;
465 bool posix_pathnames = false;
471 if (!lp_ea_support(SNUM(conn))) {
477 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
479 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
482 status = get_ea_names_from_file(talloc_tos(),
489 if (!NT_STATUS_IS_OK(status)) {
493 if (num_names == 0) {
497 for (i=0; i<num_names; i++) {
498 struct ea_list *listp;
501 if (strnequal(names[i], "system.", 7)
502 || samba_private_attr_name(names[i]))
506 * Filter out any underlying POSIX EA names
507 * that a Windows client can't handle.
509 if (!posix_pathnames &&
510 is_invalid_windows_ea_name(names[i])) {
514 listp = talloc(mem_ctx, struct ea_list);
516 return NT_STATUS_NO_MEMORY;
519 status = get_ea_value(listp,
526 if (!NT_STATUS_IS_OK(status)) {
531 if (listp->ea.value.length == 0) {
533 * We can never return a zero length EA.
534 * Windows reports the EA's as corrupted.
540 push_ascii_fstring(dos_ea_name, listp->ea.name);
543 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
545 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
546 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
547 (unsigned int)listp->ea.value.length));
549 DLIST_ADD_END(ea_list_head, listp);
553 /* Add on 4 for total length. */
554 if (*pea_total_len) {
558 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
559 (unsigned int)*pea_total_len));
561 *ea_list = ea_list_head;
565 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
566 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
571 if (!lp_ea_support(SNUM(conn))) {
575 if (is_ntfs_stream_smb_fname(smb_fname)) {
576 return NT_STATUS_INVALID_PARAMETER;
579 return get_ea_list_from_file_path(mem_ctx,
587 /****************************************************************************
588 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
590 ****************************************************************************/
592 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
593 connection_struct *conn, struct ea_list *ea_list)
595 unsigned int ret_data_size = 4;
598 SMB_ASSERT(total_data_size >= 4);
600 if (!lp_ea_support(SNUM(conn))) {
605 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
613 if (ea_list->ea.value.length > 65535) {
616 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
620 /* We know we have room. */
621 SCVAL(p,0,ea_list->ea.flags);
622 SCVAL(p,1,dos_namelen);
623 SSVAL(p,2,ea_list->ea.value.length);
624 strlcpy(p+4, dos_ea_name, dos_namelen+1);
625 if (ea_list->ea.value.length > 0) {
626 memcpy(p + 4 + dos_namelen + 1,
627 ea_list->ea.value.data,
628 ea_list->ea.value.length);
631 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
632 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
635 ret_data_size = PTR_DIFF(p, pdata);
636 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
637 SIVAL(pdata,0,ret_data_size);
638 return ret_data_size;
641 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
643 unsigned int total_data_size,
644 unsigned int *ret_data_size,
645 connection_struct *conn,
646 struct ea_list *ea_list)
648 uint8_t *p = (uint8_t *)pdata;
649 uint8_t *last_start = NULL;
650 bool do_store_data = (pdata != NULL);
654 if (!lp_ea_support(SNUM(conn))) {
655 return NT_STATUS_NO_EAS_ON_FILE;
658 for (; ea_list; ea_list = ea_list->next) {
664 if (last_start != NULL && do_store_data) {
665 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
669 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
670 dos_namelen = strlen(dos_ea_name);
671 if (dos_namelen > 255 || dos_namelen == 0) {
672 return NT_STATUS_INTERNAL_ERROR;
674 if (ea_list->ea.value.length > 65535) {
675 return NT_STATUS_INTERNAL_ERROR;
678 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
681 pad = (4 - (this_size % 4)) % 4;
686 if (this_size > total_data_size) {
687 return NT_STATUS_INFO_LENGTH_MISMATCH;
690 /* We know we have room. */
691 SIVAL(p, 0x00, 0); /* next offset */
692 SCVAL(p, 0x04, ea_list->ea.flags);
693 SCVAL(p, 0x05, dos_namelen);
694 SSVAL(p, 0x06, ea_list->ea.value.length);
695 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
696 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
698 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
702 total_data_size -= this_size;
708 *ret_data_size = PTR_DIFF(p, pdata);
709 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
713 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
715 size_t total_ea_len = 0;
717 struct ea_list *ea_list = NULL;
719 if (!lp_ea_support(SNUM(conn))) {
722 mem_ctx = talloc_stackframe();
724 /* If this is a stream fsp, then we need to instead find the
725 * estimated ea len from the main file, not the stream
726 * (streams cannot have EAs), but the estimate isn't just 0 in
728 if (is_ntfs_stream_smb_fname(smb_fname)) {
731 (void)get_ea_list_from_file_path(mem_ctx,
737 if(conn->sconn->using_smb2) {
739 unsigned int ret_data_size;
741 * We're going to be using fill_ea_chained_buffer() to
742 * marshall EA's - this size is significantly larger
743 * than the SMB1 buffer. Re-calculate the size without
746 status = fill_ea_chained_buffer(mem_ctx,
752 if (!NT_STATUS_IS_OK(status)) {
755 total_ea_len = ret_data_size;
757 TALLOC_FREE(mem_ctx);
761 /****************************************************************************
762 Ensure the EA name is case insensitive by matching any existing EA name.
763 ****************************************************************************/
765 static void canonicalize_ea_name(connection_struct *conn,
767 const struct smb_filename *smb_fname,
768 fstring unix_ea_name)
771 TALLOC_CTX *mem_ctx = talloc_tos();
772 struct ea_list *ea_list;
773 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
779 if (!NT_STATUS_IS_OK(status)) {
783 for (; ea_list; ea_list = ea_list->next) {
784 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
785 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
786 &unix_ea_name[5], ea_list->ea.name));
787 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
793 /****************************************************************************
794 Set or delete an extended attribute.
795 ****************************************************************************/
797 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
798 const struct smb_filename *smb_fname, struct ea_list *ea_list)
801 bool posix_pathnames = false;
803 if (!lp_ea_support(SNUM(conn))) {
804 return NT_STATUS_EAS_NOT_SUPPORTED;
809 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
811 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
814 status = refuse_symlink(conn, fsp, smb_fname);
815 if (!NT_STATUS_IS_OK(status)) {
820 status = check_access_fsp(fsp, FILE_WRITE_EA);
822 status = check_access(conn,
827 if (!NT_STATUS_IS_OK(status)) {
831 /* Setting EAs on streams isn't supported. */
832 if (is_ntfs_stream_smb_fname(smb_fname)) {
833 return NT_STATUS_INVALID_PARAMETER;
837 * Filter out invalid Windows EA names - before
838 * we set *any* of them.
841 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
842 return STATUS_INVALID_EA_NAME;
845 for (;ea_list; ea_list = ea_list->next) {
847 fstring unix_ea_name;
849 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
850 fstrcat(unix_ea_name, ea_list->ea.name);
852 canonicalize_ea_name(conn,
857 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
859 if (samba_private_attr_name(unix_ea_name)) {
860 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
861 return NT_STATUS_ACCESS_DENIED;
864 if (ea_list->ea.value.length == 0) {
865 /* Remove the attribute. */
866 if (fsp && (fsp->fh->fd != -1)) {
867 DEBUG(10,("set_ea: deleting ea name %s on "
868 "file %s by file descriptor.\n",
869 unix_ea_name, fsp_str_dbg(fsp)));
870 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
872 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
873 unix_ea_name, smb_fname->base_name));
874 ret = SMB_VFS_REMOVEXATTR(conn,
879 /* Removing a non existent attribute always succeeds. */
880 if (ret == -1 && errno == ENOATTR) {
881 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
887 if (fsp && (fsp->fh->fd != -1)) {
888 DEBUG(10,("set_ea: setting ea name %s on file "
889 "%s by file descriptor.\n",
890 unix_ea_name, fsp_str_dbg(fsp)));
891 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
892 ea_list->ea.value.data, ea_list->ea.value.length, 0);
894 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
895 unix_ea_name, smb_fname->base_name));
896 ret = SMB_VFS_SETXATTR(conn,
899 ea_list->ea.value.data,
900 ea_list->ea.value.length,
907 if (errno == ENOTSUP) {
908 return NT_STATUS_EAS_NOT_SUPPORTED;
911 return map_nt_error_from_unix(errno);
917 /****************************************************************************
918 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
919 ****************************************************************************/
921 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
923 struct ea_list *ea_list_head = NULL;
924 size_t converted_size, offset = 0;
926 while (offset + 2 < data_size) {
927 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
928 unsigned int namelen = CVAL(pdata,offset);
930 offset++; /* Go past the namelen byte. */
932 /* integer wrap paranioa. */
933 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
934 (offset > data_size) || (namelen > data_size) ||
935 (offset + namelen >= data_size)) {
938 /* Ensure the name is null terminated. */
939 if (pdata[offset + namelen] != '\0') {
942 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
944 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
945 "failed: %s", strerror(errno)));
951 offset += (namelen + 1); /* Go past the name + terminating zero. */
952 DLIST_ADD_END(ea_list_head, eal);
953 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
959 /****************************************************************************
960 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
961 ****************************************************************************/
963 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
965 struct ea_list *ea_list_head = NULL;
967 size_t bytes_used = 0;
969 while (offset < data_size) {
970 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
976 DLIST_ADD_END(ea_list_head, eal);
977 offset += bytes_used;
983 /****************************************************************************
984 Count the total EA size needed.
985 ****************************************************************************/
987 static size_t ea_list_size(struct ea_list *ealist)
990 struct ea_list *listp;
993 for (listp = ealist; listp; listp = listp->next) {
994 push_ascii_fstring(dos_ea_name, listp->ea.name);
995 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
997 /* Add on 4 for total length. */
1005 /****************************************************************************
1006 Return a union of EA's from a file list and a list of names.
1007 The TALLOC context for the two lists *MUST* be identical as we steal
1008 memory from one list to add to another. JRA.
1009 ****************************************************************************/
1011 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1013 struct ea_list *nlistp, *flistp;
1015 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1016 for (flistp = file_list; flistp; flistp = flistp->next) {
1017 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1023 /* Copy the data from this entry. */
1024 nlistp->ea.flags = flistp->ea.flags;
1025 nlistp->ea.value = flistp->ea.value;
1028 nlistp->ea.flags = 0;
1029 ZERO_STRUCT(nlistp->ea.value);
1033 *total_ea_len = ea_list_size(name_list);
1037 /****************************************************************************
1038 Send the required number of replies back.
1039 We assume all fields other than the data fields are
1040 set correctly for the type of call.
1041 HACK ! Always assumes smb_setup field is zero.
1042 ****************************************************************************/
1044 void send_trans2_replies(connection_struct *conn,
1045 struct smb_request *req,
1053 /* As we are using a protocol > LANMAN1 then the max_send
1054 variable must have been set in the sessetupX call.
1055 This takes precedence over the max_xmit field in the
1056 global struct. These different max_xmit variables should
1057 be merged as this is now too confusing */
1059 int data_to_send = datasize;
1060 int params_to_send = paramsize;
1062 const char *pp = params;
1063 const char *pd = pdata;
1064 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1065 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1066 int data_alignment_offset = 0;
1067 bool overflow = False;
1068 struct smbXsrv_connection *xconn = req->xconn;
1069 int max_send = xconn->smb1.sessions.max_send;
1071 /* Modify the data_to_send and datasize and set the error if
1072 we're trying to send more than max_data_bytes. We still send
1073 the part of the packet(s) that fit. Strange, but needed
1076 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1077 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1078 max_data_bytes, datasize ));
1079 datasize = data_to_send = max_data_bytes;
1083 /* If there genuinely are no parameters or data to send just send the empty packet */
1085 if(params_to_send == 0 && data_to_send == 0) {
1086 reply_outbuf(req, 10, 0);
1087 if (NT_STATUS_V(status)) {
1090 ntstatus_to_dos(status, &eclass, &ecode);
1091 error_packet_set((char *)req->outbuf,
1092 eclass, ecode, status,
1095 show_msg((char *)req->outbuf);
1096 if (!srv_send_smb(xconn,
1097 (char *)req->outbuf,
1098 true, req->seqnum+1,
1099 IS_CONN_ENCRYPTED(conn),
1101 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1103 TALLOC_FREE(req->outbuf);
1107 /* When sending params and data ensure that both are nicely aligned */
1108 /* Only do this alignment when there is also data to send - else
1109 can cause NT redirector problems. */
1111 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1112 data_alignment_offset = 4 - (params_to_send % 4);
1114 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1115 /* The alignment_offset is to align the param bytes on an even byte
1116 boundary. NT 4.0 Beta needs this to work correctly. */
1118 useable_space = max_send - (smb_size
1121 + data_alignment_offset);
1123 if (useable_space < 0) {
1124 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1125 "= %d!!!", useable_space));
1126 exit_server_cleanly("send_trans2_replies: Not enough space");
1129 while (params_to_send || data_to_send) {
1130 /* Calculate whether we will totally or partially fill this packet */
1132 total_sent_thistime = params_to_send + data_to_send;
1134 /* We can never send more than useable_space */
1136 * Note that 'useable_space' does not include the alignment offsets,
1137 * but we must include the alignment offsets in the calculation of
1138 * the length of the data we send over the wire, as the alignment offsets
1139 * are sent here. Fix from Marc_Jacobsen@hp.com.
1142 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1144 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1145 + data_alignment_offset);
1147 /* Set total params and data to be sent */
1148 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1149 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1151 /* Calculate how many parameters and data we can fit into
1152 * this packet. Parameters get precedence
1155 params_sent_thistime = MIN(params_to_send,useable_space);
1156 data_sent_thistime = useable_space - params_sent_thistime;
1157 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1159 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1161 /* smb_proff is the offset from the start of the SMB header to the
1162 parameter bytes, however the first 4 bytes of outbuf are
1163 the Netbios over TCP header. Thus use smb_base() to subtract
1164 them from the calculation */
1166 SSVAL(req->outbuf,smb_proff,
1167 ((smb_buf(req->outbuf)+alignment_offset)
1168 - smb_base(req->outbuf)));
1170 if(params_sent_thistime == 0)
1171 SSVAL(req->outbuf,smb_prdisp,0);
1173 /* Absolute displacement of param bytes sent in this packet */
1174 SSVAL(req->outbuf,smb_prdisp,pp - params);
1176 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1177 if(data_sent_thistime == 0) {
1178 SSVAL(req->outbuf,smb_droff,0);
1179 SSVAL(req->outbuf,smb_drdisp, 0);
1181 /* The offset of the data bytes is the offset of the
1182 parameter bytes plus the number of parameters being sent this time */
1183 SSVAL(req->outbuf, smb_droff,
1184 ((smb_buf(req->outbuf)+alignment_offset)
1185 - smb_base(req->outbuf))
1186 + params_sent_thistime + data_alignment_offset);
1187 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1190 /* Initialize the padding for alignment */
1192 if (alignment_offset != 0) {
1193 memset(smb_buf(req->outbuf), 0, alignment_offset);
1196 /* Copy the param bytes into the packet */
1198 if(params_sent_thistime) {
1199 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1200 params_sent_thistime);
1203 /* Copy in the data bytes */
1204 if(data_sent_thistime) {
1205 if (data_alignment_offset != 0) {
1206 memset((smb_buf(req->outbuf)+alignment_offset+
1207 params_sent_thistime), 0,
1208 data_alignment_offset);
1210 memcpy(smb_buf(req->outbuf)+alignment_offset
1211 +params_sent_thistime+data_alignment_offset,
1212 pd,data_sent_thistime);
1215 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1216 params_sent_thistime, data_sent_thistime, useable_space));
1217 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1218 params_to_send, data_to_send, paramsize, datasize));
1221 error_packet_set((char *)req->outbuf,
1222 ERRDOS,ERRbufferoverflow,
1223 STATUS_BUFFER_OVERFLOW,
1225 } else if (NT_STATUS_V(status)) {
1228 ntstatus_to_dos(status, &eclass, &ecode);
1229 error_packet_set((char *)req->outbuf,
1230 eclass, ecode, status,
1234 /* Send the packet */
1235 show_msg((char *)req->outbuf);
1236 if (!srv_send_smb(xconn,
1237 (char *)req->outbuf,
1238 true, req->seqnum+1,
1239 IS_CONN_ENCRYPTED(conn),
1241 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1243 TALLOC_FREE(req->outbuf);
1245 pp += params_sent_thistime;
1246 pd += data_sent_thistime;
1248 params_to_send -= params_sent_thistime;
1249 data_to_send -= data_sent_thistime;
1252 if(params_to_send < 0 || data_to_send < 0) {
1253 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1254 params_to_send, data_to_send));
1262 /****************************************************************************
1263 Reply to a TRANSACT2_OPEN.
1264 ****************************************************************************/
1266 static void call_trans2open(connection_struct *conn,
1267 struct smb_request *req,
1268 char **pparams, int total_params,
1269 char **ppdata, int total_data,
1270 unsigned int max_data_bytes)
1272 struct smb_filename *smb_fname = NULL;
1273 char *params = *pparams;
1274 char *pdata = *ppdata;
1277 bool oplock_request;
1279 bool return_additional_info;
1288 int fattr=0,mtime=0;
1289 SMB_INO_T inode = 0;
1292 struct ea_list *ea_list = NULL;
1295 uint32_t access_mask;
1296 uint32_t share_mode;
1297 uint32_t create_disposition;
1298 uint32_t create_options = 0;
1299 uint32_t private_flags = 0;
1300 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1301 TALLOC_CTX *ctx = talloc_tos();
1304 * Ensure we have enough parameters to perform the operation.
1307 if (total_params < 29) {
1308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1312 flags = SVAL(params, 0);
1313 deny_mode = SVAL(params, 2);
1314 open_attr = SVAL(params,6);
1315 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1316 if (oplock_request) {
1317 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1321 return_additional_info = BITSETW(params,0);
1322 open_sattr = SVAL(params, 4);
1323 open_time = make_unix_date3(params+8);
1325 open_ofun = SVAL(params,12);
1326 open_size = IVAL(params,14);
1327 pname = ¶ms[28];
1330 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1334 if (req->posix_pathnames) {
1335 srvstr_get_path_posix(ctx,
1344 srvstr_get_path(ctx,
1353 if (!NT_STATUS_IS_OK(status)) {
1354 reply_nterror(req, status);
1358 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1359 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1360 (unsigned int)open_ofun, open_size));
1362 status = filename_convert(ctx,
1369 if (!NT_STATUS_IS_OK(status)) {
1370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1371 reply_botherror(req,
1372 NT_STATUS_PATH_NOT_COVERED,
1373 ERRSRV, ERRbadpath);
1376 reply_nterror(req, status);
1380 if (open_ofun == 0) {
1381 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1385 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1387 &access_mask, &share_mode,
1388 &create_disposition,
1391 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1395 /* Any data in this call is an EA list. */
1396 if (total_data && (total_data != 4)) {
1397 if (total_data < 10) {
1398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1402 if (IVAL(pdata,0) > total_data) {
1403 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1404 IVAL(pdata,0), (unsigned int)total_data));
1405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1409 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1416 if (!lp_ea_support(SNUM(conn))) {
1417 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1421 if (!req->posix_pathnames &&
1422 ea_list_has_invalid_name(ea_list)) {
1424 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1425 if(*pparams == NULL ) {
1426 reply_nterror(req, NT_STATUS_NO_MEMORY);
1430 memset(params, '\0', param_len);
1431 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1432 params, param_len, NULL, 0, max_data_bytes);
1437 status = SMB_VFS_CREATE_FILE(
1440 0, /* root_dir_fid */
1441 smb_fname, /* fname */
1442 access_mask, /* access_mask */
1443 share_mode, /* share_access */
1444 create_disposition, /* create_disposition*/
1445 create_options, /* create_options */
1446 open_attr, /* file_attributes */
1447 oplock_request, /* oplock_request */
1449 open_size, /* allocation_size */
1452 ea_list, /* ea_list */
1454 &smb_action, /* psbuf */
1455 NULL, NULL); /* create context */
1457 if (!NT_STATUS_IS_OK(status)) {
1458 if (open_was_deferred(req->xconn, req->mid)) {
1459 /* We have re-scheduled this call. */
1463 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1464 reply_openerror(req, status);
1468 fsp = fcb_or_dos_open(
1475 bool ok = defer_smb1_sharing_violation(req);
1479 reply_openerror(req, status);
1483 smb_action = FILE_WAS_OPENED;
1486 size = get_file_size_stat(&smb_fname->st);
1487 fattr = dos_mode(conn, smb_fname);
1488 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1489 inode = smb_fname->st.st_ex_ino;
1490 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1491 close_file(req, fsp, ERROR_CLOSE);
1492 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1496 /* Realloc the size of parameters and data we will return */
1497 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1498 if(*pparams == NULL ) {
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1504 SSVAL(params,0,fsp->fnum);
1505 SSVAL(params,2,fattr);
1506 srv_put_dos_date2(params,4, mtime);
1507 SIVAL(params,8, (uint32_t)size);
1508 SSVAL(params,12,deny_mode);
1509 SSVAL(params,14,0); /* open_type - file or directory. */
1510 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1512 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1513 smb_action |= EXTENDED_OPLOCK_GRANTED;
1516 SSVAL(params,18,smb_action);
1519 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1521 SIVAL(params,20,inode);
1522 SSVAL(params,24,0); /* Padding. */
1524 uint32_t ea_size = estimate_ea_size(conn, fsp,
1526 SIVAL(params, 26, ea_size);
1528 SIVAL(params, 26, 0);
1531 /* Send the required number of replies */
1532 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1534 TALLOC_FREE(smb_fname);
1537 /*********************************************************
1538 Routine to check if a given string matches exactly.
1539 as a special case a mask of "." does NOT match. That
1540 is required for correct wildcard semantics
1541 Case can be significant or not.
1542 **********************************************************/
1544 static bool exact_match(bool has_wild,
1545 bool case_sensitive,
1549 if (mask[0] == '.' && mask[1] == 0) {
1557 if (case_sensitive) {
1558 return strcmp(str,mask)==0;
1560 return strcasecmp_m(str,mask) == 0;
1564 /****************************************************************************
1565 Return the filetype for UNIX extensions.
1566 ****************************************************************************/
1568 static uint32_t unix_filetype(mode_t mode)
1571 return UNIX_TYPE_FILE;
1572 else if(S_ISDIR(mode))
1573 return UNIX_TYPE_DIR;
1575 else if(S_ISLNK(mode))
1576 return UNIX_TYPE_SYMLINK;
1579 else if(S_ISCHR(mode))
1580 return UNIX_TYPE_CHARDEV;
1583 else if(S_ISBLK(mode))
1584 return UNIX_TYPE_BLKDEV;
1587 else if(S_ISFIFO(mode))
1588 return UNIX_TYPE_FIFO;
1591 else if(S_ISSOCK(mode))
1592 return UNIX_TYPE_SOCKET;
1595 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1596 return UNIX_TYPE_UNKNOWN;
1599 /****************************************************************************
1600 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1601 ****************************************************************************/
1603 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1604 const SMB_STRUCT_STAT *psbuf,
1606 enum perm_type ptype,
1611 if (perms == SMB_MODE_NO_CHANGE) {
1612 if (!VALID_STAT(*psbuf)) {
1613 return NT_STATUS_INVALID_PARAMETER;
1615 *ret_perms = psbuf->st_ex_mode;
1616 return NT_STATUS_OK;
1620 ret = wire_perms_to_unix(perms);
1622 if (ptype == PERM_NEW_FILE) {
1624 * "create mask"/"force create mode" are
1625 * only applied to new files, not existing ones.
1627 ret &= lp_create_mask(SNUM(conn));
1628 /* Add in force bits */
1629 ret |= lp_force_create_mode(SNUM(conn));
1630 } else if (ptype == PERM_NEW_DIR) {
1632 * "directory mask"/"force directory mode" are
1633 * only applied to new directories, not existing ones.
1635 ret &= lp_directory_mask(SNUM(conn));
1636 /* Add in force bits */
1637 ret |= lp_force_directory_mode(SNUM(conn));
1641 return NT_STATUS_OK;
1644 /****************************************************************************
1645 Needed to show the msdfs symlinks as directories. Modifies psbuf
1646 to be a directory if it's a msdfs link.
1647 ****************************************************************************/
1649 static bool check_msdfs_link(connection_struct *conn,
1650 struct smb_filename *smb_fname)
1652 int saved_errno = errno;
1653 if(lp_host_msdfs() &&
1654 lp_msdfs_root(SNUM(conn)) &&
1655 is_msdfs_link(conn, smb_fname)) {
1657 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1659 smb_fname->base_name));
1660 smb_fname->st.st_ex_mode =
1661 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1662 errno = saved_errno;
1665 errno = saved_errno;
1670 /****************************************************************************
1671 Get a level dependent lanman2 dir entry.
1672 ****************************************************************************/
1674 struct smbd_dirptr_lanman2_state {
1675 connection_struct *conn;
1676 uint32_t info_level;
1677 bool check_mangled_names;
1679 bool got_exact_match;
1682 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1688 struct smbd_dirptr_lanman2_state *state =
1689 (struct smbd_dirptr_lanman2_state *)private_data;
1691 char mangled_name[13]; /* mangled 8.3 name. */
1695 /* Mangle fname if it's an illegal name. */
1696 if (mangle_must_mangle(dname, state->conn->params)) {
1698 * Slow path - ensure we can push the original name as UCS2. If
1699 * not, then just don't return this name.
1703 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1704 uint8_t *tmp = talloc_array(talloc_tos(),
1708 status = srvstr_push(NULL,
1709 FLAGS2_UNICODE_STRINGS,
1718 if (!NT_STATUS_IS_OK(status)) {
1722 ok = name_to_8_3(dname, mangled_name,
1723 true, state->conn->params);
1727 fname = mangled_name;
1732 got_match = exact_match(state->has_wild,
1733 state->conn->case_sensitive,
1735 state->got_exact_match = got_match;
1737 got_match = mask_match(fname, mask,
1738 state->conn->case_sensitive);
1741 if(!got_match && state->check_mangled_names &&
1742 !mangle_is_8_3(fname, false, state->conn->params)) {
1744 * It turns out that NT matches wildcards against
1745 * both long *and* short names. This may explain some
1746 * of the wildcard wierdness from old DOS clients
1747 * that some people have been seeing.... JRA.
1749 /* Force the mangling into 8.3. */
1750 ok = name_to_8_3(fname, mangled_name,
1751 false, state->conn->params);
1756 got_match = exact_match(state->has_wild,
1757 state->conn->case_sensitive,
1758 mangled_name, mask);
1759 state->got_exact_match = got_match;
1761 got_match = mask_match(mangled_name, mask,
1762 state->conn->case_sensitive);
1770 *_fname = talloc_strdup(ctx, fname);
1771 if (*_fname == NULL) {
1778 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1780 struct smb_filename *smb_fname,
1784 struct smbd_dirptr_lanman2_state *state =
1785 (struct smbd_dirptr_lanman2_state *)private_data;
1786 bool ms_dfs_link = false;
1789 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1790 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1791 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1792 "Couldn't lstat [%s] (%s)\n",
1793 smb_fname_str_dbg(smb_fname),
1797 } else if (!VALID_STAT(smb_fname->st) &&
1798 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1799 /* Needed to show the msdfs symlinks as
1802 ms_dfs_link = check_msdfs_link(state->conn,
1805 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1806 "Couldn't stat [%s] (%s)\n",
1807 smb_fname_str_dbg(smb_fname),
1814 mode = dos_mode_msdfs(state->conn, smb_fname);
1815 } else if (get_dosmode) {
1816 mode = dos_mode(state->conn, smb_fname);
1823 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1824 connection_struct *conn,
1826 uint32_t info_level,
1827 struct ea_list *name_list,
1828 bool check_mangled_names,
1829 bool requires_resume_key,
1832 const struct smb_filename *smb_fname,
1833 int space_remaining,
1839 uint64_t *last_entry_off)
1841 char *p, *q, *pdata = *ppdata;
1843 uint64_t file_size = 0;
1844 uint64_t allocation_size = 0;
1845 uint64_t file_id = 0;
1847 struct timespec mdate_ts = {0};
1848 struct timespec adate_ts = {0};
1849 struct timespec cdate_ts = {0};
1850 struct timespec create_date_ts = {0};
1851 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1853 char *last_entry_ptr;
1858 struct readdir_attr_data *readdir_attr_data = NULL;
1860 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1861 file_size = get_file_size_stat(&smb_fname->st);
1863 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1865 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1872 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1874 mdate_ts = smb_fname->st.st_ex_mtime;
1875 adate_ts = smb_fname->st.st_ex_atime;
1876 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1877 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1879 if (lp_dos_filetime_resolution(SNUM(conn))) {
1880 dos_filetime_timespec(&create_date_ts);
1881 dos_filetime_timespec(&mdate_ts);
1882 dos_filetime_timespec(&adate_ts);
1883 dos_filetime_timespec(&cdate_ts);
1886 create_date = convert_timespec_to_time_t(create_date_ts);
1887 mdate = convert_timespec_to_time_t(mdate_ts);
1888 adate = convert_timespec_to_time_t(adate_ts);
1890 /* align the record */
1891 SMB_ASSERT(align >= 1);
1893 off = (int)PTR_DIFF(pdata, base_data);
1894 pad = (off + (align-1)) & ~(align-1);
1897 if (pad && pad > space_remaining) {
1898 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1899 "for padding (wanted %u, had %d)\n",
1902 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1906 /* initialize padding to 0 */
1908 memset(pdata, 0, pad);
1910 space_remaining -= pad;
1912 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1922 switch (info_level) {
1923 case SMB_FIND_INFO_STANDARD:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1925 if(requires_resume_key) {
1929 srv_put_dos_date2(p,0,create_date);
1930 srv_put_dos_date2(p,4,adate);
1931 srv_put_dos_date2(p,8,mdate);
1932 SIVAL(p,12,(uint32_t)file_size);
1933 SIVAL(p,16,(uint32_t)allocation_size);
1937 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1938 p += ucs2_align(base_data, p, 0);
1940 status = srvstr_push(base_data, flags2, p,
1941 fname, PTR_DIFF(end_data, p),
1942 STR_TERMINATE, &len);
1943 if (!NT_STATUS_IS_OK(status)) {
1946 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1948 SCVAL(nameptr, -1, len - 2);
1950 SCVAL(nameptr, -1, 0);
1954 SCVAL(nameptr, -1, len - 1);
1956 SCVAL(nameptr, -1, 0);
1962 case SMB_FIND_EA_SIZE:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1964 if (requires_resume_key) {
1968 srv_put_dos_date2(p,0,create_date);
1969 srv_put_dos_date2(p,4,adate);
1970 srv_put_dos_date2(p,8,mdate);
1971 SIVAL(p,12,(uint32_t)file_size);
1972 SIVAL(p,16,(uint32_t)allocation_size);
1975 unsigned int ea_size = estimate_ea_size(conn, NULL,
1977 SIVAL(p,22,ea_size); /* Extended attributes */
1981 status = srvstr_push(base_data, flags2,
1982 p, fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE | STR_NOALIGN, &len);
1984 if (!NT_STATUS_IS_OK(status)) {
1987 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2000 SCVAL(nameptr,0,len);
2002 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2005 case SMB_FIND_EA_LIST:
2007 struct ea_list *file_list = NULL;
2010 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2012 return NT_STATUS_INVALID_PARAMETER;
2014 if (requires_resume_key) {
2018 srv_put_dos_date2(p,0,create_date);
2019 srv_put_dos_date2(p,4,adate);
2020 srv_put_dos_date2(p,8,mdate);
2021 SIVAL(p,12,(uint32_t)file_size);
2022 SIVAL(p,16,(uint32_t)allocation_size);
2024 p += 22; /* p now points to the EA area. */
2026 status = get_ea_list_from_file(ctx, conn, NULL,
2028 &ea_len, &file_list);
2029 if (!NT_STATUS_IS_OK(status)) {
2032 name_list = ea_list_union(name_list, file_list, &ea_len);
2034 /* We need to determine if this entry will fit in the space available. */
2035 /* Max string size is 255 bytes. */
2036 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2037 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2038 "(wanted %u, had %d)\n",
2039 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2041 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2044 /* Push the ea_data followed by the name. */
2045 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2047 status = srvstr_push(base_data, flags2,
2048 p + 1, fname, PTR_DIFF(end_data, p+1),
2049 STR_TERMINATE | STR_NOALIGN, &len);
2050 if (!NT_STATUS_IS_OK(status)) {
2053 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2066 SCVAL(nameptr,0,len);
2068 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2072 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2073 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2074 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2076 SIVAL(p,0,reskey); p += 4;
2077 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2078 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2079 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2080 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2081 SOFF_T(p,0,file_size); p += 8;
2082 SOFF_T(p,0,allocation_size); p += 8;
2083 SIVAL(p,0,mode); p += 4;
2084 q = p; p += 4; /* q is placeholder for name length. */
2085 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2086 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2088 unsigned int ea_size = estimate_ea_size(conn, NULL,
2090 SIVAL(p,0,ea_size); /* Extended attributes */
2093 /* Clear the short name buffer. This is
2094 * IMPORTANT as not doing so will trigger
2095 * a Win2k client bug. JRA.
2097 if (!was_8_3 && check_mangled_names) {
2098 char mangled_name[13]; /* mangled 8.3 name. */
2099 if (!name_to_8_3(fname,mangled_name,True,
2101 /* Error - mangle failed ! */
2102 memset(mangled_name,'\0',12);
2104 mangled_name[12] = 0;
2105 status = srvstr_push(base_data, flags2,
2106 p+2, mangled_name, 24,
2107 STR_UPPER|STR_UNICODE, &len);
2108 if (!NT_STATUS_IS_OK(status)) {
2112 memset(p + 2 + len,'\0',24 - len);
2119 status = srvstr_push(base_data, flags2, p,
2120 fname, PTR_DIFF(end_data, p),
2121 STR_TERMINATE_ASCII, &len);
2122 if (!NT_STATUS_IS_OK(status)) {
2128 len = PTR_DIFF(p, pdata);
2129 pad = (len + (align-1)) & ~(align-1);
2131 * offset to the next entry, the caller
2132 * will overwrite it for the last entry
2133 * that's why we always include the padding
2137 * set padding to zero
2140 memset(p, 0, pad - len);
2147 case SMB_FIND_FILE_DIRECTORY_INFO:
2148 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2150 SIVAL(p,0,reskey); p += 4;
2151 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2152 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2153 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2154 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2155 SOFF_T(p,0,file_size); p += 8;
2156 SOFF_T(p,0,allocation_size); p += 8;
2157 SIVAL(p,0,mode); p += 4;
2158 status = srvstr_push(base_data, flags2,
2159 p + 4, fname, PTR_DIFF(end_data, p+4),
2160 STR_TERMINATE_ASCII, &len);
2161 if (!NT_STATUS_IS_OK(status)) {
2167 len = PTR_DIFF(p, pdata);
2168 pad = (len + (align-1)) & ~(align-1);
2170 * offset to the next entry, the caller
2171 * will overwrite it for the last entry
2172 * that's why we always include the padding
2176 * set padding to zero
2179 memset(p, 0, pad - len);
2186 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2187 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2189 SIVAL(p,0,reskey); p += 4;
2190 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2191 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2192 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2193 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2194 SOFF_T(p,0,file_size); p += 8;
2195 SOFF_T(p,0,allocation_size); p += 8;
2196 SIVAL(p,0,mode); p += 4;
2197 q = p; p += 4; /* q is placeholder for name length. */
2198 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2199 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2201 unsigned int ea_size = estimate_ea_size(conn, NULL,
2203 SIVAL(p,0,ea_size); /* Extended attributes */
2206 status = srvstr_push(base_data, flags2, p,
2207 fname, PTR_DIFF(end_data, p),
2208 STR_TERMINATE_ASCII, &len);
2209 if (!NT_STATUS_IS_OK(status)) {
2215 len = PTR_DIFF(p, pdata);
2216 pad = (len + (align-1)) & ~(align-1);
2218 * offset to the next entry, the caller
2219 * will overwrite it for the last entry
2220 * that's why we always include the padding
2224 * set padding to zero
2227 memset(p, 0, pad - len);
2234 case SMB_FIND_FILE_NAMES_INFO:
2235 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2237 SIVAL(p,0,reskey); p += 4;
2239 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2240 acl on a dir (tridge) */
2241 status = srvstr_push(base_data, flags2, p,
2242 fname, PTR_DIFF(end_data, p),
2243 STR_TERMINATE_ASCII, &len);
2244 if (!NT_STATUS_IS_OK(status)) {
2250 len = PTR_DIFF(p, pdata);
2251 pad = (len + (align-1)) & ~(align-1);
2253 * offset to the next entry, the caller
2254 * will overwrite it for the last entry
2255 * that's why we always include the padding
2259 * set padding to zero
2262 memset(p, 0, pad - len);
2269 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2270 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2272 SIVAL(p,0,reskey); p += 4;
2273 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2274 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2275 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2276 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2277 SOFF_T(p,0,file_size); p += 8;
2278 SOFF_T(p,0,allocation_size); p += 8;
2279 SIVAL(p,0,mode); p += 4;
2280 q = p; p += 4; /* q is placeholder for name length. */
2281 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2282 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2284 unsigned int ea_size = estimate_ea_size(conn, NULL,
2286 SIVAL(p,0,ea_size); /* Extended attributes */
2289 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2290 SBVAL(p,0,file_id); p += 8;
2291 status = srvstr_push(base_data, flags2, p,
2292 fname, PTR_DIFF(end_data, p),
2293 STR_TERMINATE_ASCII, &len);
2294 if (!NT_STATUS_IS_OK(status)) {
2300 len = PTR_DIFF(p, pdata);
2301 pad = (len + (align-1)) & ~(align-1);
2303 * offset to the next entry, the caller
2304 * will overwrite it for the last entry
2305 * that's why we always include the padding
2309 * set padding to zero
2312 memset(p, 0, pad - len);
2319 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2320 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2321 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2323 SIVAL(p,0,reskey); p += 4;
2324 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2325 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2326 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2327 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2328 SOFF_T(p,0,file_size); p += 8;
2329 SOFF_T(p,0,allocation_size); p += 8;
2330 SIVAL(p,0,mode); p += 4;
2331 q = p; p += 4; /* q is placeholder for name length */
2332 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2333 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2334 } else if (readdir_attr_data &&
2335 readdir_attr_data->type == RDATTR_AAPL) {
2337 * OS X specific SMB2 extension negotiated via
2338 * AAPL create context: return max_access in
2341 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2343 unsigned int ea_size = estimate_ea_size(conn, NULL,
2345 SIVAL(p,0,ea_size); /* Extended attributes */
2349 if (readdir_attr_data &&
2350 readdir_attr_data->type == RDATTR_AAPL) {
2352 * OS X specific SMB2 extension negotiated via
2353 * AAPL create context: return resource fork
2354 * length and compressed FinderInfo in
2357 * According to documentation short_name_len
2358 * should be 0, but on the wire behaviour
2359 * shows its set to 24 by clients.
2363 /* Resourefork length */
2364 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2366 /* Compressed FinderInfo */
2367 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2368 } else if (!was_8_3 && check_mangled_names) {
2369 char mangled_name[13]; /* mangled 8.3 name. */
2370 if (!name_to_8_3(fname,mangled_name,True,
2372 /* Error - mangle failed ! */
2373 memset(mangled_name,'\0',12);
2375 mangled_name[12] = 0;
2376 status = srvstr_push(base_data, flags2,
2377 p+2, mangled_name, 24,
2378 STR_UPPER|STR_UNICODE, &len);
2379 if (!NT_STATUS_IS_OK(status)) {
2384 memset(p + 2 + len,'\0',24 - len);
2388 /* Clear the short name buffer. This is
2389 * IMPORTANT as not doing so will trigger
2390 * a Win2k client bug. JRA.
2397 if (readdir_attr_data &&
2398 readdir_attr_data->type == RDATTR_AAPL) {
2400 * OS X specific SMB2 extension negotiated via
2401 * AAPL create context: return UNIX mode in
2404 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2405 SSVAL(p, 0, aapl_mode);
2411 SBVAL(p,0,file_id); p += 8;
2412 status = srvstr_push(base_data, flags2, p,
2413 fname, PTR_DIFF(end_data, p),
2414 STR_TERMINATE_ASCII, &len);
2415 if (!NT_STATUS_IS_OK(status)) {
2421 len = PTR_DIFF(p, pdata);
2422 pad = (len + (align-1)) & ~(align-1);
2424 * offset to the next entry, the caller
2425 * will overwrite it for the last entry
2426 * that's why we always include the padding
2430 * set padding to zero
2433 memset(p, 0, pad - len);
2440 /* CIFS UNIX Extension. */
2442 case SMB_FIND_FILE_UNIX:
2443 case SMB_FIND_FILE_UNIX_INFO2:
2445 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2447 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2449 if (info_level == SMB_FIND_FILE_UNIX) {
2450 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2451 p = store_file_unix_basic(conn, p,
2452 NULL, &smb_fname->st);
2453 status = srvstr_push(base_data, flags2, p,
2454 fname, PTR_DIFF(end_data, p),
2455 STR_TERMINATE, &len);
2456 if (!NT_STATUS_IS_OK(status)) {
2460 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2461 p = store_file_unix_basic_info2(conn, p,
2462 NULL, &smb_fname->st);
2465 status = srvstr_push(base_data, flags2, p, fname,
2466 PTR_DIFF(end_data, p), 0, &len);
2467 if (!NT_STATUS_IS_OK(status)) {
2470 SIVAL(nameptr, 0, len);
2475 len = PTR_DIFF(p, pdata);
2476 pad = (len + (align-1)) & ~(align-1);
2478 * offset to the next entry, the caller
2479 * will overwrite it for the last entry
2480 * that's why we always include the padding
2484 * set padding to zero
2487 memset(p, 0, pad - len);
2492 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2497 return NT_STATUS_INVALID_LEVEL;
2500 if (PTR_DIFF(p,pdata) > space_remaining) {
2501 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2502 "(wanted %u, had %d)\n",
2503 (unsigned int)PTR_DIFF(p,pdata),
2505 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2508 /* Setup the last entry pointer, as an offset from base_data */
2509 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2510 /* Advance the data pointer to the next slot */
2513 return NT_STATUS_OK;
2516 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2517 connection_struct *conn,
2518 struct dptr_struct *dirptr,
2520 const char *path_mask,
2523 int requires_resume_key,
2532 int space_remaining,
2533 struct smb_filename **_smb_fname,
2534 bool *got_exact_match,
2535 int *_last_entry_off,
2536 struct ea_list *name_list,
2537 struct file_id *file_id)
2540 const char *mask = NULL;
2541 long prev_dirpos = 0;
2544 struct smb_filename *smb_fname = NULL;
2545 struct smbd_dirptr_lanman2_state state;
2547 uint64_t last_entry_off = 0;
2549 enum mangled_names_options mangled_names;
2550 bool marshall_with_83_names;
2552 mangled_names = lp_mangled_names(conn->params);
2556 state.info_level = info_level;
2557 if (mangled_names != MANGLED_NAMES_NO) {
2558 state.check_mangled_names = true;
2560 state.has_wild = dptr_has_wild(dirptr);
2561 state.got_exact_match = false;
2563 *got_exact_match = false;
2565 p = strrchr_m(path_mask,'/');
2576 ok = smbd_dirptr_get_entry(ctx,
2583 smbd_dirptr_lanman2_match_fn,
2584 smbd_dirptr_lanman2_mode_fn,
2591 return NT_STATUS_END_OF_FILE;
2594 *got_exact_match = state.got_exact_match;
2596 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2598 status = smbd_marshall_dir_entry(ctx,
2603 marshall_with_83_names,
2604 requires_resume_key,
2615 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2616 DEBUG(1,("Conversion error: illegal character: %s\n",
2617 smb_fname_str_dbg(smb_fname)));
2620 if (file_id != NULL) {
2621 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2624 if (!NT_STATUS_IS_OK(status) &&
2625 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2627 TALLOC_FREE(smb_fname);
2632 if (_smb_fname != NULL) {
2633 struct smb_filename *name = NULL;
2635 name = synthetic_smb_fname(ctx,
2642 TALLOC_FREE(smb_fname);
2644 return NT_STATUS_NO_MEMORY;
2649 TALLOC_FREE(smb_fname);
2652 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2653 dptr_SeekDir(dirptr, prev_dirpos);
2657 *_last_entry_off = last_entry_off;
2658 return NT_STATUS_OK;
2661 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2662 connection_struct *conn,
2663 struct dptr_struct *dirptr,
2665 const char *path_mask,
2668 bool requires_resume_key,
2674 int space_remaining,
2675 bool *got_exact_match,
2676 int *last_entry_off,
2677 struct ea_list *name_list)
2680 const bool do_pad = true;
2682 if (info_level >= 1 && info_level <= 3) {
2683 /* No alignment on earlier info levels. */
2687 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2688 path_mask, dirtype, info_level,
2689 requires_resume_key, dont_descend, ask_sharemode,
2690 true, align, do_pad,
2691 ppdata, base_data, end_data,
2695 last_entry_off, name_list, NULL);
2698 /****************************************************************************
2699 Reply to a TRANS2_FINDFIRST.
2700 ****************************************************************************/
2702 static void call_trans2findfirst(connection_struct *conn,
2703 struct smb_request *req,
2704 char **pparams, int total_params,
2705 char **ppdata, int total_data,
2706 unsigned int max_data_bytes)
2708 /* We must be careful here that we don't return more than the
2709 allowed number of data bytes. If this means returning fewer than
2710 maxentries then so be it. We assume that the redirector has
2711 enough room for the fixed number of parameter bytes it has
2713 struct smb_filename *smb_dname = NULL;
2714 char *params = *pparams;
2715 char *pdata = *ppdata;
2719 uint16_t findfirst_flags;
2720 bool close_after_first;
2722 bool requires_resume_key;
2724 char *directory = NULL;
2727 int last_entry_off=0;
2731 bool finished = False;
2732 bool dont_descend = False;
2733 bool out_of_space = False;
2734 int space_remaining;
2735 bool mask_contains_wcard = False;
2736 struct ea_list *ea_list = NULL;
2737 NTSTATUS ntstatus = NT_STATUS_OK;
2738 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2739 struct smbd_server_connection *sconn = req->sconn;
2740 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2741 ucf_flags_from_smb_request(req);
2742 bool backup_priv = false;
2743 bool as_root = false;
2744 files_struct *fsp = NULL;
2745 const struct loadparm_substitution *lp_sub =
2746 loadparm_s3_global_substitution();
2749 if (total_params < 13) {
2750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2754 dirtype = SVAL(params,0);
2755 maxentries = SVAL(params,2);
2756 findfirst_flags = SVAL(params,4);
2757 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2758 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2759 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2760 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2761 security_token_has_privilege(get_current_nttok(conn),
2764 info_level = SVAL(params,6);
2766 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2767 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2768 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2770 info_level, max_data_bytes));
2773 /* W2K3 seems to treat zero as 1. */
2777 switch (info_level) {
2778 case SMB_FIND_INFO_STANDARD:
2779 case SMB_FIND_EA_SIZE:
2780 case SMB_FIND_EA_LIST:
2781 case SMB_FIND_FILE_DIRECTORY_INFO:
2782 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2783 case SMB_FIND_FILE_NAMES_INFO:
2784 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2785 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2786 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2788 case SMB_FIND_FILE_UNIX:
2789 case SMB_FIND_FILE_UNIX_INFO2:
2790 /* Always use filesystem for UNIX mtime query. */
2791 ask_sharemode = false;
2792 if (!lp_unix_extensions()) {
2793 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2796 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2799 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2803 if (req->posix_pathnames) {
2804 srvstr_get_path_wcard_posix(talloc_tos(),
2812 &mask_contains_wcard);
2814 srvstr_get_path_wcard(talloc_tos(),
2822 &mask_contains_wcard);
2824 if (!NT_STATUS_IS_OK(ntstatus)) {
2825 reply_nterror(req, ntstatus);
2832 ntstatus = filename_convert_with_privilege(talloc_tos(),
2837 &mask_contains_wcard,
2840 ntstatus = filename_convert(talloc_tos(), conn,
2844 &mask_contains_wcard,
2848 if (!NT_STATUS_IS_OK(ntstatus)) {
2849 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2850 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2851 ERRSRV, ERRbadpath);
2854 reply_nterror(req, ntstatus);
2858 mask = get_original_lcomp(talloc_tos(),
2863 reply_nterror(req, NT_STATUS_NO_MEMORY);
2867 directory = smb_dname->base_name;
2869 p = strrchr_m(directory,'/');
2871 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2872 if((directory[0] == '.') && (directory[1] == '\0')) {
2873 mask = talloc_strdup(talloc_tos(),"*");
2875 reply_nterror(req, NT_STATUS_NO_MEMORY);
2878 mask_contains_wcard = True;
2884 if (p == NULL || p == directory) {
2885 /* Ensure we don't have a directory name of "". */
2886 directory = talloc_strdup(talloc_tos(), ".");
2888 reply_nterror(req, NT_STATUS_NO_MEMORY);
2891 /* Ensure smb_dname->base_name matches. */
2892 smb_dname->base_name = directory;
2895 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2897 if (info_level == SMB_FIND_EA_LIST) {
2900 if (total_data < 4) {
2901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2905 ea_size = IVAL(pdata,0);
2906 if (ea_size != total_data) {
2907 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2908 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2913 if (!lp_ea_support(SNUM(conn))) {
2914 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2918 /* Pull out the list of names. */
2919 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2926 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2931 *ppdata = (char *)SMB_REALLOC(
2932 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2933 if(*ppdata == NULL ) {
2934 reply_nterror(req, NT_STATUS_NO_MEMORY);
2938 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2940 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2943 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2944 /* Realloc the params space */
2945 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2946 if (*pparams == NULL) {
2947 reply_nterror(req, NT_STATUS_NO_MEMORY);
2953 * As we've cut off the last component from
2954 * smb_fname we need to re-stat smb_dname
2955 * so FILE_OPEN disposition knows the directory
2958 if (req->posix_pathnames) {
2959 ret = SMB_VFS_LSTAT(conn, smb_dname);
2961 ret = SMB_VFS_STAT(conn, smb_dname);
2965 ntstatus = map_nt_error_from_unix(errno);
2966 reply_nterror(req, ntstatus);
2971 * Open an fsp on this directory for the dptr.
2973 ntstatus = SMB_VFS_CREATE_FILE(
2976 0, /* root_dir_fid */
2977 smb_dname, /* dname */
2978 FILE_LIST_DIRECTORY, /* access_mask */
2980 FILE_SHARE_WRITE, /* share_access */
2981 FILE_OPEN, /* create_disposition*/
2982 FILE_DIRECTORY_FILE, /* create_options */
2983 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2984 NO_OPLOCK, /* oplock_request */
2986 0, /* allocation_size */
2987 0, /* private_flags */
2992 NULL, /* in_context */
2993 NULL);/* out_context */
2995 if (!NT_STATUS_IS_OK(ntstatus)) {
2996 DBG_ERR("failed to open directory %s\n",
2997 smb_fname_str_dbg(smb_dname));
2998 reply_nterror(req, ntstatus);
3002 /* Save the wildcard match and attribs we are using on this directory -
3003 needed as lanman2 assumes these are being saved between calls */
3005 ntstatus = dptr_create(conn,
3012 mask_contains_wcard,
3016 if (!NT_STATUS_IS_OK(ntstatus)) {
3018 * Use NULL here for the first parameter (req)
3019 * as this is not a client visible handle so
3020 * can'tbe part of an SMB1 chain.
3022 close_file(NULL, fsp, NORMAL_CLOSE);
3024 reply_nterror(req, ntstatus);
3029 /* Remember this in case we have
3030 to do a findnext. */
3031 dptr_set_priv(fsp->dptr);
3034 dptr_num = dptr_dnum(fsp->dptr);
3035 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3037 /* We don't need to check for VOL here as this is returned by
3038 a different TRANS2 call. */
3040 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3041 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3042 if (in_list(directory,
3043 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3044 conn->case_sensitive)) {
3045 dont_descend = True;
3049 space_remaining = max_data_bytes;
3050 out_of_space = False;
3052 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3053 bool got_exact_match = False;
3055 /* this is a heuristic to avoid seeking the dirptr except when
3056 absolutely necessary. It allows for a filename of about 40 chars */
3057 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3058 out_of_space = True;
3061 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3065 mask,dirtype,info_level,
3066 requires_resume_key,dont_descend,
3071 &last_entry_off, ea_list);
3072 if (NT_STATUS_EQUAL(ntstatus,
3073 NT_STATUS_ILLEGAL_CHARACTER)) {
3075 * Bad character conversion on name. Ignore this
3080 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3081 out_of_space = true;
3083 finished = !NT_STATUS_IS_OK(ntstatus);
3087 if (!finished && !out_of_space)
3091 * As an optimisation if we know we aren't looking
3092 * for a wildcard name (ie. the name matches the wildcard exactly)
3093 * then we can finish on any (first) match.
3094 * This speeds up large directory searches. JRA.
3100 /* Ensure space_remaining never goes -ve. */
3101 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3102 space_remaining = 0;
3103 out_of_space = true;
3105 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3109 /* Check if we can close the dirptr */
3110 if(close_after_first || (finished && close_if_end)) {
3111 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3113 close_file(NULL, fsp, NORMAL_CLOSE);
3118 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3119 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3120 * the protocol level is less than NT1. Tested with smbclient. JRA.
3121 * This should fix the OS/2 client bug #2335.
3124 if(numentries == 0) {
3127 * We may have already closed the file in the
3128 * close_after_first or finished case above.
3131 close_file(NULL, fsp, NORMAL_CLOSE);
3134 if (get_Protocol() < PROTOCOL_NT1) {
3135 reply_force_doserror(req, ERRDOS, ERRnofiles);
3138 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3139 ERRDOS, ERRbadfile);
3144 /* At this point pdata points to numentries directory entries. */
3146 /* Set up the return parameter block */
3147 SSVAL(params,0,dptr_num);
3148 SSVAL(params,2,numentries);
3149 SSVAL(params,4,finished);
3150 SSVAL(params,6,0); /* Never an EA error */
3151 SSVAL(params,8,last_entry_off);
3153 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3156 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3157 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3159 reply_nterror(req, NT_STATUS_NO_MEMORY);
3163 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3164 smb_fn_name(req->cmd),
3165 mask, directory, dirtype, numentries ) );
3168 * Force a name mangle here to ensure that the
3169 * mask as an 8.3 name is top of the mangled cache.
3170 * The reasons for this are subtle. Don't remove
3171 * this code unless you know what you are doing
3172 * (see PR#13758). JRA.
3175 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3176 char mangled_name[13];
3177 name_to_8_3(mask, mangled_name, True, conn->params);
3185 TALLOC_FREE(smb_dname);
3189 /****************************************************************************
3190 Reply to a TRANS2_FINDNEXT.
3191 ****************************************************************************/
3193 static void call_trans2findnext(connection_struct *conn,
3194 struct smb_request *req,
3195 char **pparams, int total_params,
3196 char **ppdata, int total_data,
3197 unsigned int max_data_bytes)
3199 /* We must be careful here that we don't return more than the
3200 allowed number of data bytes. If this means returning fewer than
3201 maxentries then so be it. We assume that the redirector has
3202 enough room for the fixed number of parameter bytes it has
3204 char *params = *pparams;
3205 char *pdata = *ppdata;
3209 uint16_t info_level;
3210 uint32_t resume_key;
3211 uint16_t findnext_flags;
3212 bool close_after_request;
3214 bool requires_resume_key;
3216 bool mask_contains_wcard = False;
3217 char *resume_name = NULL;
3218 const char *mask = NULL;
3219 const char *directory = NULL;
3223 int i, last_entry_off=0;
3224 bool finished = False;
3225 bool dont_descend = False;
3226 bool out_of_space = False;
3227 int space_remaining;
3228 struct ea_list *ea_list = NULL;
3229 NTSTATUS ntstatus = NT_STATUS_OK;
3230 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3231 TALLOC_CTX *ctx = talloc_tos();
3232 struct smbd_server_connection *sconn = req->sconn;
3233 bool backup_priv = false;
3234 bool as_root = false;
3235 files_struct *fsp = NULL;
3236 const struct loadparm_substitution *lp_sub =
3237 loadparm_s3_global_substitution();
3239 if (total_params < 13) {
3240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3244 dptr_num = SVAL(params,0);
3245 maxentries = SVAL(params,2);
3246 info_level = SVAL(params,4);
3247 resume_key = IVAL(params,6);
3248 findnext_flags = SVAL(params,10);
3249 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3250 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3251 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3252 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3254 if (!continue_bit) {
3255 /* We only need resume_name if continue_bit is zero. */
3256 if (req->posix_pathnames) {
3257 srvstr_get_path_wcard_posix(ctx,
3265 &mask_contains_wcard);
3267 srvstr_get_path_wcard(ctx,
3275 &mask_contains_wcard);
3277 if (!NT_STATUS_IS_OK(ntstatus)) {
3278 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3279 complain (it thinks we're asking for the directory above the shared
3280 path or an invalid name). Catch this as the resume name is only compared, never used in
3281 a file access. JRA. */
3282 srvstr_pull_talloc(ctx, params, req->flags2,
3283 &resume_name, params+12,
3287 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3288 reply_nterror(req, ntstatus);
3294 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3295 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3296 resume_key = %d resume name = %s continue=%d level = %d\n",
3297 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3298 requires_resume_key, resume_key,
3299 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3302 /* W2K3 seems to treat zero as 1. */
3306 switch (info_level) {
3307 case SMB_FIND_INFO_STANDARD:
3308 case SMB_FIND_EA_SIZE:
3309 case SMB_FIND_EA_LIST:
3310 case SMB_FIND_FILE_DIRECTORY_INFO:
3311 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3312 case SMB_FIND_FILE_NAMES_INFO:
3313 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3314 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3315 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3317 case SMB_FIND_FILE_UNIX:
3318 case SMB_FIND_FILE_UNIX_INFO2:
3319 /* Always use filesystem for UNIX mtime query. */
3320 ask_sharemode = false;
3321 if (!lp_unix_extensions()) {
3322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3327 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3331 if (info_level == SMB_FIND_EA_LIST) {
3334 if (total_data < 4) {
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3339 ea_size = IVAL(pdata,0);
3340 if (ea_size != total_data) {
3341 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3342 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3347 if (!lp_ea_support(SNUM(conn))) {
3348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3352 /* Pull out the list of names. */
3353 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3360 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3365 *ppdata = (char *)SMB_REALLOC(
3366 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3367 if(*ppdata == NULL) {
3368 reply_nterror(req, NT_STATUS_NO_MEMORY);
3373 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3376 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3379 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3380 /* Realloc the params space */
3381 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3382 if(*pparams == NULL ) {
3383 reply_nterror(req, NT_STATUS_NO_MEMORY);
3389 /* Check that the dptr is valid */
3390 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3392 reply_nterror(req, STATUS_NO_MORE_FILES);
3396 directory = dptr_path(sconn, dptr_num);
3398 /* Get the wildcard mask from the dptr */
3399 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3400 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3401 reply_nterror(req, STATUS_NO_MORE_FILES);
3405 /* Get the attr mask from the dptr */
3406 dirtype = dptr_attr(sconn, dptr_num);
3408 backup_priv = dptr_get_priv(fsp->dptr);
3410 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3411 "backup_priv = %d\n",
3412 dptr_num, mask, dirtype,
3414 dptr_TellDir(fsp->dptr),
3417 /* We don't need to check for VOL here as this is returned by
3418 a different TRANS2 call. */
3420 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3421 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3422 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3423 dont_descend = True;
3426 space_remaining = max_data_bytes;
3427 out_of_space = False;
3435 * Seek to the correct position. We no longer use the resume key but
3436 * depend on the last file name instead.
3439 if(!continue_bit && resume_name && *resume_name) {
3442 long current_pos = 0;
3444 * Remember, name_to_8_3 is called by
3445 * get_lanman2_dir_entry(), so the resume name
3446 * could be mangled. Ensure we check the unmangled name.
3449 if (mangle_is_mangled(resume_name, conn->params)) {
3450 char *new_resume_name = NULL;
3451 mangle_lookup_name_from_8_3(ctx,
3455 if (new_resume_name) {
3456 resume_name = new_resume_name;
3461 * Fix for NT redirector problem triggered by resume key indexes
3462 * changing between directory scans. We now return a resume key of 0
3463 * and instead look for the filename to continue from (also given
3464 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3465 * findfirst/findnext (as is usual) then the directory pointer
3466 * should already be at the correct place.
3469 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3470 } /* end if resume_name && !continue_bit */
3472 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3473 bool got_exact_match = False;
3475 /* this is a heuristic to avoid seeking the fsp->dptr except when
3476 absolutely necessary. It allows for a filename of about 40 chars */
3477 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3478 out_of_space = True;
3481 ntstatus = get_lanman2_dir_entry(ctx,
3485 mask,dirtype,info_level,
3486 requires_resume_key,dont_descend,
3491 &last_entry_off, ea_list);
3492 if (NT_STATUS_EQUAL(ntstatus,
3493 NT_STATUS_ILLEGAL_CHARACTER)) {
3495 * Bad character conversion on name. Ignore this
3500 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3501 out_of_space = true;
3503 finished = !NT_STATUS_IS_OK(ntstatus);
3507 if (!finished && !out_of_space)
3511 * As an optimisation if we know we aren't looking
3512 * for a wildcard name (ie. the name matches the wildcard exactly)
3513 * then we can finish on any (first) match.
3514 * This speeds up large directory searches. JRA.
3520 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3523 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3524 smb_fn_name(req->cmd),
3525 mask, directory, dirtype, numentries ) );
3527 /* Check if we can close the fsp->dptr */
3528 if(close_after_request || (finished && close_if_end)) {
3529 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3531 close_file(NULL, fsp, NORMAL_CLOSE);
3539 /* Set up the return parameter block */
3540 SSVAL(params,0,numentries);
3541 SSVAL(params,2,finished);
3542 SSVAL(params,4,0); /* Never an EA error */
3543 SSVAL(params,6,last_entry_off);
3545 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3551 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3553 const struct loadparm_substitution *lp_sub =
3554 loadparm_s3_global_substitution();
3556 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3560 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3562 SMB_ASSERT(extended_info != NULL);
3564 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3565 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3566 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3567 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3568 #ifdef SAMBA_VERSION_REVISION
3569 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3571 extended_info->samba_subversion = 0;
3572 #ifdef SAMBA_VERSION_RC_RELEASE
3573 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3575 #ifdef SAMBA_VERSION_PRE_RELEASE
3576 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3579 #ifdef SAMBA_VERSION_VENDOR_PATCH
3580 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3582 extended_info->samba_gitcommitdate = 0;
3583 #ifdef SAMBA_VERSION_COMMIT_TIME
3584 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3587 memset(extended_info->samba_version_string, 0,
3588 sizeof(extended_info->samba_version_string));
3590 snprintf (extended_info->samba_version_string,
3591 sizeof(extended_info->samba_version_string),
3592 "%s", samba_version_string());
3595 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3596 connection_struct *conn,
3597 TALLOC_CTX *mem_ctx,
3598 uint16_t info_level,
3600 unsigned int max_data_bytes,
3601 size_t *fixed_portion,
3602 struct smb_filename *fname,
3606 const struct loadparm_substitution *lp_sub =
3607 loadparm_s3_global_substitution();
3608 char *pdata, *end_data;
3611 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3612 int snum = SNUM(conn);
3613 const char *fstype = lp_fstype(SNUM(conn));
3614 const char *filename = NULL;
3615 const uint64_t bytes_per_sector = 512;
3616 uint32_t additional_flags = 0;
3617 struct smb_filename smb_fname;
3619 NTSTATUS status = NT_STATUS_OK;
3622 if (fname == NULL || fname->base_name == NULL) {
3625 filename = fname->base_name;
3629 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3630 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3631 "info level (0x%x) on IPC$.\n",
3632 (unsigned int)info_level));
3633 return NT_STATUS_ACCESS_DENIED;
3637 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3639 ZERO_STRUCT(smb_fname);
3640 smb_fname.base_name = discard_const_p(char, filename);
3642 if(info_level != SMB_FS_QUOTA_INFORMATION
3643 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3644 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3645 return map_nt_error_from_unix(errno);
3650 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3651 return NT_STATUS_INVALID_PARAMETER;
3654 *ppdata = (char *)SMB_REALLOC(
3655 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3656 if (*ppdata == NULL) {
3657 return NT_STATUS_NO_MEMORY;
3661 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3662 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3666 switch (info_level) {
3667 case SMB_INFO_ALLOCATION:
3669 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3671 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3673 if (df_ret == (uint64_t)-1) {
3674 return map_nt_error_from_unix(errno);
3677 block_size = lp_block_size(snum);
3678 if (bsize < block_size) {
3679 uint64_t factor = block_size/bsize;
3684 if (bsize > block_size) {
3685 uint64_t factor = bsize/block_size;
3690 sectors_per_unit = bsize/bytes_per_sector;
3692 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3693 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3694 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3697 * For large drives, return max values and not modulo.
3699 dsize = MIN(dsize, UINT32_MAX);
3700 dfree = MIN(dfree, UINT32_MAX);
3702 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3703 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3704 SIVAL(pdata,l1_cUnit,dsize);
3705 SIVAL(pdata,l1_cUnitAvail,dfree);
3706 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3710 case SMB_INFO_VOLUME:
3711 /* Return volume name */
3713 * Add volume serial number - hash of a combination of
3714 * the called hostname and the service name.
3716 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3718 * Win2k3 and previous mess this up by sending a name length
3719 * one byte short. I believe only older clients (OS/2 Win9x) use
3720 * this call so try fixing this by adding a terminating null to
3721 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3723 status = srvstr_push(
3725 pdata+l2_vol_szVolLabel, vname,
3726 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3727 STR_NOALIGN|STR_TERMINATE, &len);
3728 if (!NT_STATUS_IS_OK(status)) {
3731 SCVAL(pdata,l2_vol_cch,len);
3732 data_len = l2_vol_szVolLabel + len;
3733 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3734 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3735 (unsigned)len, vname));
3738 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3739 case SMB_FS_ATTRIBUTE_INFORMATION:
3741 additional_flags = 0;
3742 #if defined(HAVE_SYS_QUOTAS)
3743 additional_flags |= FILE_VOLUME_QUOTAS;
3746 if(lp_nt_acl_support(SNUM(conn))) {
3747 additional_flags |= FILE_PERSISTENT_ACLS;
3750 /* Capabilities are filled in at connection time through STATVFS call */
3751 additional_flags |= conn->fs_capabilities;
3752 additional_flags |= lp_parm_int(conn->params->service,
3753 "share", "fake_fscaps",
3756 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3757 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3758 additional_flags); /* FS ATTRIBUTES */
3760 SIVAL(pdata,4,255); /* Max filename component length */
3761 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3762 and will think we can't do long filenames */
3763 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3764 PTR_DIFF(end_data, pdata+12),
3766 if (!NT_STATUS_IS_OK(status)) {
3770 data_len = 12 + len;
3771 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3772 /* the client only requested a portion of the
3774 data_len = max_data_bytes;
3775 status = STATUS_BUFFER_OVERFLOW;
3777 *fixed_portion = 16;
3780 case SMB_QUERY_FS_LABEL_INFO:
3781 case SMB_FS_LABEL_INFORMATION:
3782 status = srvstr_push(pdata, flags2, pdata+4, vname,
3783 PTR_DIFF(end_data, pdata+4), 0, &len);
3784 if (!NT_STATUS_IS_OK(status)) {
3791 case SMB_QUERY_FS_VOLUME_INFO:
3792 case SMB_FS_VOLUME_INFORMATION:
3795 * Add volume serial number - hash of a combination of
3796 * the called hostname and the service name.
3798 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3799 (str_checksum(get_local_machine_name())<<16));
3801 /* Max label len is 32 characters. */
3802 status = srvstr_push(pdata, flags2, pdata+18, vname,
3803 PTR_DIFF(end_data, pdata+18),
3805 if (!NT_STATUS_IS_OK(status)) {
3808 SIVAL(pdata,12,len);
3811 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3812 (int)strlen(vname),vname,
3813 lp_servicename(talloc_tos(), lp_sub, snum)));
3814 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3815 /* the client only requested a portion of the
3817 data_len = max_data_bytes;
3818 status = STATUS_BUFFER_OVERFLOW;
3820 *fixed_portion = 24;
3823 case SMB_QUERY_FS_SIZE_INFO:
3824 case SMB_FS_SIZE_INFORMATION:
3826 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3828 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3830 if (df_ret == (uint64_t)-1) {
3831 return map_nt_error_from_unix(errno);
3833 block_size = lp_block_size(snum);
3834 if (bsize < block_size) {
3835 uint64_t factor = block_size/bsize;
3840 if (bsize > block_size) {
3841 uint64_t factor = bsize/block_size;
3846 sectors_per_unit = bsize/bytes_per_sector;
3847 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3848 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3849 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3850 SBIG_UINT(pdata,0,dsize);
3851 SBIG_UINT(pdata,8,dfree);
3852 SIVAL(pdata,16,sectors_per_unit);
3853 SIVAL(pdata,20,bytes_per_sector);
3854 *fixed_portion = 24;
3858 case SMB_FS_FULL_SIZE_INFORMATION:
3860 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3862 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3864 if (df_ret == (uint64_t)-1) {
3865 return map_nt_error_from_unix(errno);
3867 block_size = lp_block_size(snum);
3868 if (bsize < block_size) {
3869 uint64_t factor = block_size/bsize;
3874 if (bsize > block_size) {
3875 uint64_t factor = bsize/block_size;
3880 sectors_per_unit = bsize/bytes_per_sector;
3881 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3882 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3883 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3884 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3885 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3886 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3887 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3888 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3889 *fixed_portion = 32;
3893 case SMB_QUERY_FS_DEVICE_INFO:
3894 case SMB_FS_DEVICE_INFORMATION:
3896 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3898 if (!CAN_WRITE(conn)) {
3899 characteristics |= FILE_READ_ONLY_DEVICE;
3902 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3903 SIVAL(pdata,4,characteristics);
3908 #ifdef HAVE_SYS_QUOTAS
3909 case SMB_FS_QUOTA_INFORMATION:
3911 * what we have to send --metze:
3913 * Unknown1: 24 NULL bytes
3914 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3915 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3916 * Quota Flags: 2 byte :
3917 * Unknown3: 6 NULL bytes
3921 * details for Quota Flags:
3923 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3924 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3925 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3926 * 0x0001 Enable Quotas: enable quota for this fs
3930 /* we need to fake up a fsp here,
3931 * because its not send in this call
3934 SMB_NTQUOTA_STRUCT quotas;
3937 ZERO_STRUCT(quotas);
3940 fsp.fnum = FNUM_FIELD_INVALID;
3943 if (get_current_uid(conn) != 0) {
3944 DEBUG(0,("get_user_quota: access_denied "
3945 "service [%s] user [%s]\n",
3946 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3947 conn->session_info->unix_info->unix_name));
3948 return NT_STATUS_ACCESS_DENIED;
3951 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3953 if (!NT_STATUS_IS_OK(status)) {
3954 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3960 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3961 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3963 /* Unknown1 24 NULL bytes*/
3964 SBIG_UINT(pdata,0,(uint64_t)0);
3965 SBIG_UINT(pdata,8,(uint64_t)0);
3966 SBIG_UINT(pdata,16,(uint64_t)0);
3968 /* Default Soft Quota 8 bytes */
3969 SBIG_UINT(pdata,24,quotas.softlim);
3971 /* Default Hard Quota 8 bytes */
3972 SBIG_UINT(pdata,32,quotas.hardlim);
3974 /* Quota flag 2 bytes */
3975 SSVAL(pdata,40,quotas.qflags);
3977 /* Unknown3 6 NULL bytes */
3983 #endif /* HAVE_SYS_QUOTAS */
3984 case SMB_FS_OBJECTID_INFORMATION:
3986 unsigned char objid[16];
3987 struct smb_extended_info extended_info;
3988 memcpy(pdata,create_volume_objectid(conn, objid),16);
3989 samba_extended_info_version (&extended_info);
3990 SIVAL(pdata,16,extended_info.samba_magic);
3991 SIVAL(pdata,20,extended_info.samba_version);
3992 SIVAL(pdata,24,extended_info.samba_subversion);
3993 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3994 memcpy(pdata+36,extended_info.samba_version_string,28);
3999 case SMB_FS_SECTOR_SIZE_INFORMATION:
4003 * These values match a physical Windows Server 2012
4004 * share backed by NTFS atop spinning rust.
4006 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
4007 /* logical_bytes_per_sector */
4008 SIVAL(pdata, 0, bytes_per_sector);
4009 /* phys_bytes_per_sector_atomic */
4010 SIVAL(pdata, 4, bytes_per_sector);
4011 /* phys_bytes_per_sector_perf */
4012 SIVAL(pdata, 8, bytes_per_sector);
4013 /* fs_effective_phys_bytes_per_sector_atomic */
4014 SIVAL(pdata, 12, bytes_per_sector);
4016 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4017 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4018 /* byte_off_sector_align */
4019 SIVAL(pdata, 20, 0);
4020 /* byte_off_partition_align */
4021 SIVAL(pdata, 24, 0);
4022 *fixed_portion = 28;
4028 * Query the version and capabilities of the CIFS UNIX extensions
4032 case SMB_QUERY_CIFS_UNIX_INFO:
4034 bool large_write = lp_min_receive_file_size() &&
4035 !srv_is_signing_active(xconn);
4036 bool large_read = !srv_is_signing_active(xconn);
4037 int encrypt_caps = 0;
4039 if (!lp_unix_extensions()) {
4040 return NT_STATUS_INVALID_LEVEL;
4043 switch (conn->encrypt_level) {
4044 case SMB_SIGNING_OFF:
4047 case SMB_SIGNING_DESIRED:
4048 case SMB_SIGNING_IF_REQUIRED:
4049 case SMB_SIGNING_DEFAULT:
4050 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4052 case SMB_SIGNING_REQUIRED:
4053 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4054 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4055 large_write = false;
4061 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4062 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4064 /* We have POSIX ACLs, pathname, encryption,
4065 * large read/write, and locking capability. */
4067 SBIG_UINT(pdata,4,((uint64_t)(
4068 CIFS_UNIX_POSIX_ACLS_CAP|
4069 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4070 CIFS_UNIX_FCNTL_LOCKS_CAP|
4071 CIFS_UNIX_EXTATTR_CAP|
4072 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4074 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4076 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4080 case SMB_QUERY_POSIX_FS_INFO:
4083 vfs_statvfs_struct svfs;
4085 if (!lp_unix_extensions()) {
4086 return NT_STATUS_INVALID_LEVEL;
4089 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4093 SIVAL(pdata,0,svfs.OptimalTransferSize);
4094 SIVAL(pdata,4,svfs.BlockSize);
4095 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4096 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4097 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4098 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4099 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4100 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4101 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4103 } else if (rc == EOPNOTSUPP) {
4104 return NT_STATUS_INVALID_LEVEL;
4105 #endif /* EOPNOTSUPP */
4107 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4108 return NT_STATUS_DOS(ERRSRV, ERRerror);
4113 case SMB_QUERY_POSIX_WHOAMI:
4119 if (!lp_unix_extensions()) {
4120 return NT_STATUS_INVALID_LEVEL;
4123 if (max_data_bytes < 40) {
4124 return NT_STATUS_BUFFER_TOO_SMALL;
4127 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4128 flags |= SMB_WHOAMI_GUEST;
4131 /* NOTE: 8 bytes for UID/GID, irrespective of native
4132 * platform size. This matches
4133 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4135 data_len = 4 /* flags */
4142 + 4 /* pad/reserved */
4143 + (conn->session_info->unix_token->ngroups * 8)
4145 + (conn->session_info->security_token->num_sids *
4149 SIVAL(pdata, 0, flags);
4150 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4152 (uint64_t)conn->session_info->unix_token->uid);
4153 SBIG_UINT(pdata, 16,
4154 (uint64_t)conn->session_info->unix_token->gid);
4157 if (data_len >= max_data_bytes) {
4158 /* Potential overflow, skip the GIDs and SIDs. */
4160 SIVAL(pdata, 24, 0); /* num_groups */
4161 SIVAL(pdata, 28, 0); /* num_sids */
4162 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4163 SIVAL(pdata, 36, 0); /* reserved */
4169 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4170 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4172 /* We walk the SID list twice, but this call is fairly
4173 * infrequent, and I don't expect that it's performance
4174 * sensitive -- jpeach
4176 for (i = 0, sid_bytes = 0;
4177 i < conn->session_info->security_token->num_sids; ++i) {
4178 sid_bytes += ndr_size_dom_sid(
4179 &conn->session_info->security_token->sids[i],
4183 /* SID list byte count */
4184 SIVAL(pdata, 32, sid_bytes);
4186 /* 4 bytes pad/reserved - must be zero */
4187 SIVAL(pdata, 36, 0);
4191 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4192 SBIG_UINT(pdata, data_len,
4193 (uint64_t)conn->session_info->unix_token->groups[i]);
4199 i < conn->session_info->security_token->num_sids; ++i) {
4200 int sid_len = ndr_size_dom_sid(
4201 &conn->session_info->security_token->sids[i],
4204 sid_linearize((uint8_t *)(pdata + data_len),
4206 &conn->session_info->security_token->sids[i]);
4207 data_len += sid_len;
4213 case SMB_MAC_QUERY_FS_INFO:
4215 * Thursby MAC extension... ONLY on NTFS filesystems
4216 * once we do streams then we don't need this
4218 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4220 SIVAL(pdata,84,0x100); /* Don't support mac... */
4226 return NT_STATUS_INVALID_LEVEL;
4229 *ret_data_len = data_len;
4233 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4234 struct smb_request *req,
4236 const DATA_BLOB *qdata)
4238 const struct loadparm_substitution *lp_sub =
4239 loadparm_s3_global_substitution();
4241 SMB_NTQUOTA_STRUCT quotas;
4243 ZERO_STRUCT(quotas);
4246 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4247 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4248 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4249 conn->session_info->unix_info->unix_name));
4250 return NT_STATUS_ACCESS_DENIED;
4253 if (!check_fsp_ntquota_handle(conn, req,
4255 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4256 return NT_STATUS_INVALID_HANDLE;
4259 /* note: normally there're 48 bytes,
4260 * but we didn't use the last 6 bytes for now
4263 if (qdata->length < 42) {
4264 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4265 (unsigned int)qdata->length));
4266 return NT_STATUS_INVALID_PARAMETER;
4269 /* unknown_1 24 NULL bytes in pdata*/
4271 /* the soft quotas 8 bytes (uint64_t)*/
4272 quotas.softlim = BVAL(qdata->data,24);
4274 /* the hard quotas 8 bytes (uint64_t)*/
4275 quotas.hardlim = BVAL(qdata->data,32);
4277 /* quota_flags 2 bytes **/
4278 quotas.qflags = SVAL(qdata->data,40);
4280 /* unknown_2 6 NULL bytes follow*/
4282 /* now set the quotas */
4283 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4284 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4285 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4286 status = map_nt_error_from_unix(errno);
4288 status = NT_STATUS_OK;
4293 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4294 struct smb_request *req,
4295 TALLOC_CTX *mem_ctx,
4296 uint16_t info_level,
4298 const DATA_BLOB *pdata)
4300 switch (info_level) {
4301 case SMB_FS_QUOTA_INFORMATION:
4303 return smb_set_fsquota(conn,
4312 return NT_STATUS_INVALID_LEVEL;
4315 /****************************************************************************
4316 Reply to a TRANS2_QFSINFO (query filesystem info).
4317 ****************************************************************************/
4319 static void call_trans2qfsinfo(connection_struct *conn,
4320 struct smb_request *req,
4321 char **pparams, int total_params,
4322 char **ppdata, int total_data,
4323 unsigned int max_data_bytes)
4325 char *params = *pparams;
4326 uint16_t info_level;
4328 size_t fixed_portion;
4331 if (total_params < 2) {
4332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4336 info_level = SVAL(params,0);
4338 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4339 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4340 DEBUG(0,("call_trans2qfsinfo: encryption required "
4341 "and info level 0x%x sent.\n",
4342 (unsigned int)info_level));
4343 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4348 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4350 status = smbd_do_qfsinfo(req->xconn, conn, req,
4357 if (!NT_STATUS_IS_OK(status)) {
4358 reply_nterror(req, status);
4362 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4365 DEBUG( 4, ( "%s info_level = %d\n",
4366 smb_fn_name(req->cmd), info_level) );
4371 /****************************************************************************
4372 Reply to a TRANS2_SETFSINFO (set filesystem info).
4373 ****************************************************************************/
4375 static void call_trans2setfsinfo(connection_struct *conn,
4376 struct smb_request *req,
4377 char **pparams, int total_params,
4378 char **ppdata, int total_data,
4379 unsigned int max_data_bytes)
4381 const struct loadparm_substitution *lp_sub =
4382 loadparm_s3_global_substitution();
4383 struct smbXsrv_connection *xconn = req->xconn;
4384 char *pdata = *ppdata;
4385 char *params = *pparams;
4386 uint16_t info_level;
4388 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4389 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4392 if (total_params < 4) {
4393 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4399 info_level = SVAL(params,2);
4402 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4403 info_level != SMB_SET_CIFS_UNIX_INFO) {
4404 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4405 "info level (0x%x) on IPC$.\n",
4406 (unsigned int)info_level));
4407 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4412 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4413 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4414 DEBUG(0,("call_trans2setfsinfo: encryption required "
4415 "and info level 0x%x sent.\n",
4416 (unsigned int)info_level));
4417 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4422 switch(info_level) {
4423 case SMB_SET_CIFS_UNIX_INFO:
4424 if (!lp_unix_extensions()) {
4425 DEBUG(2,("call_trans2setfsinfo: "
4426 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4427 "unix extensions off\n"));
4429 NT_STATUS_INVALID_LEVEL);
4433 /* There should be 12 bytes of capabilities set. */
4434 if (total_data < 12) {
4437 NT_STATUS_INVALID_PARAMETER);
4440 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4441 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4442 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4443 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4444 /* Just print these values for now. */
4445 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4446 "major = %u, minor = %u cap_low = 0x%x, "
4448 (unsigned int)xconn->
4449 smb1.unix_info.client_major,
4450 (unsigned int)xconn->
4451 smb1.unix_info.client_minor,
4452 (unsigned int)xconn->
4453 smb1.unix_info.client_cap_low,
4454 (unsigned int)xconn->
4455 smb1.unix_info.client_cap_high));
4457 /* Here is where we must switch to posix pathname processing... */
4458 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4459 lp_set_posix_pathnames();
4460 mangle_change_to_posix();
4463 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4464 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4465 /* Client that knows how to do posix locks,
4466 * but not posix open/mkdir operations. Set a
4467 * default type for read/write checks. */
4469 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4474 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4477 size_t param_len = 0;
4478 size_t data_len = total_data;
4480 if (!lp_unix_extensions()) {
4483 NT_STATUS_INVALID_LEVEL);
4487 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4490 NT_STATUS_NOT_SUPPORTED);
4494 if (xconn->smb1.echo_handler.trusted_fde) {
4495 DEBUG( 2,("call_trans2setfsinfo: "
4496 "request transport encryption disabled"
4497 "with 'fork echo handler = yes'\n"));
4500 NT_STATUS_NOT_SUPPORTED);
4504 DEBUG( 4,("call_trans2setfsinfo: "
4505 "request transport encryption.\n"));
4507 status = srv_request_encryption_setup(conn,
4508 (unsigned char **)ppdata,
4510 (unsigned char **)pparams,
4513 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4514 !NT_STATUS_IS_OK(status)) {
4515 reply_nterror(req, status);
4519 send_trans2_replies(conn, req,
4527 if (NT_STATUS_IS_OK(status)) {
4528 /* Server-side transport
4529 * encryption is now *on*. */
4530 status = srv_encryption_start(conn);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 char *reason = talloc_asprintf(talloc_tos(),
4533 "Failure in setting "
4534 "up encrypted transport: %s",
4536 exit_server_cleanly(reason);
4542 case SMB_FS_QUOTA_INFORMATION:
4546 .data = (uint8_t *)pdata,
4547 .length = total_data
4549 files_struct *fsp = NULL;
4550 fsp = file_fsp(req, SVAL(params,0));
4552 status = smb_set_fsquota(conn,
4556 if (!NT_STATUS_IS_OK(status)) {
4557 reply_nterror(req, status);
4563 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4565 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4571 * sending this reply works fine,
4572 * but I'm not sure it's the same
4573 * like windows do...
4576 reply_outbuf(req, 10, 0);
4579 #if defined(HAVE_POSIX_ACLS)
4580 /****************************************************************************
4581 Utility function to count the number of entries in a POSIX acl.
4582 ****************************************************************************/
4584 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4586 unsigned int ace_count = 0;
4587 int entry_id = SMB_ACL_FIRST_ENTRY;
4588 SMB_ACL_ENTRY_T entry;
4590 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4592 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4593 entry_id = SMB_ACL_NEXT_ENTRY;
4600 /****************************************************************************
4601 Utility function to marshall a POSIX acl into wire format.
4602 ****************************************************************************/
4604 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4606 int entry_id = SMB_ACL_FIRST_ENTRY;
4607 SMB_ACL_ENTRY_T entry;
4609 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4610 SMB_ACL_TAG_T tagtype;
4611 SMB_ACL_PERMSET_T permset;
4612 unsigned char perms = 0;
4613 unsigned int own_grp;
4616 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4617 entry_id = SMB_ACL_NEXT_ENTRY;
4620 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4621 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4625 if (sys_acl_get_permset(entry, &permset) == -1) {
4626 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4630 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4631 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4632 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4634 SCVAL(pdata,1,perms);
4637 case SMB_ACL_USER_OBJ:
4638 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4639 own_grp = (unsigned int)pst->st_ex_uid;
4640 SIVAL(pdata,2,own_grp);
4645 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4647 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4650 own_grp = (unsigned int)*puid;
4651 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4652 SIVAL(pdata,2,own_grp);
4656 case SMB_ACL_GROUP_OBJ:
4657 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4658 own_grp = (unsigned int)pst->st_ex_gid;
4659 SIVAL(pdata,2,own_grp);
4664 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4666 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4669 own_grp = (unsigned int)*pgid;
4670 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4671 SIVAL(pdata,2,own_grp);
4676 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4677 SIVAL(pdata,2,0xFFFFFFFF);
4678 SIVAL(pdata,6,0xFFFFFFFF);
4681 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4682 SIVAL(pdata,2,0xFFFFFFFF);
4683 SIVAL(pdata,6,0xFFFFFFFF);
4686 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4689 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4696 /****************************************************************************
4697 Store the FILE_UNIX_BASIC info.
4698 ****************************************************************************/
4700 static char *store_file_unix_basic(connection_struct *conn,
4703 const SMB_STRUCT_STAT *psbuf)
4707 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4708 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4710 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4713 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4716 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4717 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4718 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4721 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4725 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4729 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4732 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4733 devno = psbuf->st_ex_rdev;
4735 devno = psbuf->st_ex_dev;
4738 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4742 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4746 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4749 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4753 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4760 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4761 * the chflags(2) (or equivalent) flags.
4763 * XXX: this really should be behind the VFS interface. To do this, we would
4764 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4765 * Each VFS module could then implement its own mapping as appropriate for the
4766 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4768 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4772 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4776 { UF_IMMUTABLE, EXT_IMMUTABLE },
4780 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4784 { UF_HIDDEN, EXT_HIDDEN },
4787 /* Do not remove. We need to guarantee that this array has at least one
4788 * entry to build on HP-UX.
4794 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4795 uint32_t *smb_fflags, uint32_t *smb_fmask)
4799 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4800 *smb_fmask |= info2_flags_map[i].smb_fflag;
4801 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4802 *smb_fflags |= info2_flags_map[i].smb_fflag;
4807 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4808 const uint32_t smb_fflags,
4809 const uint32_t smb_fmask,
4812 uint32_t max_fmask = 0;
4815 *stat_fflags = psbuf->st_ex_flags;
4817 /* For each flags requested in smb_fmask, check the state of the
4818 * corresponding flag in smb_fflags and set or clear the matching
4822 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4823 max_fmask |= info2_flags_map[i].smb_fflag;
4824 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4825 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4826 *stat_fflags |= info2_flags_map[i].stat_fflag;
4828 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4833 /* If smb_fmask is asking to set any bits that are not supported by
4834 * our flag mappings, we should fail.
4836 if ((smb_fmask & max_fmask) != smb_fmask) {
4844 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4845 * of file flags and birth (create) time.
4847 static char *store_file_unix_basic_info2(connection_struct *conn,
4850 const SMB_STRUCT_STAT *psbuf)
4852 uint32_t file_flags = 0;
4853 uint32_t flags_mask = 0;
4855 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4857 /* Create (birth) time 64 bit */
4858 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4861 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4862 SIVAL(pdata, 0, file_flags); /* flags */
4863 SIVAL(pdata, 4, flags_mask); /* mask */
4869 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4870 const struct stream_struct *streams,
4872 unsigned int max_data_bytes,
4873 unsigned int *data_size)
4876 unsigned int ofs = 0;
4878 if (max_data_bytes < 32) {
4879 return NT_STATUS_INFO_LENGTH_MISMATCH;
4882 for (i = 0; i < num_streams; i++) {
4883 unsigned int next_offset;
4885 smb_ucs2_t *namebuf;
4887 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4888 streams[i].name, &namelen) ||
4891 return NT_STATUS_INVALID_PARAMETER;
4895 * name_buf is now null-terminated, we need to marshall as not
4902 * We cannot overflow ...
4904 if ((ofs + 24 + namelen) > max_data_bytes) {
4905 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4907 TALLOC_FREE(namebuf);
4908 return STATUS_BUFFER_OVERFLOW;
4911 SIVAL(data, ofs+4, namelen);
4912 SOFF_T(data, ofs+8, streams[i].size);
4913 SOFF_T(data, ofs+16, streams[i].alloc_size);
4914 memcpy(data+ofs+24, namebuf, namelen);
4915 TALLOC_FREE(namebuf);
4917 next_offset = ofs + 24 + namelen;
4919 if (i == num_streams-1) {
4920 SIVAL(data, ofs, 0);
4923 unsigned int align = ndr_align_size(next_offset, 8);
4925 if ((next_offset + align) > max_data_bytes) {
4926 DEBUG(10, ("refusing to overflow align "
4927 "reply at stream %u\n",
4929 TALLOC_FREE(namebuf);
4930 return STATUS_BUFFER_OVERFLOW;
4933 memset(data+next_offset, 0, align);
4934 next_offset += align;
4936 SIVAL(data, ofs, next_offset - ofs);
4943 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4947 return NT_STATUS_OK;
4950 #if defined(HAVE_POSIX_ACLS)
4951 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4952 struct smb_request *req,
4954 struct smb_filename *smb_fname,
4956 unsigned int data_size_in,
4957 unsigned int *pdata_size_out)
4959 SMB_ACL_T file_acl = NULL;
4960 SMB_ACL_T def_acl = NULL;
4961 uint16_t num_file_acls = 0;
4962 uint16_t num_def_acls = 0;
4963 unsigned int size_needed = 0;
4966 bool close_fsp = false;
4969 * Ensure we always operate on a file descriptor, not just
4973 uint32_t access_mask = SEC_STD_READ_CONTROL|
4974 FILE_READ_ATTRIBUTES|
4975 FILE_WRITE_ATTRIBUTES;
4977 status = get_posix_fsp(conn,
4983 if (!NT_STATUS_IS_OK(status)) {
4989 SMB_ASSERT(fsp != NULL);
4991 status = refuse_symlink(conn,
4994 if (!NT_STATUS_IS_OK(status)) {
4998 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5001 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5002 DBG_INFO("ACLs not implemented on "
5003 "filesystem containing %s\n",
5005 status = NT_STATUS_NOT_IMPLEMENTED;
5009 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5011 * We can only have default POSIX ACLs on
5014 if (!fsp->fsp_flags.is_directory) {
5015 DBG_INFO("Non-directory open %s\n",
5017 status = NT_STATUS_INVALID_HANDLE;
5020 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5022 SMB_ACL_TYPE_DEFAULT,
5024 def_acl = free_empty_sys_acl(conn, def_acl);
5027 num_file_acls = count_acl_entries(conn, file_acl);
5028 num_def_acls = count_acl_entries(conn, def_acl);
5031 if (num_file_acls + num_def_acls < num_file_acls) {
5032 status = NT_STATUS_INVALID_PARAMETER;
5036 size_needed = num_file_acls + num_def_acls;
5039 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5040 * than UINT_MAX, so check by division.
5042 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5043 status = NT_STATUS_INVALID_PARAMETER;
5047 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5048 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5049 status = NT_STATUS_INVALID_PARAMETER;
5052 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5054 if ( data_size_in < size_needed) {
5055 DBG_INFO("data_size too small (%u) need %u\n",
5058 status = NT_STATUS_BUFFER_TOO_SMALL;
5062 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5063 SSVAL(pdata,2,num_file_acls);
5064 SSVAL(pdata,4,num_def_acls);
5065 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5067 ok = marshall_posix_acl(conn,
5072 status = NT_STATUS_INTERNAL_ERROR;
5075 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5077 ok = marshall_posix_acl(conn,
5082 status = NT_STATUS_INTERNAL_ERROR;
5086 *pdata_size_out = size_needed;
5087 status = NT_STATUS_OK;
5093 * Ensure the stat struct in smb_fname is up to
5094 * date. Structure copy.
5096 smb_fname->st = fsp->fsp_name->st;
5097 (void)close_file(req, fsp, NORMAL_CLOSE);
5101 TALLOC_FREE(file_acl);
5102 TALLOC_FREE(def_acl);
5107 /****************************************************************************
5108 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5109 ****************************************************************************/
5111 static void call_trans2qpipeinfo(connection_struct *conn,
5112 struct smb_request *req,
5113 unsigned int tran_call,
5114 char **pparams, int total_params,
5115 char **ppdata, int total_data,
5116 unsigned int max_data_bytes)
5118 char *params = *pparams;
5119 char *pdata = *ppdata;
5120 unsigned int data_size = 0;
5121 unsigned int param_size = 2;
5122 uint16_t info_level;
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5130 if (total_params < 4) {
5131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5135 fsp = file_fsp(req, SVAL(params,0));
5136 if (!fsp_is_np(fsp)) {
5137 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5141 info_level = SVAL(params,2);
5143 *pparams = (char *)SMB_REALLOC(*pparams,2);
5144 if (*pparams == NULL) {
5145 reply_nterror(req, NT_STATUS_NO_MEMORY);
5150 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5154 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5155 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5156 if (*ppdata == NULL ) {
5157 reply_nterror(req, NT_STATUS_NO_MEMORY);
5162 switch (info_level) {
5163 case SMB_FILE_STANDARD_INFORMATION:
5165 SOFF_T(pdata,0,4096LL);
5172 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5176 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5182 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5183 TALLOC_CTX *mem_ctx,
5184 struct smb_request *req,
5185 uint16_t info_level,
5187 struct smb_filename *smb_fname,
5188 bool delete_pending,
5189 struct timespec write_time_ts,
5190 struct ea_list *ea_list,
5191 int lock_data_count,
5194 unsigned int max_data_bytes,
5195 size_t *fixed_portion,
5197 unsigned int *pdata_size)
5199 char *pdata = *ppdata;
5200 char *dstart, *dend;
5201 unsigned int data_size;
5202 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5203 time_t create_time, mtime, atime, c_time;
5204 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5211 uint64_t file_size = 0;
5213 uint64_t allocation_size = 0;
5214 uint64_t file_id = 0;
5215 uint32_t access_mask = 0;
5218 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5219 return NT_STATUS_INVALID_LEVEL;
5222 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5223 smb_fname_str_dbg(smb_fname),
5225 info_level, max_data_bytes));
5227 mode = dos_mode(conn, smb_fname);
5228 nlink = psbuf->st_ex_nlink;
5230 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5234 if ((nlink > 0) && delete_pending) {
5238 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5239 return NT_STATUS_INVALID_PARAMETER;
5242 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5243 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5244 if (*ppdata == NULL) {
5245 return NT_STATUS_NO_MEMORY;
5249 dend = dstart + data_size - 1;
5251 if (!is_omit_timespec(&write_time_ts) &&
5252 !INFO_LEVEL_IS_UNIX(info_level))
5254 update_stat_ex_mtime(psbuf, write_time_ts);
5257 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5258 mtime_ts = psbuf->st_ex_mtime;
5259 atime_ts = psbuf->st_ex_atime;
5260 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5262 if (lp_dos_filetime_resolution(SNUM(conn))) {
5263 dos_filetime_timespec(&create_time_ts);
5264 dos_filetime_timespec(&mtime_ts);
5265 dos_filetime_timespec(&atime_ts);
5266 dos_filetime_timespec(&ctime_ts);
5269 create_time = convert_timespec_to_time_t(create_time_ts);
5270 mtime = convert_timespec_to_time_t(mtime_ts);
5271 atime = convert_timespec_to_time_t(atime_ts);
5272 c_time = convert_timespec_to_time_t(ctime_ts);
5274 p = strrchr_m(smb_fname->base_name,'/');
5276 base_name = smb_fname->base_name;
5280 /* NT expects the name to be in an exact form of the *full*
5281 filename. See the trans2 torture test */
5282 if (ISDOT(base_name)) {
5283 dos_fname = talloc_strdup(mem_ctx, "\\");
5285 return NT_STATUS_NO_MEMORY;
5288 dos_fname = talloc_asprintf(mem_ctx,
5290 smb_fname->base_name);
5292 return NT_STATUS_NO_MEMORY;
5294 if (is_ntfs_stream_smb_fname(smb_fname)) {
5295 dos_fname = talloc_asprintf(dos_fname, "%s",
5296 smb_fname->stream_name);
5298 return NT_STATUS_NO_MEMORY;
5302 string_replace(dos_fname, '/', '\\');
5305 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5308 /* Do we have this path open ? */
5310 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5311 fsp1 = file_find_di_first(conn->sconn, fileid);
5312 if (fsp1 && fsp1->initial_allocation_size) {
5313 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5317 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5318 file_size = get_file_size_stat(psbuf);
5322 pos = fsp->fh->position_information;
5326 access_mask = fsp->access_mask;
5328 /* GENERIC_EXECUTE mapping from Windows */
5329 access_mask = 0x12019F;
5332 /* This should be an index number - looks like
5335 I think this causes us to fail the IFSKIT
5336 BasicFileInformationTest. -tpot */
5337 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5341 switch (info_level) {
5342 case SMB_INFO_STANDARD:
5343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5345 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5346 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5347 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5348 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5349 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5350 SSVAL(pdata,l1_attrFile,mode);
5353 case SMB_INFO_QUERY_EA_SIZE:
5355 unsigned int ea_size =
5356 estimate_ea_size(conn, fsp,
5358 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5360 srv_put_dos_date2(pdata,0,create_time);
5361 srv_put_dos_date2(pdata,4,atime);
5362 srv_put_dos_date2(pdata,8,mtime); /* write time */
5363 SIVAL(pdata,12,(uint32_t)file_size);
5364 SIVAL(pdata,16,(uint32_t)allocation_size);
5365 SSVAL(pdata,20,mode);
5366 SIVAL(pdata,22,ea_size);
5370 case SMB_INFO_IS_NAME_VALID:
5371 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5373 /* os/2 needs this ? really ?*/
5374 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5376 /* This is only reached for qpathinfo */
5380 case SMB_INFO_QUERY_EAS_FROM_LIST:
5382 size_t total_ea_len = 0;
5383 struct ea_list *ea_file_list = NULL;
5384 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5387 get_ea_list_from_file(mem_ctx, conn, fsp,
5389 &total_ea_len, &ea_file_list);
5390 if (!NT_STATUS_IS_OK(status)) {
5394 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5396 if (!ea_list || (total_ea_len > data_size)) {
5398 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5402 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5406 case SMB_INFO_QUERY_ALL_EAS:
5408 /* We have data_size bytes to put EA's into. */
5409 size_t total_ea_len = 0;
5410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5412 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5414 &total_ea_len, &ea_list);
5415 if (!NT_STATUS_IS_OK(status)) {
5419 if (!ea_list || (total_ea_len > data_size)) {
5421 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5425 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5429 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5431 /* This is FileFullEaInformation - 0xF which maps to
5432 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5434 /* We have data_size bytes to put EA's into. */
5435 size_t total_ea_len = 0;
5436 struct ea_list *ea_file_list = NULL;
5438 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5440 /*TODO: add filtering and index handling */
5443 get_ea_list_from_file(mem_ctx, conn, fsp,
5445 &total_ea_len, &ea_file_list);
5446 if (!NT_STATUS_IS_OK(status)) {
5449 if (!ea_file_list) {
5450 return NT_STATUS_NO_EAS_ON_FILE;
5453 status = fill_ea_chained_buffer(mem_ctx,
5457 conn, ea_file_list);
5458 if (!NT_STATUS_IS_OK(status)) {
5464 case SMB_FILE_BASIC_INFORMATION:
5465 case SMB_QUERY_FILE_BASIC_INFO:
5467 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5469 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5475 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5476 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5477 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5478 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5479 SIVAL(pdata,32,mode);
5481 DEBUG(5,("SMB_QFBI - "));
5482 DEBUG(5,("create: %s ", ctime(&create_time)));
5483 DEBUG(5,("access: %s ", ctime(&atime)));
5484 DEBUG(5,("write: %s ", ctime(&mtime)));
5485 DEBUG(5,("change: %s ", ctime(&c_time)));
5486 DEBUG(5,("mode: %x\n", mode));
5487 *fixed_portion = data_size;
5490 case SMB_FILE_STANDARD_INFORMATION:
5491 case SMB_QUERY_FILE_STANDARD_INFO:
5493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5495 SOFF_T(pdata,0,allocation_size);
5496 SOFF_T(pdata,8,file_size);
5497 SIVAL(pdata,16,nlink);
5498 SCVAL(pdata,20,delete_pending?1:0);
5499 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5500 SSVAL(pdata,22,0); /* Padding. */
5501 *fixed_portion = 24;
5504 case SMB_FILE_EA_INFORMATION:
5505 case SMB_QUERY_FILE_EA_INFO:
5507 unsigned int ea_size =
5508 estimate_ea_size(conn, fsp, smb_fname);
5509 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5512 SIVAL(pdata,0,ea_size);
5516 /* Get the 8.3 name - used if NT SMB was negotiated. */
5517 case SMB_QUERY_FILE_ALT_NAME_INFO:
5518 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5520 char mangled_name[13];
5521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5522 if (!name_to_8_3(base_name,mangled_name,
5523 True,conn->params)) {
5524 return NT_STATUS_NO_MEMORY;
5526 status = srvstr_push(dstart, flags2,
5527 pdata+4, mangled_name,
5528 PTR_DIFF(dend, pdata+4),
5530 if (!NT_STATUS_IS_OK(status)) {
5533 data_size = 4 + len;
5539 case SMB_QUERY_FILE_NAME_INFO:
5542 this must be *exactly* right for ACLs on mapped drives to work
5544 status = srvstr_push(dstart, flags2,
5546 PTR_DIFF(dend, pdata+4),
5548 if (!NT_STATUS_IS_OK(status)) {
5551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5552 data_size = 4 + len;
5557 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5559 char *nfname = NULL;
5561 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5562 return NT_STATUS_INVALID_LEVEL;
5565 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5566 if (nfname == NULL) {
5567 return NT_STATUS_NO_MEMORY;
5570 if (ISDOT(nfname)) {
5573 string_replace(nfname, '/', '\\');
5575 if (smb_fname->stream_name != NULL) {
5576 const char *s = smb_fname->stream_name;
5577 const char *e = NULL;
5580 SMB_ASSERT(s[0] != '\0');
5583 * smb_fname->stream_name is in form
5584 * of ':StrEam:$DATA', but we should only
5585 * append ':StrEam' here.
5588 e = strchr(&s[1], ':');
5594 nfname = talloc_strndup_append(nfname, s, n);
5595 if (nfname == NULL) {
5596 return NT_STATUS_NO_MEMORY;
5600 status = srvstr_push(dstart, flags2,
5602 PTR_DIFF(dend, pdata+4),
5604 if (!NT_STATUS_IS_OK(status)) {
5607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5608 data_size = 4 + len;
5614 case SMB_FILE_ALLOCATION_INFORMATION:
5615 case SMB_QUERY_FILE_ALLOCATION_INFO:
5616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5618 SOFF_T(pdata,0,allocation_size);
5621 case SMB_FILE_END_OF_FILE_INFORMATION:
5622 case SMB_QUERY_FILE_END_OF_FILEINFO:
5623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5625 SOFF_T(pdata,0,file_size);
5628 case SMB_QUERY_FILE_ALL_INFO:
5629 case SMB_FILE_ALL_INFORMATION:
5631 unsigned int ea_size =
5632 estimate_ea_size(conn, fsp, smb_fname);
5633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5634 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5635 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5636 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5637 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5638 SIVAL(pdata,32,mode);
5639 SIVAL(pdata,36,0); /* padding. */
5641 SOFF_T(pdata,0,allocation_size);
5642 SOFF_T(pdata,8,file_size);
5643 SIVAL(pdata,16,nlink);
5644 SCVAL(pdata,20,delete_pending);
5645 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5648 SIVAL(pdata,0,ea_size);
5649 pdata += 4; /* EA info */
5650 status = srvstr_push(dstart, flags2,
5652 PTR_DIFF(dend, pdata+4),
5654 if (!NT_STATUS_IS_OK(status)) {
5659 data_size = PTR_DIFF(pdata,(*ppdata));
5660 *fixed_portion = 10;
5664 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5666 unsigned int ea_size =
5667 estimate_ea_size(conn, fsp, smb_fname);
5668 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5669 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5670 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5671 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5672 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5673 SIVAL(pdata, 0x20, mode);
5674 SIVAL(pdata, 0x24, 0); /* padding. */
5675 SBVAL(pdata, 0x28, allocation_size);
5676 SBVAL(pdata, 0x30, file_size);
5677 SIVAL(pdata, 0x38, nlink);
5678 SCVAL(pdata, 0x3C, delete_pending);
5679 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5680 SSVAL(pdata, 0x3E, 0); /* padding */
5681 SBVAL(pdata, 0x40, file_id);
5682 SIVAL(pdata, 0x48, ea_size);
5683 SIVAL(pdata, 0x4C, access_mask);
5684 SBVAL(pdata, 0x50, pos);
5685 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5686 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5690 status = srvstr_push(dstart, flags2,
5692 PTR_DIFF(dend, pdata+4),
5694 if (!NT_STATUS_IS_OK(status)) {
5699 data_size = PTR_DIFF(pdata,(*ppdata));
5700 *fixed_portion = 104;
5703 case SMB_FILE_INTERNAL_INFORMATION:
5705 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5706 SBVAL(pdata, 0, file_id);
5711 case SMB_FILE_ACCESS_INFORMATION:
5712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5713 SIVAL(pdata, 0, access_mask);
5718 case SMB_FILE_NAME_INFORMATION:
5719 /* Pathname with leading '\'. */
5722 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5723 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5724 SIVAL(pdata,0,byte_len);
5725 data_size = 4 + byte_len;
5729 case SMB_FILE_DISPOSITION_INFORMATION:
5730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5732 SCVAL(pdata,0,delete_pending);
5736 case SMB_FILE_POSITION_INFORMATION:
5737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5739 SOFF_T(pdata,0,pos);
5743 case SMB_FILE_MODE_INFORMATION:
5744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5745 SIVAL(pdata,0,mode);
5750 case SMB_FILE_ALIGNMENT_INFORMATION:
5751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5752 SIVAL(pdata,0,0); /* No alignment needed. */
5758 * NT4 server just returns "invalid query" to this - if we try
5759 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5762 /* The first statement above is false - verified using Thursby
5763 * client against NT4 -- gcolley.
5765 case SMB_QUERY_FILE_STREAM_INFO:
5766 case SMB_FILE_STREAM_INFORMATION: {
5767 unsigned int num_streams = 0;
5768 struct stream_struct *streams = NULL;
5770 DEBUG(10,("smbd_do_qfilepathinfo: "
5771 "SMB_FILE_STREAM_INFORMATION\n"));
5773 if (is_ntfs_stream_smb_fname(smb_fname)) {
5774 return NT_STATUS_INVALID_PARAMETER;
5777 status = vfs_streaminfo(conn,
5784 if (!NT_STATUS_IS_OK(status)) {
5785 DEBUG(10, ("could not get stream info: %s\n",
5786 nt_errstr(status)));
5790 status = marshall_stream_info(num_streams, streams,
5791 pdata, max_data_bytes,
5794 if (!NT_STATUS_IS_OK(status)) {
5795 DEBUG(10, ("marshall_stream_info failed: %s\n",
5796 nt_errstr(status)));
5797 TALLOC_FREE(streams);
5801 TALLOC_FREE(streams);
5803 *fixed_portion = 32;
5807 case SMB_QUERY_COMPRESSION_INFO:
5808 case SMB_FILE_COMPRESSION_INFORMATION:
5809 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5810 SOFF_T(pdata,0,file_size);
5811 SIVAL(pdata,8,0); /* ??? */
5812 SIVAL(pdata,12,0); /* ??? */
5814 *fixed_portion = 16;
5817 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5818 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5819 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5820 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5821 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5822 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5823 SOFF_T(pdata,32,allocation_size);
5824 SOFF_T(pdata,40,file_size);
5825 SIVAL(pdata,48,mode);
5826 SIVAL(pdata,52,0); /* ??? */
5828 *fixed_portion = 56;
5831 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5832 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5833 SIVAL(pdata,0,mode);
5840 * CIFS UNIX Extensions.
5843 case SMB_QUERY_FILE_UNIX_BASIC:
5845 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5846 data_size = PTR_DIFF(pdata,(*ppdata));
5848 DEBUG(4,("smbd_do_qfilepathinfo: "
5849 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5850 dump_data(4, (uint8_t *)(*ppdata), data_size);
5854 case SMB_QUERY_FILE_UNIX_INFO2:
5856 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5857 data_size = PTR_DIFF(pdata,(*ppdata));
5861 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5863 for (i=0; i<100; i++)
5864 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5870 case SMB_QUERY_FILE_UNIX_LINK:
5873 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5876 return NT_STATUS_NO_MEMORY;
5879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5881 if(!S_ISLNK(psbuf->st_ex_mode)) {
5882 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5885 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5887 link_len = SMB_VFS_READLINKAT(conn,
5893 if (link_len == -1) {
5894 return map_nt_error_from_unix(errno);
5896 buffer[link_len] = 0;
5897 status = srvstr_push(dstart, flags2,
5899 PTR_DIFF(dend, pdata),
5900 STR_TERMINATE, &len);
5901 if (!NT_STATUS_IS_OK(status)) {
5905 data_size = PTR_DIFF(pdata,(*ppdata));
5910 #if defined(HAVE_POSIX_ACLS)
5911 case SMB_QUERY_POSIX_ACL:
5913 status = smb_query_posix_acl(conn,
5920 if (!NT_STATUS_IS_OK(status)) {
5928 case SMB_QUERY_POSIX_LOCK:
5933 enum brl_type lock_type;
5935 /* We need an open file with a real fd for this. */
5936 if (!fsp || fsp->fh->fd == -1) {
5937 return NT_STATUS_INVALID_LEVEL;
5940 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5945 case POSIX_LOCK_TYPE_READ:
5946 lock_type = READ_LOCK;
5948 case POSIX_LOCK_TYPE_WRITE:
5949 lock_type = WRITE_LOCK;
5951 case POSIX_LOCK_TYPE_UNLOCK:
5953 /* There's no point in asking for an unlock... */
5954 return NT_STATUS_INVALID_PARAMETER;
5957 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5958 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5959 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5961 status = query_lock(fsp,
5968 if (ERROR_WAS_LOCK_DENIED(status)) {
5969 /* Here we need to report who has it locked... */
5970 data_size = POSIX_LOCK_DATA_SIZE;
5972 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5973 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5974 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5975 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5976 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5978 } else if (NT_STATUS_IS_OK(status)) {
5979 /* For success we just return a copy of what we sent
5980 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5981 data_size = POSIX_LOCK_DATA_SIZE;
5982 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5983 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5991 return NT_STATUS_INVALID_LEVEL;
5994 *pdata_size = data_size;
5995 return NT_STATUS_OK;
5998 /****************************************************************************
5999 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6000 file name or file id).
6001 ****************************************************************************/
6003 static void call_trans2qfilepathinfo(connection_struct *conn,
6004 struct smb_request *req,
6005 unsigned int tran_call,
6006 char **pparams, int total_params,
6007 char **ppdata, int total_data,
6008 unsigned int max_data_bytes)
6010 char *params = *pparams;
6011 char *pdata = *ppdata;
6012 uint16_t info_level;
6013 unsigned int data_size = 0;
6014 unsigned int param_size = 2;
6015 struct smb_filename *smb_fname = NULL;
6016 bool delete_pending = False;
6017 struct timespec write_time_ts;
6018 files_struct *fsp = NULL;
6019 struct file_id fileid;
6020 struct ea_list *ea_list = NULL;
6021 int lock_data_count = 0;
6022 char *lock_data = NULL;
6023 size_t fixed_portion;
6024 NTSTATUS status = NT_STATUS_OK;
6027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6031 ZERO_STRUCT(write_time_ts);
6033 if (tran_call == TRANSACT2_QFILEINFO) {
6034 if (total_params < 4) {
6035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6040 call_trans2qpipeinfo(conn, req, tran_call,
6041 pparams, total_params,
6047 fsp = file_fsp(req, SVAL(params,0));
6048 info_level = SVAL(params,2);
6050 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6052 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6053 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6057 /* Initial check for valid fsp ptr. */
6058 if (!check_fsp_open(conn, req, fsp)) {
6062 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6063 if (smb_fname == NULL) {
6064 reply_nterror(req, NT_STATUS_NO_MEMORY);
6068 if(fsp->fake_file_handle) {
6070 * This is actually for the QUOTA_FAKE_FILE --metze
6073 /* We know this name is ok, it's already passed the checks. */
6075 } else if(fsp->fh->fd == -1) {
6077 * This is actually a QFILEINFO on a directory
6078 * handle (returned from an NT SMB). NT5.0 seems
6079 * to do this call. JRA.
6082 if (INFO_LEVEL_IS_UNIX(info_level)) {
6083 /* Always do lstat for UNIX calls. */
6084 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6085 DEBUG(3,("call_trans2qfilepathinfo: "
6086 "SMB_VFS_LSTAT of %s failed "
6088 smb_fname_str_dbg(smb_fname),
6091 map_nt_error_from_unix(errno));
6094 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6095 DEBUG(3,("call_trans2qfilepathinfo: "
6096 "SMB_VFS_STAT of %s failed (%s)\n",
6097 smb_fname_str_dbg(smb_fname),
6100 map_nt_error_from_unix(errno));
6104 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6105 fileid = vfs_file_id_from_sbuf(
6106 conn, &smb_fname->st);
6107 get_file_infos(fileid, fsp->name_hash,
6113 * Original code - this is an open file.
6115 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6116 DEBUG(3, ("fstat of %s failed (%s)\n",
6117 fsp_fnum_dbg(fsp), strerror(errno)));
6119 map_nt_error_from_unix(errno));
6122 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6123 fileid = vfs_file_id_from_sbuf(
6124 conn, &smb_fname->st);
6125 get_file_infos(fileid, fsp->name_hash,
6134 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6137 if (total_params < 7) {
6138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6142 info_level = SVAL(params,0);
6144 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6146 if (INFO_LEVEL_IS_UNIX(info_level)) {
6147 if (!lp_unix_extensions()) {
6148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6151 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6152 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6153 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6154 req->posix_pathnames) {
6155 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6159 if (req->posix_pathnames) {
6160 srvstr_get_path_posix(req,
6169 srvstr_get_path(req,
6178 if (!NT_STATUS_IS_OK(status)) {
6179 reply_nterror(req, status);
6183 status = filename_convert(req,
6190 if (!NT_STATUS_IS_OK(status)) {
6191 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6192 reply_botherror(req,
6193 NT_STATUS_PATH_NOT_COVERED,
6194 ERRSRV, ERRbadpath);
6197 reply_nterror(req, status);
6201 /* If this is a stream, check if there is a delete_pending. */
6202 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6203 && is_ntfs_stream_smb_fname(smb_fname)) {
6204 struct smb_filename *smb_fname_base;
6206 /* Create an smb_filename with stream_name == NULL. */
6207 smb_fname_base = synthetic_smb_fname(
6209 smb_fname->base_name,
6214 if (smb_fname_base == NULL) {
6215 reply_nterror(req, NT_STATUS_NO_MEMORY);
6219 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6220 /* Always do lstat for UNIX calls. */
6221 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6222 DEBUG(3,("call_trans2qfilepathinfo: "
6223 "SMB_VFS_LSTAT of %s failed "
6225 smb_fname_str_dbg(smb_fname_base),
6227 TALLOC_FREE(smb_fname_base);
6229 map_nt_error_from_unix(errno));
6233 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6234 DEBUG(3,("call_trans2qfilepathinfo: "
6235 "fileinfo of %s failed "
6237 smb_fname_str_dbg(smb_fname_base),
6239 TALLOC_FREE(smb_fname_base);
6241 map_nt_error_from_unix(errno));
6246 status = file_name_hash(conn,
6247 smb_fname_str_dbg(smb_fname_base),
6249 if (!NT_STATUS_IS_OK(status)) {
6250 TALLOC_FREE(smb_fname_base);
6251 reply_nterror(req, status);
6255 fileid = vfs_file_id_from_sbuf(conn,
6256 &smb_fname_base->st);
6257 TALLOC_FREE(smb_fname_base);
6258 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6259 if (delete_pending) {
6260 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6265 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6266 /* Always do lstat for UNIX calls. */
6267 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6268 DEBUG(3,("call_trans2qfilepathinfo: "
6269 "SMB_VFS_LSTAT of %s failed (%s)\n",
6270 smb_fname_str_dbg(smb_fname),
6273 map_nt_error_from_unix(errno));
6278 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6279 DEBUG(3,("call_trans2qfilepathinfo: "
6280 "SMB_VFS_STAT of %s failed (%s)\n",
6281 smb_fname_str_dbg(smb_fname),
6284 map_nt_error_from_unix(errno));
6289 status = file_name_hash(conn,
6290 smb_fname_str_dbg(smb_fname),
6292 if (!NT_STATUS_IS_OK(status)) {
6293 reply_nterror(req, status);
6297 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6298 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6299 get_file_infos(fileid, name_hash, &delete_pending,
6303 if (delete_pending) {
6304 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6309 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6310 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6312 info_level,tran_call,total_data));
6314 /* Pull out any data sent here before we realloc. */
6315 switch (info_level) {
6316 case SMB_INFO_QUERY_EAS_FROM_LIST:
6318 /* Pull any EA list from the data portion. */
6321 if (total_data < 4) {
6323 req, NT_STATUS_INVALID_PARAMETER);
6326 ea_size = IVAL(pdata,0);
6328 if (total_data > 0 && ea_size != total_data) {
6329 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6330 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6332 req, NT_STATUS_INVALID_PARAMETER);
6336 if (!lp_ea_support(SNUM(conn))) {
6337 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6341 /* Pull out the list of names. */
6342 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6345 req, NT_STATUS_INVALID_PARAMETER);
6351 case SMB_QUERY_POSIX_LOCK:
6353 if (fsp == NULL || fsp->fh->fd == -1) {
6354 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6358 if (total_data != POSIX_LOCK_DATA_SIZE) {
6360 req, NT_STATUS_INVALID_PARAMETER);
6364 /* Copy the lock range data. */
6365 lock_data = (char *)talloc_memdup(
6366 req, pdata, total_data);
6368 reply_nterror(req, NT_STATUS_NO_MEMORY);
6371 lock_data_count = total_data;
6377 *pparams = (char *)SMB_REALLOC(*pparams,2);
6378 if (*pparams == NULL) {
6379 reply_nterror(req, NT_STATUS_NO_MEMORY);
6386 * draft-leach-cifs-v1-spec-02.txt
6387 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6390 * The requested information is placed in the Data portion of the
6391 * transaction response. For the information levels greater than 0x100,
6392 * the transaction response has 1 parameter word which should be
6393 * ignored by the client.
6395 * However Windows only follows this rule for the IS_NAME_VALID call.
6397 switch (info_level) {
6398 case SMB_INFO_IS_NAME_VALID:
6403 if ((info_level & 0xFF00) == 0xFF00) {
6405 * We use levels that start with 0xFF00
6406 * internally to represent SMB2 specific levels
6408 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6412 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6414 delete_pending, write_time_ts,
6416 lock_data_count, lock_data,
6417 req->flags2, max_data_bytes,
6419 ppdata, &data_size);
6420 if (!NT_STATUS_IS_OK(status)) {
6421 if (open_was_deferred(req->xconn, req->mid)) {
6422 /* We have re-scheduled this call. */
6425 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6426 bool ok = defer_smb1_sharing_violation(req);
6431 reply_nterror(req, status);
6434 if (fixed_portion > max_data_bytes) {
6435 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6439 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6445 /****************************************************************************
6446 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6448 ****************************************************************************/
6450 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6451 connection_struct *conn,
6452 struct smb_request *req,
6453 bool overwrite_if_exists,
6454 const struct smb_filename *smb_fname_old,
6455 struct smb_filename *smb_fname_new)
6457 NTSTATUS status = NT_STATUS_OK;
6461 /* source must already exist. */
6462 if (!VALID_STAT(smb_fname_old->st)) {
6463 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6466 if (VALID_STAT(smb_fname_new->st)) {
6467 if (overwrite_if_exists) {
6468 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6469 return NT_STATUS_FILE_IS_A_DIRECTORY;
6471 status = unlink_internals(conn,
6473 FILE_ATTRIBUTE_NORMAL,
6476 if (!NT_STATUS_IS_OK(status)) {
6480 /* Disallow if newname already exists. */
6481 return NT_STATUS_OBJECT_NAME_COLLISION;
6485 /* No links from a directory. */
6486 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6487 return NT_STATUS_FILE_IS_A_DIRECTORY;
6490 /* Setting a hardlink to/from a stream isn't currently supported. */
6491 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6493 DBG_DEBUG("Old name has streams\n");
6494 return NT_STATUS_INVALID_PARAMETER;
6496 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6498 DBG_DEBUG("New name has streams\n");
6499 return NT_STATUS_INVALID_PARAMETER;
6502 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6503 smb_fname_old->base_name, smb_fname_new->base_name));
6505 ret = SMB_VFS_LINKAT(conn,
6513 status = map_nt_error_from_unix(errno);
6514 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6515 nt_errstr(status), smb_fname_old->base_name,
6516 smb_fname_new->base_name));
6521 /****************************************************************************
6522 Deal with setting the time from any of the setfilepathinfo functions.
6523 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6524 calling this function.
6525 ****************************************************************************/
6527 NTSTATUS smb_set_file_time(connection_struct *conn,
6529 const struct smb_filename *smb_fname,
6530 struct smb_file_time *ft,
6531 bool setting_write_time)
6533 struct smb_filename smb_fname_base;
6534 struct timeval_buf tbuf[4];
6536 FILE_NOTIFY_CHANGE_LAST_ACCESS
6537 |FILE_NOTIFY_CHANGE_LAST_WRITE
6538 |FILE_NOTIFY_CHANGE_CREATION;
6540 if (!VALID_STAT(smb_fname->st)) {
6541 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6544 /* get some defaults (no modifications) if any info is zero or -1. */
6545 if (is_omit_timespec(&ft->create_time)) {
6546 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6549 if (is_omit_timespec(&ft->atime)) {
6550 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6553 if (is_omit_timespec(&ft->mtime)) {
6554 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6557 if (!setting_write_time) {
6558 /* ft->mtime comes from change time, not write time. */
6559 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6562 /* Ensure the resolution is the correct for
6563 * what we can store on this filesystem. */
6565 round_timespec(conn->ts_res, &ft->create_time);
6566 round_timespec(conn->ts_res, &ft->ctime);
6567 round_timespec(conn->ts_res, &ft->atime);
6568 round_timespec(conn->ts_res, &ft->mtime);
6570 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6571 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6572 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6573 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6574 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6575 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6576 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6577 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6579 if (setting_write_time) {
6581 * This was a Windows setfileinfo on an open file.
6582 * NT does this a lot. We also need to
6583 * set the time here, as it can be read by
6584 * FindFirst/FindNext and with the patch for bug #2045
6585 * in smbd/fileio.c it ensures that this timestamp is
6586 * kept sticky even after a write. We save the request
6587 * away and will set it on file close and after a write. JRA.
6590 DBG_DEBUG("setting pending modtime to %s\n",
6591 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6594 if (fsp->base_fsp) {
6595 set_sticky_write_time_fsp(fsp->base_fsp,
6598 set_sticky_write_time_fsp(fsp, ft->mtime);
6601 set_sticky_write_time_path(
6602 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6607 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6609 /* Always call ntimes on the base, even if a stream was passed in. */
6610 smb_fname_base = *smb_fname;
6611 smb_fname_base.stream_name = NULL;
6613 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6614 return map_nt_error_from_unix(errno);
6617 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6618 smb_fname->base_name);
6619 return NT_STATUS_OK;
6622 /****************************************************************************
6623 Deal with setting the dosmode from any of the setfilepathinfo functions.
6624 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6625 done before calling this function.
6626 ****************************************************************************/
6628 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6629 const struct smb_filename *smb_fname,
6632 struct smb_filename *smb_fname_base;
6635 if (!VALID_STAT(smb_fname->st)) {
6636 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6639 /* Always operate on the base_name, even if a stream was passed in. */
6640 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6641 smb_fname->base_name,
6646 if (smb_fname_base == NULL) {
6647 return NT_STATUS_NO_MEMORY;
6651 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6652 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6654 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6658 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6660 /* check the mode isn't different, before changing it */
6661 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6662 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6663 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6664 (unsigned int)dosmode));
6666 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6668 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6670 smb_fname_str_dbg(smb_fname_base),
6672 status = map_nt_error_from_unix(errno);
6676 status = NT_STATUS_OK;
6678 TALLOC_FREE(smb_fname_base);
6682 /****************************************************************************
6683 Deal with setting the size from any of the setfilepathinfo functions.
6684 ****************************************************************************/
6686 static NTSTATUS smb_set_file_size(connection_struct *conn,
6687 struct smb_request *req,
6689 const struct smb_filename *smb_fname,
6690 const SMB_STRUCT_STAT *psbuf,
6692 bool fail_after_createfile)
6694 NTSTATUS status = NT_STATUS_OK;
6695 struct smb_filename *smb_fname_tmp = NULL;
6696 files_struct *new_fsp = NULL;
6698 if (!VALID_STAT(*psbuf)) {
6699 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6702 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6704 get_file_size_stat(psbuf));
6706 if (size == get_file_size_stat(psbuf)) {
6708 return NT_STATUS_OK;
6710 if (!fsp->fsp_flags.modified) {
6711 return NT_STATUS_OK;
6713 trigger_write_time_update_immediate(fsp);
6714 return NT_STATUS_OK;
6717 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6718 smb_fname_str_dbg(smb_fname), (double)size));
6720 if (fsp && fsp->fh->fd != -1) {
6721 /* Handle based call. */
6722 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6723 return NT_STATUS_ACCESS_DENIED;
6726 if (vfs_set_filelen(fsp, size) == -1) {
6727 return map_nt_error_from_unix(errno);
6729 trigger_write_time_update_immediate(fsp);
6730 return NT_STATUS_OK;
6733 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6734 if (smb_fname_tmp == NULL) {
6735 return NT_STATUS_NO_MEMORY;
6738 smb_fname_tmp->st = *psbuf;
6740 status = SMB_VFS_CREATE_FILE(
6743 0, /* root_dir_fid */
6744 smb_fname_tmp, /* fname */
6745 FILE_WRITE_DATA, /* access_mask */
6746 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6748 FILE_OPEN, /* create_disposition*/
6749 0, /* create_options */
6750 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6751 0, /* oplock_request */
6753 0, /* allocation_size */
6754 0, /* private_flags */
6757 &new_fsp, /* result */
6759 NULL, NULL); /* create context */
6761 TALLOC_FREE(smb_fname_tmp);
6763 if (!NT_STATUS_IS_OK(status)) {
6764 /* NB. We check for open_was_deferred in the caller. */
6768 /* See RAW-SFILEINFO-END-OF-FILE */
6769 if (fail_after_createfile) {
6770 close_file(req, new_fsp,NORMAL_CLOSE);
6771 return NT_STATUS_INVALID_LEVEL;
6774 if (vfs_set_filelen(new_fsp, size) == -1) {
6775 status = map_nt_error_from_unix(errno);
6776 close_file(req, new_fsp,NORMAL_CLOSE);
6780 trigger_write_time_update_immediate(new_fsp);
6781 close_file(req, new_fsp,NORMAL_CLOSE);
6782 return NT_STATUS_OK;
6785 /****************************************************************************
6786 Deal with SMB_INFO_SET_EA.
6787 ****************************************************************************/
6789 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6793 const struct smb_filename *smb_fname)
6795 struct ea_list *ea_list = NULL;
6796 TALLOC_CTX *ctx = NULL;
6797 NTSTATUS status = NT_STATUS_OK;
6799 if (total_data < 10) {
6801 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6802 length. They seem to have no effect. Bug #3212. JRA */
6804 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6805 /* We're done. We only get EA info in this call. */
6806 return NT_STATUS_OK;
6809 return NT_STATUS_INVALID_PARAMETER;
6812 if (IVAL(pdata,0) > total_data) {
6813 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6814 IVAL(pdata,0), (unsigned int)total_data));
6815 return NT_STATUS_INVALID_PARAMETER;
6819 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6821 return NT_STATUS_INVALID_PARAMETER;
6824 status = set_ea(conn, fsp, smb_fname, ea_list);
6829 /****************************************************************************
6830 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6831 ****************************************************************************/
6833 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6838 struct ea_list *ea_list = NULL;
6842 return NT_STATUS_INVALID_HANDLE;
6845 if (!lp_ea_support(SNUM(conn))) {
6846 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6847 "EA's not supported.\n",
6848 (unsigned int)total_data));
6849 return NT_STATUS_EAS_NOT_SUPPORTED;
6852 if (total_data < 10) {
6853 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6855 (unsigned int)total_data));
6856 return NT_STATUS_INVALID_PARAMETER;
6859 ea_list = read_nttrans_ea_list(talloc_tos(),
6864 return NT_STATUS_INVALID_PARAMETER;
6867 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6869 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6870 smb_fname_str_dbg(fsp->fsp_name),
6871 nt_errstr(status) ));
6877 /****************************************************************************
6878 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6879 ****************************************************************************/
6881 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6885 struct smb_filename *smb_fname)
6887 NTSTATUS status = NT_STATUS_OK;
6888 bool delete_on_close;
6889 uint32_t dosmode = 0;
6891 if (total_data < 1) {
6892 return NT_STATUS_INVALID_PARAMETER;
6896 return NT_STATUS_INVALID_HANDLE;
6899 delete_on_close = (CVAL(pdata,0) ? True : False);
6900 dosmode = dos_mode(conn, smb_fname);
6902 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6903 "delete_on_close = %u\n",
6904 smb_fname_str_dbg(smb_fname),
6905 (unsigned int)dosmode,
6906 (unsigned int)delete_on_close ));
6908 if (delete_on_close) {
6909 status = can_set_delete_on_close(fsp, dosmode);
6910 if (!NT_STATUS_IS_OK(status)) {
6915 /* The set is across all open files on this dev/inode pair. */
6916 if (!set_delete_on_close(fsp, delete_on_close,
6917 conn->session_info->security_token,
6918 conn->session_info->unix_token)) {
6919 return NT_STATUS_ACCESS_DENIED;
6921 return NT_STATUS_OK;
6924 /****************************************************************************
6925 Deal with SMB_FILE_POSITION_INFORMATION.
6926 ****************************************************************************/
6928 static NTSTATUS smb_file_position_information(connection_struct *conn,
6933 uint64_t position_information;
6935 if (total_data < 8) {
6936 return NT_STATUS_INVALID_PARAMETER;
6940 /* Ignore on pathname based set. */
6941 return NT_STATUS_OK;
6944 position_information = (uint64_t)IVAL(pdata,0);
6945 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6947 DEBUG(10,("smb_file_position_information: Set file position "
6948 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6949 (double)position_information));
6950 fsp->fh->position_information = position_information;
6951 return NT_STATUS_OK;
6954 /****************************************************************************
6955 Deal with SMB_FILE_MODE_INFORMATION.
6956 ****************************************************************************/
6958 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6964 if (total_data < 4) {
6965 return NT_STATUS_INVALID_PARAMETER;
6967 mode = IVAL(pdata,0);
6968 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6969 return NT_STATUS_INVALID_PARAMETER;
6971 return NT_STATUS_OK;
6974 /****************************************************************************
6975 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6976 ****************************************************************************/
6978 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6979 struct smb_request *req,
6982 const struct smb_filename *new_smb_fname)
6984 char *link_target = NULL;
6985 struct smb_filename target_fname;
6986 TALLOC_CTX *ctx = talloc_tos();
6990 /* Set a symbolic link. */
6991 /* Don't allow this if follow links is false. */
6993 if (total_data == 0) {
6994 return NT_STATUS_INVALID_PARAMETER;
6997 if (!lp_follow_symlinks(SNUM(conn))) {
6998 return NT_STATUS_ACCESS_DENIED;
7001 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
7002 total_data, STR_TERMINATE);
7005 return NT_STATUS_INVALID_PARAMETER;
7008 target_fname = (struct smb_filename) {
7009 .base_name = link_target,
7012 /* Removes @GMT tokens if any */
7013 status = canonicalize_snapshot_path(&target_fname, 0);
7014 if (!NT_STATUS_IS_OK(status)) {
7018 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7019 new_smb_fname->base_name, link_target ));
7021 ret = SMB_VFS_SYMLINKAT(conn,
7026 return map_nt_error_from_unix(errno);
7029 return NT_STATUS_OK;
7032 /****************************************************************************
7033 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7034 ****************************************************************************/
7036 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7037 struct smb_request *req,
7038 const char *pdata, int total_data,
7039 struct smb_filename *smb_fname_new)
7041 char *oldname = NULL;
7042 struct smb_filename *smb_fname_old = NULL;
7043 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7044 TALLOC_CTX *ctx = talloc_tos();
7045 NTSTATUS status = NT_STATUS_OK;
7047 /* Set a hard link. */
7048 if (total_data == 0) {
7049 return NT_STATUS_INVALID_PARAMETER;
7052 if (req->posix_pathnames) {
7053 srvstr_get_path_posix(ctx,
7062 srvstr_get_path(ctx,
7071 if (!NT_STATUS_IS_OK(status)) {
7075 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7076 smb_fname_str_dbg(smb_fname_new), oldname));
7078 status = filename_convert(ctx,
7085 if (!NT_STATUS_IS_OK(status)) {
7089 return hardlink_internals(ctx, conn, req, false,
7090 smb_fname_old, smb_fname_new);
7093 /****************************************************************************
7094 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7095 ****************************************************************************/
7097 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7098 struct smb_request *req,
7102 struct smb_filename *smb_fname_src)
7106 char *newname = NULL;
7107 struct smb_filename *smb_fname_dst = NULL;
7108 const char *dst_original_lcomp = NULL;
7109 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7110 NTSTATUS status = NT_STATUS_OK;
7111 TALLOC_CTX *ctx = talloc_tos();
7114 return NT_STATUS_INVALID_HANDLE;
7117 if (total_data < 20) {
7118 return NT_STATUS_INVALID_PARAMETER;
7121 overwrite = (CVAL(pdata,0) ? True : False);
7122 len = IVAL(pdata,16);
7124 if (len > (total_data - 20) || (len == 0)) {
7125 return NT_STATUS_INVALID_PARAMETER;
7128 if (req->posix_pathnames) {
7129 srvstr_get_path_posix(ctx,
7138 srvstr_get_path(ctx,
7147 if (!NT_STATUS_IS_OK(status)) {
7151 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7154 status = filename_convert(ctx,
7161 if (!NT_STATUS_IS_OK(status)) {
7165 if (fsp->base_fsp) {
7166 /* newname must be a stream name. */
7167 if (newname[0] != ':') {
7168 return NT_STATUS_NOT_SUPPORTED;
7171 /* Create an smb_fname to call rename_internals_fsp() with. */
7172 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7173 fsp->base_fsp->fsp_name->base_name,
7176 fsp->base_fsp->fsp_name->twrp,
7177 fsp->base_fsp->fsp_name->flags);
7178 if (smb_fname_dst == NULL) {
7179 status = NT_STATUS_NO_MEMORY;
7185 * Set the original last component, since
7186 * rename_internals_fsp() requires it.
7188 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7192 if (dst_original_lcomp == NULL) {
7193 status = NT_STATUS_NO_MEMORY;
7197 DEBUG(10,("smb2_file_rename_information: "
7198 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7199 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7200 smb_fname_str_dbg(smb_fname_dst)));
7201 status = rename_internals_fsp(conn,
7205 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7209 TALLOC_FREE(smb_fname_dst);
7213 static NTSTATUS smb_file_link_information(connection_struct *conn,
7214 struct smb_request *req,
7218 struct smb_filename *smb_fname_src)
7222 char *newname = NULL;
7223 struct smb_filename *smb_fname_dst = NULL;
7224 NTSTATUS status = NT_STATUS_OK;
7225 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7226 TALLOC_CTX *ctx = talloc_tos();
7229 return NT_STATUS_INVALID_HANDLE;
7232 if (total_data < 20) {
7233 return NT_STATUS_INVALID_PARAMETER;
7236 overwrite = (CVAL(pdata,0) ? true : false);
7237 len = IVAL(pdata,16);
7239 if (len > (total_data - 20) || (len == 0)) {
7240 return NT_STATUS_INVALID_PARAMETER;
7243 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7244 srvstr_get_path_posix(ctx,
7252 ucf_flags |= UCF_POSIX_PATHNAMES;
7254 srvstr_get_path(ctx,
7263 if (!NT_STATUS_IS_OK(status)) {
7267 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7270 status = filename_convert(ctx,
7277 if (!NT_STATUS_IS_OK(status)) {
7281 if (fsp->base_fsp) {
7282 /* No stream names. */
7283 return NT_STATUS_NOT_SUPPORTED;
7286 DEBUG(10,("smb_file_link_information: "
7287 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7288 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7289 smb_fname_str_dbg(smb_fname_dst)));
7290 status = hardlink_internals(ctx,
7297 TALLOC_FREE(smb_fname_dst);
7301 /****************************************************************************
7302 Deal with SMB_FILE_RENAME_INFORMATION.
7303 ****************************************************************************/
7305 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7306 struct smb_request *req,
7310 struct smb_filename *smb_fname_src)
7315 char *newname = NULL;
7316 struct smb_filename *smb_fname_dst = NULL;
7317 const char *dst_original_lcomp = NULL;
7318 bool dest_has_wcard = False;
7319 NTSTATUS status = NT_STATUS_OK;
7321 TALLOC_CTX *ctx = talloc_tos();
7323 if (total_data < 13) {
7324 return NT_STATUS_INVALID_PARAMETER;
7327 overwrite = (CVAL(pdata,0) ? True : False);
7328 root_fid = IVAL(pdata,4);
7329 len = IVAL(pdata,8);
7331 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7332 return NT_STATUS_INVALID_PARAMETER;
7335 if (req->posix_pathnames) {
7336 srvstr_get_path_wcard_posix(ctx,
7346 srvstr_get_path_wcard(ctx,
7356 if (!NT_STATUS_IS_OK(status)) {
7360 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7363 /* Check the new name has no '/' characters. */
7364 if (strchr_m(newname, '/')) {
7365 return NT_STATUS_NOT_SUPPORTED;
7368 if (fsp && fsp->base_fsp) {
7369 /* newname must be a stream name. */
7370 if (newname[0] != ':') {
7371 return NT_STATUS_NOT_SUPPORTED;
7374 /* Create an smb_fname to call rename_internals_fsp() with. */
7375 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7376 fsp->base_fsp->fsp_name->base_name,
7379 fsp->base_fsp->fsp_name->twrp,
7380 fsp->base_fsp->fsp_name->flags);
7381 if (smb_fname_dst == NULL) {
7382 status = NT_STATUS_NO_MEMORY;
7387 * Get the original last component, since
7388 * rename_internals_fsp() requires it.
7390 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7394 if (dst_original_lcomp == NULL) {
7395 status = NT_STATUS_NO_MEMORY;
7401 * Build up an smb_fname_dst based on the filename passed in.
7402 * We basically just strip off the last component, and put on
7403 * the newname instead.
7405 char *base_name = NULL;
7406 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7408 if (dest_has_wcard) {
7409 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7412 /* newname must *not* be a stream name. */
7413 if (newname[0] == ':') {
7414 return NT_STATUS_NOT_SUPPORTED;
7418 * Strip off the last component (filename) of the path passed
7421 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7423 return NT_STATUS_NO_MEMORY;
7425 p = strrchr_m(base_name, '/');
7429 base_name = talloc_strdup(ctx, "");
7431 return NT_STATUS_NO_MEMORY;
7434 /* Append the new name. */
7435 base_name = talloc_asprintf_append(base_name,
7439 return NT_STATUS_NO_MEMORY;
7442 status = filename_convert(ctx,
7450 /* If an error we expect this to be
7451 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7453 if (!NT_STATUS_IS_OK(status)) {
7454 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7458 /* Create an smb_fname to call rename_internals_fsp() */
7459 smb_fname_dst = synthetic_smb_fname(ctx,
7463 smb_fname_src->twrp,
7464 smb_fname_src->flags);
7465 if (smb_fname_dst == NULL) {
7466 status = NT_STATUS_NO_MEMORY;
7470 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7474 if (dst_original_lcomp == NULL) {
7475 status = NT_STATUS_NO_MEMORY;
7481 DEBUG(10,("smb_file_rename_information: "
7482 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7483 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7484 smb_fname_str_dbg(smb_fname_dst)));
7485 status = rename_internals_fsp(conn,
7492 DEBUG(10,("smb_file_rename_information: "
7493 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7494 smb_fname_str_dbg(smb_fname_src),
7495 smb_fname_str_dbg(smb_fname_dst)));
7496 status = rename_internals(ctx,
7506 FILE_WRITE_ATTRIBUTES);
7509 TALLOC_FREE(smb_fname_dst);
7513 /****************************************************************************
7514 Deal with SMB_SET_POSIX_ACL.
7515 ****************************************************************************/
7517 #if defined(HAVE_POSIX_ACLS)
7518 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7519 struct smb_request *req,
7523 const struct smb_filename *smb_fname)
7525 uint16_t posix_acl_version;
7526 uint16_t num_file_acls;
7527 uint16_t num_def_acls;
7528 bool valid_file_acls = true;
7529 bool valid_def_acls = true;
7531 unsigned int size_needed;
7532 unsigned int total_data;
7533 bool close_fsp = false;
7535 if (total_data_in < 0) {
7536 status = NT_STATUS_INVALID_PARAMETER;
7540 total_data = total_data_in;
7542 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7543 status = NT_STATUS_INVALID_PARAMETER;
7546 posix_acl_version = SVAL(pdata,0);
7547 num_file_acls = SVAL(pdata,2);
7548 num_def_acls = SVAL(pdata,4);
7550 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7551 valid_file_acls = false;
7555 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7556 valid_def_acls = false;
7560 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7561 status = NT_STATUS_INVALID_PARAMETER;
7566 if (num_file_acls + num_def_acls < num_file_acls) {
7567 status = NT_STATUS_INVALID_PARAMETER;
7571 size_needed = num_file_acls + num_def_acls;
7574 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7575 * than UINT_MAX, so check by division.
7577 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7578 status = NT_STATUS_INVALID_PARAMETER;
7582 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7583 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7584 status = NT_STATUS_INVALID_PARAMETER;
7587 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7589 if (total_data < size_needed) {
7590 status = NT_STATUS_INVALID_PARAMETER;
7595 * Ensure we always operate on a file descriptor, not just
7599 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7601 SEC_STD_READ_CONTROL|
7602 FILE_READ_ATTRIBUTES|
7603 FILE_WRITE_ATTRIBUTES;
7605 status = get_posix_fsp(conn,
7611 if (!NT_STATUS_IS_OK(status)) {
7617 /* Here we know fsp != NULL */
7618 SMB_ASSERT(fsp != NULL);
7620 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7621 if (!NT_STATUS_IS_OK(status)) {
7625 /* If we have a default acl, this *must* be a directory. */
7626 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7627 DBG_INFO("Can't set default acls on "
7628 "non-directory %s\n",
7630 return NT_STATUS_INVALID_HANDLE;
7633 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7634 "num_def_acls = %"PRIu16"\n",
7639 /* Move pdata to the start of the file ACL entries. */
7640 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7642 if (valid_file_acls) {
7643 status = set_unix_posix_acl(conn,
7647 if (!NT_STATUS_IS_OK(status)) {
7652 /* Move pdata to the start of the default ACL entries. */
7653 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7655 if (valid_def_acls) {
7656 status = set_unix_posix_default_acl(conn,
7660 if (!NT_STATUS_IS_OK(status)) {
7665 status = NT_STATUS_OK;
7670 (void)close_file(req, fsp, NORMAL_CLOSE);
7677 /****************************************************************************
7678 Deal with SMB_SET_POSIX_LOCK.
7679 ****************************************************************************/
7681 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7683 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7684 struct smb_request *req,
7689 struct tevent_req *subreq = NULL;
7690 struct smbd_lock_element *lck = NULL;
7694 bool blocking_lock = False;
7695 enum brl_type lock_type;
7697 NTSTATUS status = NT_STATUS_OK;
7699 if (fsp == NULL || fsp->fh->fd == -1) {
7700 return NT_STATUS_INVALID_HANDLE;
7703 if (total_data != POSIX_LOCK_DATA_SIZE) {
7704 return NT_STATUS_INVALID_PARAMETER;
7707 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7708 case POSIX_LOCK_TYPE_READ:
7709 lock_type = READ_LOCK;
7711 case POSIX_LOCK_TYPE_WRITE:
7712 /* Return the right POSIX-mappable error code for files opened read-only. */
7713 if (!fsp->fsp_flags.can_write) {
7714 return NT_STATUS_INVALID_HANDLE;
7716 lock_type = WRITE_LOCK;
7718 case POSIX_LOCK_TYPE_UNLOCK:
7719 lock_type = UNLOCK_LOCK;
7722 return NT_STATUS_INVALID_PARAMETER;
7725 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7726 case POSIX_LOCK_FLAG_NOWAIT:
7727 blocking_lock = false;
7729 case POSIX_LOCK_FLAG_WAIT:
7730 blocking_lock = true;
7733 return NT_STATUS_INVALID_PARAMETER;
7736 if (!lp_blocking_locks(SNUM(conn))) {
7737 blocking_lock = False;
7740 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7741 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7742 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7743 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7744 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7746 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7747 "count = %"PRIu64", offset = %"PRIu64"\n",
7749 (unsigned int)lock_type,
7754 if (lock_type == UNLOCK_LOCK) {
7755 struct smbd_lock_element l = {
7756 .req_guid = smbd_request_guid(req, 0),
7758 .brltype = UNLOCK_LOCK,
7762 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7766 lck = talloc(req, struct smbd_lock_element);
7768 return NT_STATUS_NO_MEMORY;
7771 *lck = (struct smbd_lock_element) {
7772 .req_guid = smbd_request_guid(req, 0),
7774 .brltype = lock_type,
7779 subreq = smbd_smb1_do_locks_send(
7784 blocking_lock ? UINT32_MAX : 0,
7785 true, /* large_offset */
7789 if (subreq == NULL) {
7791 return NT_STATUS_NO_MEMORY;
7793 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7794 return NT_STATUS_EVENT_PENDING;
7797 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7799 struct smb_request *req = NULL;
7803 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7806 status = smbd_smb1_do_locks_recv(subreq);
7807 TALLOC_FREE(subreq);
7809 if (NT_STATUS_IS_OK(status)) {
7810 char params[2] = {0};
7811 /* Fake up max_data_bytes here - we know it fits. */
7812 send_trans2_replies(
7822 reply_nterror(req, status);
7825 (char *)req->outbuf,
7828 IS_CONN_ENCRYPTED(req->conn),
7831 exit_server_cleanly("smb_set_posix_lock_done: "
7832 "srv_send_smb failed.");
7840 /****************************************************************************
7841 Deal with SMB_SET_FILE_BASIC_INFO.
7842 ****************************************************************************/
7844 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7848 const struct smb_filename *smb_fname)
7850 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7851 struct smb_file_time ft;
7852 uint32_t dosmode = 0;
7853 NTSTATUS status = NT_STATUS_OK;
7855 init_smb_file_time(&ft);
7857 if (total_data < 36) {
7858 return NT_STATUS_INVALID_PARAMETER;
7862 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7864 status = check_access(conn,
7867 FILE_WRITE_ATTRIBUTES);
7869 if (!NT_STATUS_IS_OK(status)) {
7873 /* Set the attributes */
7874 dosmode = IVAL(pdata,32);
7875 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7876 if (!NT_STATUS_IS_OK(status)) {
7881 ft.create_time = pull_long_date_full_timespec(pdata);
7884 ft.atime = pull_long_date_full_timespec(pdata+8);
7887 ft.mtime = pull_long_date_full_timespec(pdata+16);
7890 ft.ctime = pull_long_date_full_timespec(pdata+24);
7892 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7893 smb_fname_str_dbg(smb_fname)));
7895 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7896 if (!NT_STATUS_IS_OK(status)) {
7900 if (fsp != NULL && fsp->fsp_flags.modified) {
7901 trigger_write_time_update_immediate(fsp);
7903 return NT_STATUS_OK;
7906 /****************************************************************************
7907 Deal with SMB_INFO_STANDARD.
7908 ****************************************************************************/
7910 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7914 const struct smb_filename *smb_fname)
7917 struct smb_file_time ft;
7919 init_smb_file_time(&ft);
7921 if (total_data < 12) {
7922 return NT_STATUS_INVALID_PARAMETER;
7926 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7928 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7930 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7932 DEBUG(10,("smb_set_info_standard: file %s\n",
7933 smb_fname_str_dbg(smb_fname)));
7936 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7938 status = check_access(conn,
7941 FILE_WRITE_ATTRIBUTES);
7943 if (!NT_STATUS_IS_OK(status)) {
7947 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7948 if (!NT_STATUS_IS_OK(status)) {
7952 if (fsp != NULL && fsp->fsp_flags.modified) {
7953 trigger_write_time_update_immediate(fsp);
7955 return NT_STATUS_OK;
7958 /****************************************************************************
7959 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7960 ****************************************************************************/
7962 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7963 struct smb_request *req,
7967 struct smb_filename *smb_fname)
7969 uint64_t allocation_size = 0;
7970 NTSTATUS status = NT_STATUS_OK;
7971 files_struct *new_fsp = NULL;
7973 if (!VALID_STAT(smb_fname->st)) {
7974 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7977 if (total_data < 8) {
7978 return NT_STATUS_INVALID_PARAMETER;
7981 allocation_size = (uint64_t)IVAL(pdata,0);
7982 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7983 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7984 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7985 (double)allocation_size));
7987 if (allocation_size) {
7988 allocation_size = smb_roundup(conn, allocation_size);
7991 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7992 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7993 (double)allocation_size));
7995 if (fsp && fsp->fh->fd != -1) {
7996 /* Open file handle. */
7997 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7998 return NT_STATUS_ACCESS_DENIED;
8001 /* Only change if needed. */
8002 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8003 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
8004 return map_nt_error_from_unix(errno);
8007 /* But always update the time. */
8009 * This is equivalent to a write. Ensure it's seen immediately
8010 * if there are no pending writes.
8012 trigger_write_time_update_immediate(fsp);
8013 return NT_STATUS_OK;
8016 /* Pathname or stat or directory file. */
8017 status = SMB_VFS_CREATE_FILE(
8020 0, /* root_dir_fid */
8021 smb_fname, /* fname */
8022 FILE_WRITE_DATA, /* access_mask */
8023 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8025 FILE_OPEN, /* create_disposition*/
8026 0, /* create_options */
8027 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8028 0, /* oplock_request */
8030 0, /* allocation_size */
8031 0, /* private_flags */
8034 &new_fsp, /* result */
8036 NULL, NULL); /* create context */
8038 if (!NT_STATUS_IS_OK(status)) {
8039 /* NB. We check for open_was_deferred in the caller. */
8043 /* Only change if needed. */
8044 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8045 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8046 status = map_nt_error_from_unix(errno);
8047 close_file(req, new_fsp, NORMAL_CLOSE);
8052 /* Changing the allocation size should set the last mod time. */
8054 * This is equivalent to a write. Ensure it's seen immediately
8055 * if there are no pending writes.
8057 trigger_write_time_update_immediate(new_fsp);
8058 close_file(req, new_fsp, NORMAL_CLOSE);
8059 return NT_STATUS_OK;
8062 /****************************************************************************
8063 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8064 ****************************************************************************/
8066 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8067 struct smb_request *req,
8071 const struct smb_filename *smb_fname,
8072 bool fail_after_createfile)
8076 if (total_data < 8) {
8077 return NT_STATUS_INVALID_PARAMETER;
8080 size = IVAL(pdata,0);
8081 size |= (((off_t)IVAL(pdata,4)) << 32);
8082 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8083 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8086 return smb_set_file_size(conn, req,
8091 fail_after_createfile);
8094 /****************************************************************************
8095 Allow a UNIX info mknod.
8096 ****************************************************************************/
8098 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8101 const struct smb_filename *smb_fname)
8103 uint32_t file_type = IVAL(pdata,56);
8104 #if defined(HAVE_MAKEDEV)
8105 uint32_t dev_major = IVAL(pdata,60);
8106 uint32_t dev_minor = IVAL(pdata,68);
8108 SMB_DEV_T dev = (SMB_DEV_T)0;
8109 uint32_t raw_unixmode = IVAL(pdata,84);
8114 if (total_data < 100) {
8115 return NT_STATUS_INVALID_PARAMETER;
8118 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8119 PERM_NEW_FILE, &unixmode);
8120 if (!NT_STATUS_IS_OK(status)) {
8124 #if defined(HAVE_MAKEDEV)
8125 dev = makedev(dev_major, dev_minor);
8128 switch (file_type) {
8129 /* We can't create other objects here. */
8130 case UNIX_TYPE_FILE:
8132 case UNIX_TYPE_SYMLINK:
8133 return NT_STATUS_ACCESS_DENIED;
8134 #if defined(S_IFIFO)
8135 case UNIX_TYPE_FIFO:
8136 unixmode |= S_IFIFO;
8139 #if defined(S_IFSOCK)
8140 case UNIX_TYPE_SOCKET:
8141 unixmode |= S_IFSOCK;
8144 #if defined(S_IFCHR)
8145 case UNIX_TYPE_CHARDEV:
8146 /* This is only allowed for root. */
8147 if (get_current_uid(conn) != sec_initial_uid()) {
8148 return NT_STATUS_ACCESS_DENIED;
8150 unixmode |= S_IFCHR;
8153 #if defined(S_IFBLK)
8154 case UNIX_TYPE_BLKDEV:
8155 if (get_current_uid(conn) != sec_initial_uid()) {
8156 return NT_STATUS_ACCESS_DENIED;
8158 unixmode |= S_IFBLK;
8162 return NT_STATUS_INVALID_PARAMETER;
8165 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8166 "%.0f mode 0%o for file %s\n", (double)dev,
8167 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8169 /* Ok - do the mknod. */
8170 ret = SMB_VFS_MKNODAT(conn,
8177 return map_nt_error_from_unix(errno);
8180 /* If any of the other "set" calls fail we
8181 * don't want to end up with a half-constructed mknod.
8184 if (lp_inherit_permissions(SNUM(conn))) {
8185 struct smb_filename *parent_fname = NULL;
8188 ok = parent_smb_fname(talloc_tos(),
8193 return NT_STATUS_NO_MEMORY;
8195 inherit_access_posix_acl(conn,
8199 TALLOC_FREE(parent_fname);
8202 return NT_STATUS_OK;
8205 /****************************************************************************
8206 Deal with SMB_SET_FILE_UNIX_BASIC.
8207 ****************************************************************************/
8209 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8210 struct smb_request *req,
8214 const struct smb_filename *smb_fname)
8216 struct smb_file_time ft;
8217 uint32_t raw_unixmode;
8220 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8221 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8222 NTSTATUS status = NT_STATUS_OK;
8223 enum perm_type ptype;
8224 files_struct *all_fsps = NULL;
8225 bool modify_mtime = true;
8227 SMB_STRUCT_STAT sbuf;
8229 init_smb_file_time(&ft);
8231 if (total_data < 100) {
8232 return NT_STATUS_INVALID_PARAMETER;
8235 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8236 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8237 size=IVAL(pdata,0); /* first 8 Bytes are size */
8238 size |= (((off_t)IVAL(pdata,4)) << 32);
8241 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8242 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8243 set_owner = (uid_t)IVAL(pdata,40);
8244 set_grp = (gid_t)IVAL(pdata,48);
8245 raw_unixmode = IVAL(pdata,84);
8247 if (VALID_STAT(smb_fname->st)) {
8248 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8249 ptype = PERM_EXISTING_DIR;
8251 ptype = PERM_EXISTING_FILE;
8254 ptype = PERM_NEW_FILE;
8257 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8259 if (!NT_STATUS_IS_OK(status)) {
8263 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8264 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8265 smb_fname_str_dbg(smb_fname), (double)size,
8266 (unsigned int)set_owner, (unsigned int)set_grp,
8267 (int)raw_unixmode));
8269 sbuf = smb_fname->st;
8271 if (!VALID_STAT(sbuf)) {
8273 * The only valid use of this is to create character and block
8274 * devices, and named pipes. This is deprecated (IMHO) and
8275 * a new info level should be used for mknod. JRA.
8278 return smb_unix_mknod(conn,
8285 /* Horrible backwards compatibility hack as an old server bug
8286 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8290 size = get_file_size_stat(&sbuf);
8295 * Deal with the UNIX specific mode set.
8298 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8301 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8302 "setting mode 0%o for file %s\n",
8303 (unsigned int)unixmode,
8304 smb_fname_str_dbg(smb_fname)));
8305 if (fsp && fsp->fh->fd != -1) {
8306 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8308 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8311 return map_nt_error_from_unix(errno);
8316 * Deal with the UNIX specific uid set.
8319 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8320 (sbuf.st_ex_uid != set_owner)) {
8323 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8324 "changing owner %u for path %s\n",
8325 (unsigned int)set_owner,
8326 smb_fname_str_dbg(smb_fname)));
8328 if (fsp && fsp->fh->fd != -1) {
8329 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8332 * UNIX extensions calls must always operate
8335 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8336 set_owner, (gid_t)-1);
8340 status = map_nt_error_from_unix(errno);
8346 * Deal with the UNIX specific gid set.
8349 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8350 (sbuf.st_ex_gid != set_grp)) {
8353 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8354 "changing group %u for file %s\n",
8355 (unsigned int)set_grp,
8356 smb_fname_str_dbg(smb_fname)));
8357 if (fsp && fsp->fh->fd != -1) {
8358 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8361 * UNIX extensions calls must always operate
8364 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8368 status = map_nt_error_from_unix(errno);
8373 /* Deal with any size changes. */
8375 if (S_ISREG(sbuf.st_ex_mode)) {
8376 status = smb_set_file_size(conn, req,
8382 if (!NT_STATUS_IS_OK(status)) {
8387 /* Deal with any time changes. */
8388 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8389 /* No change, don't cancel anything. */
8393 id = vfs_file_id_from_sbuf(conn, &sbuf);
8394 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8395 all_fsps = file_find_di_next(all_fsps)) {
8397 * We're setting the time explicitly for UNIX.
8398 * Cancel any pending changes over all handles.
8400 all_fsps->fsp_flags.update_write_time_on_close = false;
8401 TALLOC_FREE(all_fsps->update_write_time_event);
8405 * Override the "setting_write_time"
8406 * parameter here as it almost does what
8407 * we need. Just remember if we modified
8408 * mtime and send the notify ourselves.
8410 if (is_omit_timespec(&ft.mtime)) {
8411 modify_mtime = false;
8414 status = smb_set_file_time(conn,
8420 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8421 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8426 /****************************************************************************
8427 Deal with SMB_SET_FILE_UNIX_INFO2.
8428 ****************************************************************************/
8430 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8431 struct smb_request *req,
8435 const struct smb_filename *smb_fname)
8438 uint32_t smb_fflags;
8441 if (total_data < 116) {
8442 return NT_STATUS_INVALID_PARAMETER;
8445 /* Start by setting all the fields that are common between UNIX_BASIC
8448 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8450 if (!NT_STATUS_IS_OK(status)) {
8454 smb_fflags = IVAL(pdata, 108);
8455 smb_fmask = IVAL(pdata, 112);
8457 /* NB: We should only attempt to alter the file flags if the client
8458 * sends a non-zero mask.
8460 if (smb_fmask != 0) {
8461 int stat_fflags = 0;
8463 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8464 smb_fmask, &stat_fflags)) {
8465 /* Client asked to alter a flag we don't understand. */
8466 return NT_STATUS_INVALID_PARAMETER;
8469 if (fsp && fsp->fh->fd != -1) {
8470 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8471 return NT_STATUS_NOT_SUPPORTED;
8473 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8474 stat_fflags) != 0) {
8475 return map_nt_error_from_unix(errno);
8480 /* XXX: need to add support for changing the create_time here. You
8481 * can do this for paths on Darwin with setattrlist(2). The right way
8482 * to hook this up is probably by extending the VFS utimes interface.
8485 return NT_STATUS_OK;
8488 /****************************************************************************
8489 Create a directory with POSIX semantics.
8490 ****************************************************************************/
8492 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8493 struct smb_request *req,
8496 struct smb_filename *smb_fname,
8497 int *pdata_return_size)
8499 NTSTATUS status = NT_STATUS_OK;
8500 uint32_t raw_unixmode = 0;
8501 mode_t unixmode = (mode_t)0;
8502 files_struct *fsp = NULL;
8503 uint16_t info_level_return = 0;
8505 char *pdata = *ppdata;
8506 struct smb2_create_blobs *posx = NULL;
8508 if (total_data < 18) {
8509 return NT_STATUS_INVALID_PARAMETER;
8512 raw_unixmode = IVAL(pdata,8);
8513 /* Next 4 bytes are not yet defined. */
8515 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8516 PERM_NEW_DIR, &unixmode);
8517 if (!NT_STATUS_IS_OK(status)) {
8521 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8522 if (!NT_STATUS_IS_OK(status)) {
8523 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8528 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8529 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8531 status = SMB_VFS_CREATE_FILE(
8534 0, /* root_dir_fid */
8535 smb_fname, /* fname */
8536 FILE_READ_ATTRIBUTES, /* access_mask */
8537 FILE_SHARE_NONE, /* share_access */
8538 FILE_CREATE, /* create_disposition*/
8539 FILE_DIRECTORY_FILE, /* create_options */
8540 0, /* file_attributes */
8541 0, /* oplock_request */
8543 0, /* allocation_size */
8544 0, /* private_flags */
8549 posx, /* in_context_blobs */
8550 NULL); /* out_context_blobs */
8554 if (NT_STATUS_IS_OK(status)) {
8555 close_file(req, fsp, NORMAL_CLOSE);
8558 info_level_return = SVAL(pdata,16);
8560 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8561 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8562 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8563 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8565 *pdata_return_size = 12;
8568 /* Realloc the data size */
8569 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8570 if (*ppdata == NULL) {
8571 *pdata_return_size = 0;
8572 return NT_STATUS_NO_MEMORY;
8576 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8577 SSVAL(pdata,2,0); /* No fnum. */
8578 SIVAL(pdata,4,info); /* Was directory created. */
8580 switch (info_level_return) {
8581 case SMB_QUERY_FILE_UNIX_BASIC:
8582 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8583 SSVAL(pdata,10,0); /* Padding. */
8584 store_file_unix_basic(conn, pdata + 12, fsp,
8587 case SMB_QUERY_FILE_UNIX_INFO2:
8588 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8589 SSVAL(pdata,10,0); /* Padding. */
8590 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8594 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8595 SSVAL(pdata,10,0); /* Padding. */
8602 /****************************************************************************
8603 Open/Create a file with POSIX semantics.
8604 ****************************************************************************/
8606 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8607 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8609 static NTSTATUS smb_posix_open(connection_struct *conn,
8610 struct smb_request *req,
8613 struct smb_filename *smb_fname,
8614 int *pdata_return_size)
8616 bool extended_oplock_granted = False;
8617 char *pdata = *ppdata;
8619 uint32_t wire_open_mode = 0;
8620 uint32_t raw_unixmode = 0;
8621 uint32_t attributes = 0;
8622 uint32_t create_disp = 0;
8623 uint32_t access_mask = 0;
8624 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8625 NTSTATUS status = NT_STATUS_OK;
8626 mode_t unixmode = (mode_t)0;
8627 files_struct *fsp = NULL;
8628 int oplock_request = 0;
8630 uint16_t info_level_return = 0;
8631 struct smb2_create_blobs *posx = NULL;
8633 if (total_data < 18) {
8634 return NT_STATUS_INVALID_PARAMETER;
8637 flags = IVAL(pdata,0);
8638 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8639 if (oplock_request) {
8640 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8643 wire_open_mode = IVAL(pdata,4);
8645 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8646 return smb_posix_mkdir(conn, req,
8653 switch (wire_open_mode & SMB_ACCMODE) {
8655 access_mask = SMB_O_RDONLY_MAPPING;
8658 access_mask = SMB_O_WRONLY_MAPPING;
8661 access_mask = (SMB_O_RDONLY_MAPPING|
8662 SMB_O_WRONLY_MAPPING);
8665 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8666 (unsigned int)wire_open_mode ));
8667 return NT_STATUS_INVALID_PARAMETER;
8670 wire_open_mode &= ~SMB_ACCMODE;
8672 /* First take care of O_CREAT|O_EXCL interactions. */
8673 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8674 case (SMB_O_CREAT | SMB_O_EXCL):
8675 /* File exists fail. File not exist create. */
8676 create_disp = FILE_CREATE;
8679 /* File exists open. File not exist create. */
8680 create_disp = FILE_OPEN_IF;
8683 /* O_EXCL on its own without O_CREAT is undefined.
8684 We deliberately ignore it as some versions of
8685 Linux CIFSFS can send a bare O_EXCL on the
8686 wire which other filesystems in the kernel
8687 ignore. See bug 9519 for details. */
8692 /* File exists open. File not exist fail. */
8693 create_disp = FILE_OPEN;
8696 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8697 (unsigned int)wire_open_mode ));
8698 return NT_STATUS_INVALID_PARAMETER;
8701 /* Next factor in the effects of O_TRUNC. */
8702 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8704 if (wire_open_mode & SMB_O_TRUNC) {
8705 switch (create_disp) {
8707 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8708 /* Leave create_disp alone as
8709 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8711 /* File exists fail. File not exist create. */
8714 /* SMB_O_CREAT | SMB_O_TRUNC */
8715 /* File exists overwrite. File not exist create. */
8716 create_disp = FILE_OVERWRITE_IF;
8720 /* File exists overwrite. File not exist fail. */
8721 create_disp = FILE_OVERWRITE;
8724 /* Cannot get here. */
8725 smb_panic("smb_posix_open: logic error");
8726 return NT_STATUS_INVALID_PARAMETER;
8730 raw_unixmode = IVAL(pdata,8);
8731 /* Next 4 bytes are not yet defined. */
8733 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8734 (VALID_STAT(smb_fname->st) ?
8735 PERM_EXISTING_FILE : PERM_NEW_FILE),
8738 if (!NT_STATUS_IS_OK(status)) {
8742 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8743 if (!NT_STATUS_IS_OK(status)) {
8744 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8749 if (wire_open_mode & SMB_O_SYNC) {
8750 create_options |= FILE_WRITE_THROUGH;
8752 if (wire_open_mode & SMB_O_APPEND) {
8753 access_mask |= FILE_APPEND_DATA;
8755 if (wire_open_mode & SMB_O_DIRECT) {
8756 attributes |= FILE_FLAG_NO_BUFFERING;
8759 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8760 VALID_STAT_OF_DIR(smb_fname->st)) {
8761 if (access_mask != SMB_O_RDONLY_MAPPING) {
8762 return NT_STATUS_FILE_IS_A_DIRECTORY;
8764 create_options &= ~FILE_NON_DIRECTORY_FILE;
8765 create_options |= FILE_DIRECTORY_FILE;
8768 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8769 smb_fname_str_dbg(smb_fname),
8770 (unsigned int)wire_open_mode,
8771 (unsigned int)unixmode ));
8773 status = SMB_VFS_CREATE_FILE(
8776 0, /* root_dir_fid */
8777 smb_fname, /* fname */
8778 access_mask, /* access_mask */
8779 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8781 create_disp, /* create_disposition*/
8782 create_options, /* create_options */
8783 attributes, /* file_attributes */
8784 oplock_request, /* oplock_request */
8786 0, /* allocation_size */
8787 0, /* private_flags */
8792 posx, /* in_context_blobs */
8793 NULL); /* out_context_blobs */
8797 if (!NT_STATUS_IS_OK(status)) {
8801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8802 extended_oplock_granted = True;
8805 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8806 extended_oplock_granted = True;
8809 info_level_return = SVAL(pdata,16);
8811 /* Allocate the correct return size. */
8813 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8814 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8815 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8816 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8818 *pdata_return_size = 12;
8821 /* Realloc the data size */
8822 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8823 if (*ppdata == NULL) {
8824 close_file(req, fsp, ERROR_CLOSE);
8825 *pdata_return_size = 0;
8826 return NT_STATUS_NO_MEMORY;
8830 if (extended_oplock_granted) {
8831 if (flags & REQUEST_BATCH_OPLOCK) {
8832 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8834 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8836 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8837 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8839 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8842 SSVAL(pdata,2,fsp->fnum);
8843 SIVAL(pdata,4,info); /* Was file created etc. */
8845 switch (info_level_return) {
8846 case SMB_QUERY_FILE_UNIX_BASIC:
8847 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8848 SSVAL(pdata,10,0); /* padding. */
8849 store_file_unix_basic(conn, pdata + 12, fsp,
8852 case SMB_QUERY_FILE_UNIX_INFO2:
8853 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8854 SSVAL(pdata,10,0); /* padding. */
8855 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8859 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8860 SSVAL(pdata,10,0); /* padding. */
8863 return NT_STATUS_OK;
8866 /****************************************************************************
8867 Delete a file with POSIX semantics.
8868 ****************************************************************************/
8870 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8871 struct smb_request *req,
8874 struct smb_filename *smb_fname)
8876 NTSTATUS status = NT_STATUS_OK;
8877 files_struct *fsp = NULL;
8881 int create_options = 0;
8882 struct share_mode_lock *lck = NULL;
8883 bool other_nonposix_opens;
8884 struct smb2_create_blobs *posx = NULL;
8886 if (total_data < 2) {
8887 return NT_STATUS_INVALID_PARAMETER;
8890 flags = SVAL(pdata,0);
8892 if (!VALID_STAT(smb_fname->st)) {
8893 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8896 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8897 !VALID_STAT_OF_DIR(smb_fname->st)) {
8898 return NT_STATUS_NOT_A_DIRECTORY;
8901 DEBUG(10,("smb_posix_unlink: %s %s\n",
8902 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8903 smb_fname_str_dbg(smb_fname)));
8905 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8906 create_options |= FILE_DIRECTORY_FILE;
8909 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8910 if (!NT_STATUS_IS_OK(status)) {
8911 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8916 status = SMB_VFS_CREATE_FILE(
8919 0, /* root_dir_fid */
8920 smb_fname, /* fname */
8921 DELETE_ACCESS, /* access_mask */
8922 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8924 FILE_OPEN, /* create_disposition*/
8925 create_options, /* create_options */
8926 0, /* file_attributes */
8927 0, /* oplock_request */
8929 0, /* allocation_size */
8930 0, /* private_flags */
8935 posx, /* in_context_blobs */
8936 NULL); /* out_context_blobs */
8940 if (!NT_STATUS_IS_OK(status)) {
8945 * Don't lie to client. If we can't really delete due to
8946 * non-POSIX opens return SHARING_VIOLATION.
8949 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8951 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8952 "lock for file %s\n", fsp_str_dbg(fsp)));
8953 close_file(req, fsp, NORMAL_CLOSE);
8954 return NT_STATUS_INVALID_PARAMETER;
8957 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8958 if (other_nonposix_opens) {
8959 /* Fail with sharing violation. */
8961 close_file(req, fsp, NORMAL_CLOSE);
8962 return NT_STATUS_SHARING_VIOLATION;
8966 * Set the delete on close.
8968 status = smb_set_file_disposition_info(conn,
8976 if (!NT_STATUS_IS_OK(status)) {
8977 close_file(req, fsp, NORMAL_CLOSE);
8980 return close_file(req, fsp, NORMAL_CLOSE);
8983 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8984 struct smb_request *req,
8985 TALLOC_CTX *mem_ctx,
8986 uint16_t info_level,
8988 struct smb_filename *smb_fname,
8989 char **ppdata, int total_data,
8992 char *pdata = *ppdata;
8993 NTSTATUS status = NT_STATUS_OK;
8994 int data_return_size = 0;
8998 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8999 return NT_STATUS_INVALID_LEVEL;
9002 if (!CAN_WRITE(conn)) {
9003 /* Allow POSIX opens. The open path will deny
9004 * any non-readonly opens. */
9005 if (info_level != SMB_POSIX_PATH_OPEN) {
9006 return NT_STATUS_DOS(ERRSRV, ERRaccess);
9010 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9011 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9013 info_level, total_data));
9015 switch (info_level) {
9017 case SMB_INFO_STANDARD:
9019 status = smb_set_info_standard(conn,
9027 case SMB_INFO_SET_EA:
9029 status = smb_info_set_ea(conn,
9037 case SMB_SET_FILE_BASIC_INFO:
9038 case SMB_FILE_BASIC_INFORMATION:
9040 status = smb_set_file_basic_info(conn,
9048 case SMB_FILE_ALLOCATION_INFORMATION:
9049 case SMB_SET_FILE_ALLOCATION_INFO:
9051 status = smb_set_file_allocation_info(conn, req,
9059 case SMB_FILE_END_OF_FILE_INFORMATION:
9060 case SMB_SET_FILE_END_OF_FILE_INFO:
9063 * XP/Win7 both fail after the createfile with
9064 * SMB_SET_FILE_END_OF_FILE_INFO but not
9065 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9066 * The level is known here, so pass it down
9070 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9072 status = smb_set_file_end_of_file_info(conn, req,
9081 case SMB_FILE_DISPOSITION_INFORMATION:
9082 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9085 /* JRA - We used to just ignore this on a path ?
9086 * Shouldn't this be invalid level on a pathname
9089 if (tran_call != TRANSACT2_SETFILEINFO) {
9090 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9093 status = smb_set_file_disposition_info(conn,
9101 case SMB_FILE_POSITION_INFORMATION:
9103 status = smb_file_position_information(conn,
9110 case SMB_FILE_FULL_EA_INFORMATION:
9112 status = smb_set_file_full_ea_info(conn,
9119 /* From tridge Samba4 :
9120 * MODE_INFORMATION in setfileinfo (I have no
9121 * idea what "mode information" on a file is - it takes a value of 0,
9122 * 2, 4 or 6. What could it be?).
9125 case SMB_FILE_MODE_INFORMATION:
9127 status = smb_file_mode_information(conn,
9133 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9134 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9135 case SMB_FILE_SHORT_NAME_INFORMATION:
9136 return NT_STATUS_NOT_SUPPORTED;
9139 * CIFS UNIX extensions.
9142 case SMB_SET_FILE_UNIX_BASIC:
9144 status = smb_set_file_unix_basic(conn, req,
9152 case SMB_SET_FILE_UNIX_INFO2:
9154 status = smb_set_file_unix_info2(conn, req,
9162 case SMB_SET_FILE_UNIX_LINK:
9165 /* We must have a pathname for this. */
9166 return NT_STATUS_INVALID_LEVEL;
9168 status = smb_set_file_unix_link(conn, req, pdata,
9169 total_data, smb_fname);
9173 case SMB_SET_FILE_UNIX_HLINK:
9176 /* We must have a pathname for this. */
9177 return NT_STATUS_INVALID_LEVEL;
9179 status = smb_set_file_unix_hlink(conn, req,
9185 case SMB_FILE_RENAME_INFORMATION:
9187 status = smb_file_rename_information(conn, req,
9193 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9195 /* SMB2 rename information. */
9196 status = smb2_file_rename_information(conn, req,
9202 case SMB_FILE_LINK_INFORMATION:
9204 status = smb_file_link_information(conn, req,
9210 #if defined(HAVE_POSIX_ACLS)
9211 case SMB_SET_POSIX_ACL:
9213 status = smb_set_posix_acl(conn,
9223 case SMB_SET_POSIX_LOCK:
9226 return NT_STATUS_INVALID_LEVEL;
9228 status = smb_set_posix_lock(conn, req,
9229 pdata, total_data, fsp);
9233 case SMB_POSIX_PATH_OPEN:
9236 /* We must have a pathname for this. */
9237 return NT_STATUS_INVALID_LEVEL;
9240 status = smb_posix_open(conn, req,
9248 case SMB_POSIX_PATH_UNLINK:
9251 /* We must have a pathname for this. */
9252 return NT_STATUS_INVALID_LEVEL;
9255 status = smb_posix_unlink(conn, req,
9263 return NT_STATUS_INVALID_LEVEL;
9266 if (!NT_STATUS_IS_OK(status)) {
9270 *ret_data_size = data_return_size;
9271 return NT_STATUS_OK;
9274 /****************************************************************************
9275 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9276 ****************************************************************************/
9278 static void call_trans2setfilepathinfo(connection_struct *conn,
9279 struct smb_request *req,
9280 unsigned int tran_call,
9281 char **pparams, int total_params,
9282 char **ppdata, int total_data,
9283 unsigned int max_data_bytes)
9285 char *params = *pparams;
9286 char *pdata = *ppdata;
9287 uint16_t info_level;
9288 struct smb_filename *smb_fname = NULL;
9289 files_struct *fsp = NULL;
9290 NTSTATUS status = NT_STATUS_OK;
9291 int data_return_size = 0;
9294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9298 if (tran_call == TRANSACT2_SETFILEINFO) {
9299 if (total_params < 4) {
9300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9304 fsp = file_fsp(req, SVAL(params,0));
9305 /* Basic check for non-null fsp. */
9306 if (!check_fsp_open(conn, req, fsp)) {
9309 info_level = SVAL(params,2);
9311 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9312 if (smb_fname == NULL) {
9313 reply_nterror(req, NT_STATUS_NO_MEMORY);
9317 if(fsp->fh->fd == -1) {
9319 * This is actually a SETFILEINFO on a directory
9320 * handle (returned from an NT SMB). NT5.0 seems
9321 * to do this call. JRA.
9323 if (INFO_LEVEL_IS_UNIX(info_level)) {
9324 /* Always do lstat for UNIX calls. */
9325 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9326 DEBUG(3,("call_trans2setfilepathinfo: "
9327 "SMB_VFS_LSTAT of %s failed "
9329 smb_fname_str_dbg(smb_fname),
9331 reply_nterror(req, map_nt_error_from_unix(errno));
9335 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9336 DEBUG(3,("call_trans2setfilepathinfo: "
9337 "fileinfo of %s failed (%s)\n",
9338 smb_fname_str_dbg(smb_fname),
9340 reply_nterror(req, map_nt_error_from_unix(errno));
9344 } else if (fsp->print_file) {
9346 * Doing a DELETE_ON_CLOSE should cancel a print job.
9348 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9349 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9351 DEBUG(3,("call_trans2setfilepathinfo: "
9352 "Cancelling print job (%s)\n",
9356 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9362 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9367 * Original code - this is an open file.
9369 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9370 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9371 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9373 reply_nterror(req, map_nt_error_from_unix(errno));
9379 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9382 if (total_params < 7) {
9383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9387 info_level = SVAL(params,0);
9388 if (req->posix_pathnames) {
9389 srvstr_get_path_posix(req,
9398 srvstr_get_path(req,
9407 if (!NT_STATUS_IS_OK(status)) {
9408 reply_nterror(req, status);
9412 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9413 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9414 info_level == SMB_FILE_RENAME_INFORMATION ||
9415 info_level == SMB_POSIX_PATH_OPEN ||
9416 info_level == SMB_POSIX_PATH_UNLINK) {
9417 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9420 status = filename_convert(req, conn,
9426 if (!NT_STATUS_IS_OK(status)) {
9427 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9428 reply_botherror(req,
9429 NT_STATUS_PATH_NOT_COVERED,
9430 ERRSRV, ERRbadpath);
9433 reply_nterror(req, status);
9437 if (INFO_LEVEL_IS_UNIX(info_level)) {
9439 * For CIFS UNIX extensions the target name may not exist.
9442 /* Always do lstat for UNIX calls. */
9443 SMB_VFS_LSTAT(conn, smb_fname);
9445 } else if (!VALID_STAT(smb_fname->st) &&
9446 SMB_VFS_STAT(conn, smb_fname)) {
9447 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9449 smb_fname_str_dbg(smb_fname),
9451 reply_nterror(req, map_nt_error_from_unix(errno));
9456 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9457 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9459 info_level,total_data));
9461 /* Realloc the parameter size */
9462 *pparams = (char *)SMB_REALLOC(*pparams,2);
9463 if (*pparams == NULL) {
9464 reply_nterror(req, NT_STATUS_NO_MEMORY);
9471 status = smbd_do_setfilepathinfo(conn, req, req,
9477 if (!NT_STATUS_IS_OK(status)) {
9478 if (open_was_deferred(req->xconn, req->mid)) {
9479 /* We have re-scheduled this call. */
9482 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9483 bool ok = defer_smb1_sharing_violation(req);
9488 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9489 /* We have re-scheduled this call. */
9492 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9493 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9494 ERRSRV, ERRbadpath);
9497 if (info_level == SMB_POSIX_PATH_OPEN) {
9498 reply_openerror(req, status);
9503 * Invalid EA name needs to return 2 param bytes,
9504 * not a zero-length error packet.
9506 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9507 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9510 reply_nterror(req, status);
9515 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9521 /****************************************************************************
9522 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9523 ****************************************************************************/
9525 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9526 char **pparams, int total_params,
9527 char **ppdata, int total_data,
9528 unsigned int max_data_bytes)
9530 struct smb_filename *smb_dname = NULL;
9531 char *params = *pparams;
9532 char *pdata = *ppdata;
9533 char *directory = NULL;
9534 NTSTATUS status = NT_STATUS_OK;
9535 struct ea_list *ea_list = NULL;
9536 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9537 TALLOC_CTX *ctx = talloc_tos();
9539 if (!CAN_WRITE(conn)) {
9540 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9544 if (total_params < 5) {
9545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9549 if (req->posix_pathnames) {
9550 srvstr_get_path_posix(ctx,
9559 srvstr_get_path(ctx,
9568 if (!NT_STATUS_IS_OK(status)) {
9569 reply_nterror(req, status);
9573 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9575 status = filename_convert(ctx,
9583 if (!NT_STATUS_IS_OK(status)) {
9584 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9585 reply_botherror(req,
9586 NT_STATUS_PATH_NOT_COVERED,
9587 ERRSRV, ERRbadpath);
9590 reply_nterror(req, status);
9595 * OS/2 workplace shell seems to send SET_EA requests of "null"
9596 * length (4 bytes containing IVAL 4).
9597 * They seem to have no effect. Bug #3212. JRA.
9600 if (total_data && (total_data != 4)) {
9601 /* Any data in this call is an EA list. */
9602 if (total_data < 10) {
9603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9607 if (IVAL(pdata,0) > total_data) {
9608 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9609 IVAL(pdata,0), (unsigned int)total_data));
9610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9614 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9621 if (!lp_ea_support(SNUM(conn))) {
9622 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9626 /* If total_data == 4 Windows doesn't care what values
9627 * are placed in that field, it just ignores them.
9628 * The System i QNTC IBM SMB client puts bad values here,
9629 * so ignore them. */
9631 status = create_directory(conn, req, smb_dname);
9633 if (!NT_STATUS_IS_OK(status)) {
9634 reply_nterror(req, status);
9638 /* Try and set any given EA. */
9640 status = set_ea(conn, NULL, smb_dname, ea_list);
9641 if (!NT_STATUS_IS_OK(status)) {
9642 reply_nterror(req, status);
9647 /* Realloc the parameter and data sizes */
9648 *pparams = (char *)SMB_REALLOC(*pparams,2);
9649 if(*pparams == NULL) {
9650 reply_nterror(req, NT_STATUS_NO_MEMORY);
9657 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9660 TALLOC_FREE(smb_dname);
9664 /****************************************************************************
9665 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9666 We don't actually do this - we just send a null response.
9667 ****************************************************************************/
9669 static void call_trans2findnotifyfirst(connection_struct *conn,
9670 struct smb_request *req,
9671 char **pparams, int total_params,
9672 char **ppdata, int total_data,
9673 unsigned int max_data_bytes)
9675 char *params = *pparams;
9676 uint16_t info_level;
9678 if (total_params < 6) {
9679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9683 info_level = SVAL(params,4);
9684 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9686 switch (info_level) {
9691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9695 /* Realloc the parameter and data sizes */
9696 *pparams = (char *)SMB_REALLOC(*pparams,6);
9697 if (*pparams == NULL) {
9698 reply_nterror(req, NT_STATUS_NO_MEMORY);
9703 SSVAL(params,0,fnf_handle);
9704 SSVAL(params,2,0); /* No changes */
9705 SSVAL(params,4,0); /* No EA errors */
9712 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9717 /****************************************************************************
9718 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9719 changes). Currently this does nothing.
9720 ****************************************************************************/
9722 static void call_trans2findnotifynext(connection_struct *conn,
9723 struct smb_request *req,
9724 char **pparams, int total_params,
9725 char **ppdata, int total_data,
9726 unsigned int max_data_bytes)
9728 char *params = *pparams;
9730 DEBUG(3,("call_trans2findnotifynext\n"));
9732 /* Realloc the parameter and data sizes */
9733 *pparams = (char *)SMB_REALLOC(*pparams,4);
9734 if (*pparams == NULL) {
9735 reply_nterror(req, NT_STATUS_NO_MEMORY);
9740 SSVAL(params,0,0); /* No changes */
9741 SSVAL(params,2,0); /* No EA errors */
9743 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9748 /****************************************************************************
9749 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9750 ****************************************************************************/
9752 static void call_trans2getdfsreferral(connection_struct *conn,
9753 struct smb_request *req,
9754 char **pparams, int total_params,
9755 char **ppdata, int total_data,
9756 unsigned int max_data_bytes)
9758 char *params = *pparams;
9759 char *pathname = NULL;
9761 int max_referral_level;
9762 NTSTATUS status = NT_STATUS_OK;
9763 TALLOC_CTX *ctx = talloc_tos();
9765 DEBUG(10,("call_trans2getdfsreferral\n"));
9767 if (total_params < 3) {
9768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9772 max_referral_level = SVAL(params,0);
9774 if(!lp_host_msdfs()) {
9775 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9779 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9780 total_params - 2, STR_TERMINATE);
9782 reply_nterror(req, NT_STATUS_NOT_FOUND);
9785 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9786 ppdata,&status)) < 0) {
9787 reply_nterror(req, status);
9791 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9792 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9793 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9798 #define LMCAT_SPL 0x53
9799 #define LMFUNC_GETJOBID 0x60
9801 /****************************************************************************
9802 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9803 ****************************************************************************/
9805 static void call_trans2ioctl(connection_struct *conn,
9806 struct smb_request *req,
9807 char **pparams, int total_params,
9808 char **ppdata, int total_data,
9809 unsigned int max_data_bytes)
9811 const struct loadparm_substitution *lp_sub =
9812 loadparm_s3_global_substitution();
9813 char *pdata = *ppdata;
9814 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9818 /* check for an invalid fid before proceeding */
9821 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9825 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9826 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9827 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9828 if (*ppdata == NULL) {
9829 reply_nterror(req, NT_STATUS_NO_MEMORY);
9834 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9835 CAN ACCEPT THIS IN UNICODE. JRA. */
9838 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9840 status = srvstr_push(pdata, req->flags2, pdata + 2,
9841 lp_netbios_name(), 15,
9842 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9843 if (!NT_STATUS_IS_OK(status)) {
9844 reply_nterror(req, status);
9847 status = srvstr_push(pdata, req->flags2, pdata+18,
9848 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9849 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9850 if (!NT_STATUS_IS_OK(status)) {
9851 reply_nterror(req, status);
9854 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9859 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9860 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9863 /****************************************************************************
9864 Reply to a SMBfindclose (stop trans2 directory search).
9865 ****************************************************************************/
9867 void reply_findclose(struct smb_request *req)
9870 struct smbd_server_connection *sconn = req->sconn;
9871 files_struct *fsp = NULL;
9873 START_PROFILE(SMBfindclose);
9876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9877 END_PROFILE(SMBfindclose);
9881 dptr_num = SVALS(req->vwv+0, 0);
9883 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9886 * OS/2 seems to use -1 to indicate "close all directories"
9887 * This has to mean on this specific connection struct.
9889 if (dptr_num == -1) {
9890 dptr_closecnum(req->conn);
9892 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9895 close_file(NULL, fsp, NORMAL_CLOSE);
9900 reply_outbuf(req, 0, 0);
9902 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9904 END_PROFILE(SMBfindclose);
9908 /****************************************************************************
9909 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9910 ****************************************************************************/
9912 void reply_findnclose(struct smb_request *req)
9916 START_PROFILE(SMBfindnclose);
9919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9920 END_PROFILE(SMBfindnclose);
9924 dptr_num = SVAL(req->vwv+0, 0);
9926 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9928 /* We never give out valid handles for a
9929 findnotifyfirst - so any dptr_num is ok here.
9932 reply_outbuf(req, 0, 0);
9934 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9936 END_PROFILE(SMBfindnclose);
9940 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9941 struct trans_state *state)
9943 if (get_Protocol() >= PROTOCOL_NT1) {
9944 req->flags2 |= 0x40; /* IS_LONG_NAME */
9945 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9948 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9949 if (state->call != TRANSACT2_QFSINFO &&
9950 state->call != TRANSACT2_SETFSINFO) {
9951 DEBUG(0,("handle_trans2: encryption required "
9953 (unsigned int)state->call));
9954 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9959 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9961 /* Now we must call the relevant TRANS2 function */
9962 switch(state->call) {
9963 case TRANSACT2_OPEN:
9965 START_PROFILE(Trans2_open);
9966 call_trans2open(conn, req,
9967 &state->param, state->total_param,
9968 &state->data, state->total_data,
9969 state->max_data_return);
9970 END_PROFILE(Trans2_open);
9974 case TRANSACT2_FINDFIRST:
9976 START_PROFILE(Trans2_findfirst);
9977 call_trans2findfirst(conn, req,
9978 &state->param, state->total_param,
9979 &state->data, state->total_data,
9980 state->max_data_return);
9981 END_PROFILE(Trans2_findfirst);
9985 case TRANSACT2_FINDNEXT:
9987 START_PROFILE(Trans2_findnext);
9988 call_trans2findnext(conn, req,
9989 &state->param, state->total_param,
9990 &state->data, state->total_data,
9991 state->max_data_return);
9992 END_PROFILE(Trans2_findnext);
9996 case TRANSACT2_QFSINFO:
9998 START_PROFILE(Trans2_qfsinfo);
9999 call_trans2qfsinfo(conn, req,
10000 &state->param, state->total_param,
10001 &state->data, state->total_data,
10002 state->max_data_return);
10003 END_PROFILE(Trans2_qfsinfo);
10007 case TRANSACT2_SETFSINFO:
10009 START_PROFILE(Trans2_setfsinfo);
10010 call_trans2setfsinfo(conn, req,
10011 &state->param, state->total_param,
10012 &state->data, state->total_data,
10013 state->max_data_return);
10014 END_PROFILE(Trans2_setfsinfo);
10018 case TRANSACT2_QPATHINFO:
10019 case TRANSACT2_QFILEINFO:
10021 START_PROFILE(Trans2_qpathinfo);
10022 call_trans2qfilepathinfo(conn, req, state->call,
10023 &state->param, state->total_param,
10024 &state->data, state->total_data,
10025 state->max_data_return);
10026 END_PROFILE(Trans2_qpathinfo);
10030 case TRANSACT2_SETPATHINFO:
10031 case TRANSACT2_SETFILEINFO:
10033 START_PROFILE(Trans2_setpathinfo);
10034 call_trans2setfilepathinfo(conn, req, state->call,
10035 &state->param, state->total_param,
10036 &state->data, state->total_data,
10037 state->max_data_return);
10038 END_PROFILE(Trans2_setpathinfo);
10042 case TRANSACT2_FINDNOTIFYFIRST:
10044 START_PROFILE(Trans2_findnotifyfirst);
10045 call_trans2findnotifyfirst(conn, req,
10046 &state->param, state->total_param,
10047 &state->data, state->total_data,
10048 state->max_data_return);
10049 END_PROFILE(Trans2_findnotifyfirst);
10053 case TRANSACT2_FINDNOTIFYNEXT:
10055 START_PROFILE(Trans2_findnotifynext);
10056 call_trans2findnotifynext(conn, req,
10057 &state->param, state->total_param,
10058 &state->data, state->total_data,
10059 state->max_data_return);
10060 END_PROFILE(Trans2_findnotifynext);
10064 case TRANSACT2_MKDIR:
10066 START_PROFILE(Trans2_mkdir);
10067 call_trans2mkdir(conn, req,
10068 &state->param, state->total_param,
10069 &state->data, state->total_data,
10070 state->max_data_return);
10071 END_PROFILE(Trans2_mkdir);
10075 case TRANSACT2_GET_DFS_REFERRAL:
10077 START_PROFILE(Trans2_get_dfs_referral);
10078 call_trans2getdfsreferral(conn, req,
10079 &state->param, state->total_param,
10080 &state->data, state->total_data,
10081 state->max_data_return);
10082 END_PROFILE(Trans2_get_dfs_referral);
10086 case TRANSACT2_IOCTL:
10088 START_PROFILE(Trans2_ioctl);
10089 call_trans2ioctl(conn, req,
10090 &state->param, state->total_param,
10091 &state->data, state->total_data,
10092 state->max_data_return);
10093 END_PROFILE(Trans2_ioctl);
10098 /* Error in request */
10099 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10100 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10104 /****************************************************************************
10105 Reply to a SMBtrans2.
10106 ****************************************************************************/
10108 void reply_trans2(struct smb_request *req)
10110 connection_struct *conn = req->conn;
10111 unsigned int dsoff;
10112 unsigned int dscnt;
10113 unsigned int psoff;
10114 unsigned int pscnt;
10115 unsigned int tran_call;
10116 struct trans_state *state;
10119 START_PROFILE(SMBtrans2);
10121 if (req->wct < 14) {
10122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10123 END_PROFILE(SMBtrans2);
10127 dsoff = SVAL(req->vwv+12, 0);
10128 dscnt = SVAL(req->vwv+11, 0);
10129 psoff = SVAL(req->vwv+10, 0);
10130 pscnt = SVAL(req->vwv+9, 0);
10131 tran_call = SVAL(req->vwv+14, 0);
10133 result = allow_new_trans(conn->pending_trans, req->mid);
10134 if (!NT_STATUS_IS_OK(result)) {
10135 DEBUG(2, ("Got invalid trans2 request: %s\n",
10136 nt_errstr(result)));
10137 reply_nterror(req, result);
10138 END_PROFILE(SMBtrans2);
10142 if (IS_IPC(conn)) {
10143 switch (tran_call) {
10144 /* List the allowed trans2 calls on IPC$ */
10145 case TRANSACT2_OPEN:
10146 case TRANSACT2_GET_DFS_REFERRAL:
10147 case TRANSACT2_QFILEINFO:
10148 case TRANSACT2_QFSINFO:
10149 case TRANSACT2_SETFSINFO:
10152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10153 END_PROFILE(SMBtrans2);
10158 if ((state = talloc(conn, struct trans_state)) == NULL) {
10159 DEBUG(0, ("talloc failed\n"));
10160 reply_nterror(req, NT_STATUS_NO_MEMORY);
10161 END_PROFILE(SMBtrans2);
10165 state->cmd = SMBtrans2;
10167 state->mid = req->mid;
10168 state->vuid = req->vuid;
10169 state->setup_count = SVAL(req->vwv+13, 0);
10170 state->setup = NULL;
10171 state->total_param = SVAL(req->vwv+0, 0);
10172 state->param = NULL;
10173 state->total_data = SVAL(req->vwv+1, 0);
10174 state->data = NULL;
10175 state->max_param_return = SVAL(req->vwv+2, 0);
10176 state->max_data_return = SVAL(req->vwv+3, 0);
10177 state->max_setup_return = SVAL(req->vwv+4, 0);
10178 state->close_on_completion = BITSETW(req->vwv+5, 0);
10179 state->one_way = BITSETW(req->vwv+5, 1);
10181 state->call = tran_call;
10183 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10184 is so as a sanity check */
10185 if (state->setup_count != 1) {
10187 * Need to have rc=0 for ioctl to get job id for OS/2.
10188 * Network printing will fail if function is not successful.
10189 * Similar function in reply.c will be used if protocol
10190 * is LANMAN1.0 instead of LM1.2X002.
10191 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10192 * outbuf doesn't have to be set(only job id is used).
10194 if ( (state->setup_count == 4)
10195 && (tran_call == TRANSACT2_IOCTL)
10196 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10197 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10198 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10200 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10201 DEBUG(2,("Transaction is %d\n",tran_call));
10202 TALLOC_FREE(state);
10203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10204 END_PROFILE(SMBtrans2);
10209 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10212 if (state->total_data) {
10214 if (trans_oob(state->total_data, 0, dscnt)
10215 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10219 /* Can't use talloc here, the core routines do realloc on the
10220 * params and data. */
10221 state->data = (char *)SMB_MALLOC(state->total_data);
10222 if (state->data == NULL) {
10223 DEBUG(0,("reply_trans2: data malloc fail for %u "
10224 "bytes !\n", (unsigned int)state->total_data));
10225 TALLOC_FREE(state);
10226 reply_nterror(req, NT_STATUS_NO_MEMORY);
10227 END_PROFILE(SMBtrans2);
10231 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10234 if (state->total_param) {
10236 if (trans_oob(state->total_param, 0, pscnt)
10237 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10241 /* Can't use talloc here, the core routines do realloc on the
10242 * params and data. */
10243 state->param = (char *)SMB_MALLOC(state->total_param);
10244 if (state->param == NULL) {
10245 DEBUG(0,("reply_trans: param malloc fail for %u "
10246 "bytes !\n", (unsigned int)state->total_param));
10247 SAFE_FREE(state->data);
10248 TALLOC_FREE(state);
10249 reply_nterror(req, NT_STATUS_NO_MEMORY);
10250 END_PROFILE(SMBtrans2);
10254 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10257 state->received_data = dscnt;
10258 state->received_param = pscnt;
10260 if ((state->received_param == state->total_param) &&
10261 (state->received_data == state->total_data)) {
10263 handle_trans2(conn, req, state);
10265 SAFE_FREE(state->data);
10266 SAFE_FREE(state->param);
10267 TALLOC_FREE(state);
10268 END_PROFILE(SMBtrans2);
10272 DLIST_ADD(conn->pending_trans, state);
10274 /* We need to send an interim response then receive the rest
10275 of the parameter/data bytes */
10276 reply_outbuf(req, 0, 0);
10277 show_msg((char *)req->outbuf);
10278 END_PROFILE(SMBtrans2);
10283 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10284 SAFE_FREE(state->data);
10285 SAFE_FREE(state->param);
10286 TALLOC_FREE(state);
10287 END_PROFILE(SMBtrans2);
10288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10292 /****************************************************************************
10293 Reply to a SMBtranss2
10294 ****************************************************************************/
10296 void reply_transs2(struct smb_request *req)
10298 connection_struct *conn = req->conn;
10299 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10300 struct trans_state *state;
10302 START_PROFILE(SMBtranss2);
10304 show_msg((const char *)req->inbuf);
10306 /* Windows clients expect all replies to
10307 a transact secondary (SMBtranss2 0x33)
10308 to have a command code of transact
10309 (SMBtrans2 0x32). See bug #8989
10310 and also [MS-CIFS] section 2.2.4.47.2
10313 req->cmd = SMBtrans2;
10315 if (req->wct < 8) {
10316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10317 END_PROFILE(SMBtranss2);
10321 for (state = conn->pending_trans; state != NULL;
10322 state = state->next) {
10323 if (state->mid == req->mid) {
10328 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10330 END_PROFILE(SMBtranss2);
10334 /* Revise state->total_param and state->total_data in case they have
10335 changed downwards */
10337 if (SVAL(req->vwv+0, 0) < state->total_param)
10338 state->total_param = SVAL(req->vwv+0, 0);
10339 if (SVAL(req->vwv+1, 0) < state->total_data)
10340 state->total_data = SVAL(req->vwv+1, 0);
10342 pcnt = SVAL(req->vwv+2, 0);
10343 poff = SVAL(req->vwv+3, 0);
10344 pdisp = SVAL(req->vwv+4, 0);
10346 dcnt = SVAL(req->vwv+5, 0);
10347 doff = SVAL(req->vwv+6, 0);
10348 ddisp = SVAL(req->vwv+7, 0);
10350 state->received_param += pcnt;
10351 state->received_data += dcnt;
10353 if ((state->received_data > state->total_data) ||
10354 (state->received_param > state->total_param))
10358 if (trans_oob(state->total_param, pdisp, pcnt)
10359 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10362 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10366 if (trans_oob(state->total_data, ddisp, dcnt)
10367 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10370 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10373 if ((state->received_param < state->total_param) ||
10374 (state->received_data < state->total_data)) {
10375 END_PROFILE(SMBtranss2);
10379 handle_trans2(conn, req, state);
10381 DLIST_REMOVE(conn->pending_trans, state);
10382 SAFE_FREE(state->data);
10383 SAFE_FREE(state->param);
10384 TALLOC_FREE(state);
10386 END_PROFILE(SMBtranss2);
10391 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10392 DLIST_REMOVE(conn->pending_trans, state);
10393 SAFE_FREE(state->data);
10394 SAFE_FREE(state->param);
10395 TALLOC_FREE(state);
10396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10397 END_PROFILE(SMBtranss2);