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 &conn->cwd_fsp, /* dirfsp */
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 &conn->cwd_fsp, /* dirfsp */
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 struct smb_filename *old_name = smb_dname;
2887 /* Ensure we don't have a directory name of "". */
2888 smb_dname = synthetic_smb_fname(talloc_tos(),
2894 TALLOC_FREE(old_name);
2895 if (smb_dname == NULL) {
2896 reply_nterror(req, NT_STATUS_NO_MEMORY);
2899 directory = smb_dname->base_name;
2902 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2904 if (info_level == SMB_FIND_EA_LIST) {
2907 if (total_data < 4) {
2908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2912 ea_size = IVAL(pdata,0);
2913 if (ea_size != total_data) {
2914 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2915 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2920 if (!lp_ea_support(SNUM(conn))) {
2921 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2925 /* Pull out the list of names. */
2926 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2933 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2938 *ppdata = (char *)SMB_REALLOC(
2939 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2940 if(*ppdata == NULL ) {
2941 reply_nterror(req, NT_STATUS_NO_MEMORY);
2945 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2947 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2950 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2951 /* Realloc the params space */
2952 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2953 if (*pparams == NULL) {
2954 reply_nterror(req, NT_STATUS_NO_MEMORY);
2960 * As we've cut off the last component from
2961 * smb_fname we need to re-stat smb_dname
2962 * so FILE_OPEN disposition knows the directory
2965 if (req->posix_pathnames) {
2966 ret = SMB_VFS_LSTAT(conn, smb_dname);
2968 ret = SMB_VFS_STAT(conn, smb_dname);
2972 ntstatus = map_nt_error_from_unix(errno);
2973 reply_nterror(req, ntstatus);
2978 * Open an fsp on this directory for the dptr.
2980 ntstatus = SMB_VFS_CREATE_FILE(
2983 &conn->cwd_fsp, /* dirfsp */
2984 smb_dname, /* dname */
2985 FILE_LIST_DIRECTORY, /* access_mask */
2987 FILE_SHARE_WRITE, /* share_access */
2988 FILE_OPEN, /* create_disposition*/
2989 FILE_DIRECTORY_FILE, /* create_options */
2990 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2991 NO_OPLOCK, /* oplock_request */
2993 0, /* allocation_size */
2994 0, /* private_flags */
2999 NULL, /* in_context */
3000 NULL);/* out_context */
3002 if (!NT_STATUS_IS_OK(ntstatus)) {
3003 DBG_ERR("failed to open directory %s\n",
3004 smb_fname_str_dbg(smb_dname));
3005 reply_nterror(req, ntstatus);
3009 /* Save the wildcard match and attribs we are using on this directory -
3010 needed as lanman2 assumes these are being saved between calls */
3012 ntstatus = dptr_create(conn,
3019 mask_contains_wcard,
3023 if (!NT_STATUS_IS_OK(ntstatus)) {
3025 * Use NULL here for the first parameter (req)
3026 * as this is not a client visible handle so
3027 * can'tbe part of an SMB1 chain.
3029 close_file(NULL, fsp, NORMAL_CLOSE);
3031 reply_nterror(req, ntstatus);
3036 /* Remember this in case we have
3037 to do a findnext. */
3038 dptr_set_priv(fsp->dptr);
3041 dptr_num = dptr_dnum(fsp->dptr);
3042 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3044 /* We don't need to check for VOL here as this is returned by
3045 a different TRANS2 call. */
3047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3048 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3049 if (in_list(directory,
3050 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3051 conn->case_sensitive)) {
3052 dont_descend = True;
3056 space_remaining = max_data_bytes;
3057 out_of_space = False;
3059 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3060 bool got_exact_match = False;
3062 /* this is a heuristic to avoid seeking the dirptr except when
3063 absolutely necessary. It allows for a filename of about 40 chars */
3064 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3065 out_of_space = True;
3068 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3072 mask,dirtype,info_level,
3073 requires_resume_key,dont_descend,
3078 &last_entry_off, ea_list);
3079 if (NT_STATUS_EQUAL(ntstatus,
3080 NT_STATUS_ILLEGAL_CHARACTER)) {
3082 * Bad character conversion on name. Ignore this
3087 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3088 out_of_space = true;
3090 finished = !NT_STATUS_IS_OK(ntstatus);
3094 if (!finished && !out_of_space)
3098 * As an optimisation if we know we aren't looking
3099 * for a wildcard name (ie. the name matches the wildcard exactly)
3100 * then we can finish on any (first) match.
3101 * This speeds up large directory searches. JRA.
3107 /* Ensure space_remaining never goes -ve. */
3108 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3109 space_remaining = 0;
3110 out_of_space = true;
3112 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3116 /* Check if we can close the dirptr */
3117 if(close_after_first || (finished && close_if_end)) {
3118 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3120 close_file(NULL, fsp, NORMAL_CLOSE);
3125 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3126 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3127 * the protocol level is less than NT1. Tested with smbclient. JRA.
3128 * This should fix the OS/2 client bug #2335.
3131 if(numentries == 0) {
3134 * We may have already closed the file in the
3135 * close_after_first or finished case above.
3138 close_file(NULL, fsp, NORMAL_CLOSE);
3141 if (get_Protocol() < PROTOCOL_NT1) {
3142 reply_force_doserror(req, ERRDOS, ERRnofiles);
3145 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3146 ERRDOS, ERRbadfile);
3151 /* At this point pdata points to numentries directory entries. */
3153 /* Set up the return parameter block */
3154 SSVAL(params,0,dptr_num);
3155 SSVAL(params,2,numentries);
3156 SSVAL(params,4,finished);
3157 SSVAL(params,6,0); /* Never an EA error */
3158 SSVAL(params,8,last_entry_off);
3160 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3163 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3164 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3166 reply_nterror(req, NT_STATUS_NO_MEMORY);
3170 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3171 smb_fn_name(req->cmd),
3172 mask, directory, dirtype, numentries ) );
3175 * Force a name mangle here to ensure that the
3176 * mask as an 8.3 name is top of the mangled cache.
3177 * The reasons for this are subtle. Don't remove
3178 * this code unless you know what you are doing
3179 * (see PR#13758). JRA.
3182 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3183 char mangled_name[13];
3184 name_to_8_3(mask, mangled_name, True, conn->params);
3192 TALLOC_FREE(smb_dname);
3196 /****************************************************************************
3197 Reply to a TRANS2_FINDNEXT.
3198 ****************************************************************************/
3200 static void call_trans2findnext(connection_struct *conn,
3201 struct smb_request *req,
3202 char **pparams, int total_params,
3203 char **ppdata, int total_data,
3204 unsigned int max_data_bytes)
3206 /* We must be careful here that we don't return more than the
3207 allowed number of data bytes. If this means returning fewer than
3208 maxentries then so be it. We assume that the redirector has
3209 enough room for the fixed number of parameter bytes it has
3211 char *params = *pparams;
3212 char *pdata = *ppdata;
3216 uint16_t info_level;
3217 uint32_t resume_key;
3218 uint16_t findnext_flags;
3219 bool close_after_request;
3221 bool requires_resume_key;
3223 bool mask_contains_wcard = False;
3224 char *resume_name = NULL;
3225 const char *mask = NULL;
3226 const char *directory = NULL;
3230 int i, last_entry_off=0;
3231 bool finished = False;
3232 bool dont_descend = False;
3233 bool out_of_space = False;
3234 int space_remaining;
3235 struct ea_list *ea_list = NULL;
3236 NTSTATUS ntstatus = NT_STATUS_OK;
3237 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3238 TALLOC_CTX *ctx = talloc_tos();
3239 struct smbd_server_connection *sconn = req->sconn;
3240 bool backup_priv = false;
3241 bool as_root = false;
3242 files_struct *fsp = NULL;
3243 const struct loadparm_substitution *lp_sub =
3244 loadparm_s3_global_substitution();
3246 if (total_params < 13) {
3247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3251 dptr_num = SVAL(params,0);
3252 maxentries = SVAL(params,2);
3253 info_level = SVAL(params,4);
3254 resume_key = IVAL(params,6);
3255 findnext_flags = SVAL(params,10);
3256 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3257 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3258 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3259 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3261 if (!continue_bit) {
3262 /* We only need resume_name if continue_bit is zero. */
3263 if (req->posix_pathnames) {
3264 srvstr_get_path_wcard_posix(ctx,
3272 &mask_contains_wcard);
3274 srvstr_get_path_wcard(ctx,
3282 &mask_contains_wcard);
3284 if (!NT_STATUS_IS_OK(ntstatus)) {
3285 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3286 complain (it thinks we're asking for the directory above the shared
3287 path or an invalid name). Catch this as the resume name is only compared, never used in
3288 a file access. JRA. */
3289 srvstr_pull_talloc(ctx, params, req->flags2,
3290 &resume_name, params+12,
3294 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3295 reply_nterror(req, ntstatus);
3301 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3302 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3303 resume_key = %d resume name = %s continue=%d level = %d\n",
3304 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3305 requires_resume_key, resume_key,
3306 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3309 /* W2K3 seems to treat zero as 1. */
3313 switch (info_level) {
3314 case SMB_FIND_INFO_STANDARD:
3315 case SMB_FIND_EA_SIZE:
3316 case SMB_FIND_EA_LIST:
3317 case SMB_FIND_FILE_DIRECTORY_INFO:
3318 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3319 case SMB_FIND_FILE_NAMES_INFO:
3320 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3321 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3322 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3324 case SMB_FIND_FILE_UNIX:
3325 case SMB_FIND_FILE_UNIX_INFO2:
3326 /* Always use filesystem for UNIX mtime query. */
3327 ask_sharemode = false;
3328 if (!lp_unix_extensions()) {
3329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3334 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3338 if (info_level == SMB_FIND_EA_LIST) {
3341 if (total_data < 4) {
3342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3346 ea_size = IVAL(pdata,0);
3347 if (ea_size != total_data) {
3348 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3349 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3354 if (!lp_ea_support(SNUM(conn))) {
3355 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3359 /* Pull out the list of names. */
3360 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3367 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3372 *ppdata = (char *)SMB_REALLOC(
3373 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3374 if(*ppdata == NULL) {
3375 reply_nterror(req, NT_STATUS_NO_MEMORY);
3380 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3383 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3386 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3387 /* Realloc the params space */
3388 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3389 if(*pparams == NULL ) {
3390 reply_nterror(req, NT_STATUS_NO_MEMORY);
3396 /* Check that the dptr is valid */
3397 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3399 reply_nterror(req, STATUS_NO_MORE_FILES);
3403 directory = dptr_path(sconn, dptr_num);
3405 /* Get the wildcard mask from the dptr */
3406 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3407 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3408 reply_nterror(req, STATUS_NO_MORE_FILES);
3412 /* Get the attr mask from the dptr */
3413 dirtype = dptr_attr(sconn, dptr_num);
3415 backup_priv = dptr_get_priv(fsp->dptr);
3417 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3418 "backup_priv = %d\n",
3419 dptr_num, mask, dirtype,
3421 dptr_TellDir(fsp->dptr),
3424 /* We don't need to check for VOL here as this is returned by
3425 a different TRANS2 call. */
3427 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3428 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3429 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3430 dont_descend = True;
3433 space_remaining = max_data_bytes;
3434 out_of_space = False;
3442 * Seek to the correct position. We no longer use the resume key but
3443 * depend on the last file name instead.
3446 if(!continue_bit && resume_name && *resume_name) {
3449 long current_pos = 0;
3451 * Remember, name_to_8_3 is called by
3452 * get_lanman2_dir_entry(), so the resume name
3453 * could be mangled. Ensure we check the unmangled name.
3456 if (mangle_is_mangled(resume_name, conn->params)) {
3457 char *new_resume_name = NULL;
3458 mangle_lookup_name_from_8_3(ctx,
3462 if (new_resume_name) {
3463 resume_name = new_resume_name;
3468 * Fix for NT redirector problem triggered by resume key indexes
3469 * changing between directory scans. We now return a resume key of 0
3470 * and instead look for the filename to continue from (also given
3471 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3472 * findfirst/findnext (as is usual) then the directory pointer
3473 * should already be at the correct place.
3476 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3477 } /* end if resume_name && !continue_bit */
3479 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3480 bool got_exact_match = False;
3482 /* this is a heuristic to avoid seeking the fsp->dptr except when
3483 absolutely necessary. It allows for a filename of about 40 chars */
3484 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3485 out_of_space = True;
3488 ntstatus = get_lanman2_dir_entry(ctx,
3492 mask,dirtype,info_level,
3493 requires_resume_key,dont_descend,
3498 &last_entry_off, ea_list);
3499 if (NT_STATUS_EQUAL(ntstatus,
3500 NT_STATUS_ILLEGAL_CHARACTER)) {
3502 * Bad character conversion on name. Ignore this
3507 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3508 out_of_space = true;
3510 finished = !NT_STATUS_IS_OK(ntstatus);
3514 if (!finished && !out_of_space)
3518 * As an optimisation if we know we aren't looking
3519 * for a wildcard name (ie. the name matches the wildcard exactly)
3520 * then we can finish on any (first) match.
3521 * This speeds up large directory searches. JRA.
3527 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3530 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3531 smb_fn_name(req->cmd),
3532 mask, directory, dirtype, numentries ) );
3534 /* Check if we can close the fsp->dptr */
3535 if(close_after_request || (finished && close_if_end)) {
3536 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3538 close_file(NULL, fsp, NORMAL_CLOSE);
3546 /* Set up the return parameter block */
3547 SSVAL(params,0,numentries);
3548 SSVAL(params,2,finished);
3549 SSVAL(params,4,0); /* Never an EA error */
3550 SSVAL(params,6,last_entry_off);
3552 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3558 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3560 const struct loadparm_substitution *lp_sub =
3561 loadparm_s3_global_substitution();
3563 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3567 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3569 SMB_ASSERT(extended_info != NULL);
3571 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3572 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3573 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3574 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3575 #ifdef SAMBA_VERSION_REVISION
3576 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3578 extended_info->samba_subversion = 0;
3579 #ifdef SAMBA_VERSION_RC_RELEASE
3580 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3582 #ifdef SAMBA_VERSION_PRE_RELEASE
3583 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3586 #ifdef SAMBA_VERSION_VENDOR_PATCH
3587 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3589 extended_info->samba_gitcommitdate = 0;
3590 #ifdef SAMBA_VERSION_COMMIT_TIME
3591 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3594 memset(extended_info->samba_version_string, 0,
3595 sizeof(extended_info->samba_version_string));
3597 snprintf (extended_info->samba_version_string,
3598 sizeof(extended_info->samba_version_string),
3599 "%s", samba_version_string());
3602 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3603 connection_struct *conn,
3604 TALLOC_CTX *mem_ctx,
3605 uint16_t info_level,
3607 unsigned int max_data_bytes,
3608 size_t *fixed_portion,
3609 struct smb_filename *fname,
3613 const struct loadparm_substitution *lp_sub =
3614 loadparm_s3_global_substitution();
3615 char *pdata, *end_data;
3618 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3619 int snum = SNUM(conn);
3620 const char *fstype = lp_fstype(SNUM(conn));
3621 const char *filename = NULL;
3622 const uint64_t bytes_per_sector = 512;
3623 uint32_t additional_flags = 0;
3624 struct smb_filename smb_fname;
3626 NTSTATUS status = NT_STATUS_OK;
3629 if (fname == NULL || fname->base_name == NULL) {
3632 filename = fname->base_name;
3636 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3637 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3638 "info level (0x%x) on IPC$.\n",
3639 (unsigned int)info_level));
3640 return NT_STATUS_ACCESS_DENIED;
3644 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3646 ZERO_STRUCT(smb_fname);
3647 smb_fname.base_name = discard_const_p(char, filename);
3649 if(info_level != SMB_FS_QUOTA_INFORMATION
3650 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3651 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3652 return map_nt_error_from_unix(errno);
3657 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3658 return NT_STATUS_INVALID_PARAMETER;
3661 *ppdata = (char *)SMB_REALLOC(
3662 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3663 if (*ppdata == NULL) {
3664 return NT_STATUS_NO_MEMORY;
3668 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3669 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3673 switch (info_level) {
3674 case SMB_INFO_ALLOCATION:
3676 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3678 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3680 if (df_ret == (uint64_t)-1) {
3681 return map_nt_error_from_unix(errno);
3684 block_size = lp_block_size(snum);
3685 if (bsize < block_size) {
3686 uint64_t factor = block_size/bsize;
3691 if (bsize > block_size) {
3692 uint64_t factor = bsize/block_size;
3697 sectors_per_unit = bsize/bytes_per_sector;
3699 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3700 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3701 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3704 * For large drives, return max values and not modulo.
3706 dsize = MIN(dsize, UINT32_MAX);
3707 dfree = MIN(dfree, UINT32_MAX);
3709 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3710 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3711 SIVAL(pdata,l1_cUnit,dsize);
3712 SIVAL(pdata,l1_cUnitAvail,dfree);
3713 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3717 case SMB_INFO_VOLUME:
3718 /* Return volume name */
3720 * Add volume serial number - hash of a combination of
3721 * the called hostname and the service name.
3723 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3725 * Win2k3 and previous mess this up by sending a name length
3726 * one byte short. I believe only older clients (OS/2 Win9x) use
3727 * this call so try fixing this by adding a terminating null to
3728 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3730 status = srvstr_push(
3732 pdata+l2_vol_szVolLabel, vname,
3733 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3734 STR_NOALIGN|STR_TERMINATE, &len);
3735 if (!NT_STATUS_IS_OK(status)) {
3738 SCVAL(pdata,l2_vol_cch,len);
3739 data_len = l2_vol_szVolLabel + len;
3740 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3741 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3742 (unsigned)len, vname));
3745 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3746 case SMB_FS_ATTRIBUTE_INFORMATION:
3748 additional_flags = 0;
3749 #if defined(HAVE_SYS_QUOTAS)
3750 additional_flags |= FILE_VOLUME_QUOTAS;
3753 if(lp_nt_acl_support(SNUM(conn))) {
3754 additional_flags |= FILE_PERSISTENT_ACLS;
3757 /* Capabilities are filled in at connection time through STATVFS call */
3758 additional_flags |= conn->fs_capabilities;
3759 additional_flags |= lp_parm_int(conn->params->service,
3760 "share", "fake_fscaps",
3763 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3764 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3765 additional_flags); /* FS ATTRIBUTES */
3767 SIVAL(pdata,4,255); /* Max filename component length */
3768 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3769 and will think we can't do long filenames */
3770 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3771 PTR_DIFF(end_data, pdata+12),
3773 if (!NT_STATUS_IS_OK(status)) {
3777 data_len = 12 + len;
3778 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3779 /* the client only requested a portion of the
3781 data_len = max_data_bytes;
3782 status = STATUS_BUFFER_OVERFLOW;
3784 *fixed_portion = 16;
3787 case SMB_QUERY_FS_LABEL_INFO:
3788 case SMB_FS_LABEL_INFORMATION:
3789 status = srvstr_push(pdata, flags2, pdata+4, vname,
3790 PTR_DIFF(end_data, pdata+4), 0, &len);
3791 if (!NT_STATUS_IS_OK(status)) {
3798 case SMB_QUERY_FS_VOLUME_INFO:
3799 case SMB_FS_VOLUME_INFORMATION:
3802 * Add volume serial number - hash of a combination of
3803 * the called hostname and the service name.
3805 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3806 (str_checksum(get_local_machine_name())<<16));
3808 /* Max label len is 32 characters. */
3809 status = srvstr_push(pdata, flags2, pdata+18, vname,
3810 PTR_DIFF(end_data, pdata+18),
3812 if (!NT_STATUS_IS_OK(status)) {
3815 SIVAL(pdata,12,len);
3818 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3819 (int)strlen(vname),vname,
3820 lp_servicename(talloc_tos(), lp_sub, snum)));
3821 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3822 /* the client only requested a portion of the
3824 data_len = max_data_bytes;
3825 status = STATUS_BUFFER_OVERFLOW;
3827 *fixed_portion = 24;
3830 case SMB_QUERY_FS_SIZE_INFO:
3831 case SMB_FS_SIZE_INFORMATION:
3833 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3835 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3837 if (df_ret == (uint64_t)-1) {
3838 return map_nt_error_from_unix(errno);
3840 block_size = lp_block_size(snum);
3841 if (bsize < block_size) {
3842 uint64_t factor = block_size/bsize;
3847 if (bsize > block_size) {
3848 uint64_t factor = bsize/block_size;
3853 sectors_per_unit = bsize/bytes_per_sector;
3854 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3855 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3856 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3857 SBIG_UINT(pdata,0,dsize);
3858 SBIG_UINT(pdata,8,dfree);
3859 SIVAL(pdata,16,sectors_per_unit);
3860 SIVAL(pdata,20,bytes_per_sector);
3861 *fixed_portion = 24;
3865 case SMB_FS_FULL_SIZE_INFORMATION:
3867 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3869 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3871 if (df_ret == (uint64_t)-1) {
3872 return map_nt_error_from_unix(errno);
3874 block_size = lp_block_size(snum);
3875 if (bsize < block_size) {
3876 uint64_t factor = block_size/bsize;
3881 if (bsize > block_size) {
3882 uint64_t factor = bsize/block_size;
3887 sectors_per_unit = bsize/bytes_per_sector;
3888 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3889 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3890 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3891 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3892 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3893 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3894 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3895 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3896 *fixed_portion = 32;
3900 case SMB_QUERY_FS_DEVICE_INFO:
3901 case SMB_FS_DEVICE_INFORMATION:
3903 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3905 if (!CAN_WRITE(conn)) {
3906 characteristics |= FILE_READ_ONLY_DEVICE;
3909 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3910 SIVAL(pdata,4,characteristics);
3915 #ifdef HAVE_SYS_QUOTAS
3916 case SMB_FS_QUOTA_INFORMATION:
3918 * what we have to send --metze:
3920 * Unknown1: 24 NULL bytes
3921 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3922 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3923 * Quota Flags: 2 byte :
3924 * Unknown3: 6 NULL bytes
3928 * details for Quota Flags:
3930 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3931 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3932 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3933 * 0x0001 Enable Quotas: enable quota for this fs
3937 /* we need to fake up a fsp here,
3938 * because its not send in this call
3941 SMB_NTQUOTA_STRUCT quotas;
3944 ZERO_STRUCT(quotas);
3947 fsp.fnum = FNUM_FIELD_INVALID;
3950 if (get_current_uid(conn) != 0) {
3951 DEBUG(0,("get_user_quota: access_denied "
3952 "service [%s] user [%s]\n",
3953 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3954 conn->session_info->unix_info->unix_name));
3955 return NT_STATUS_ACCESS_DENIED;
3958 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3960 if (!NT_STATUS_IS_OK(status)) {
3961 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3967 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3968 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3970 /* Unknown1 24 NULL bytes*/
3971 SBIG_UINT(pdata,0,(uint64_t)0);
3972 SBIG_UINT(pdata,8,(uint64_t)0);
3973 SBIG_UINT(pdata,16,(uint64_t)0);
3975 /* Default Soft Quota 8 bytes */
3976 SBIG_UINT(pdata,24,quotas.softlim);
3978 /* Default Hard Quota 8 bytes */
3979 SBIG_UINT(pdata,32,quotas.hardlim);
3981 /* Quota flag 2 bytes */
3982 SSVAL(pdata,40,quotas.qflags);
3984 /* Unknown3 6 NULL bytes */
3990 #endif /* HAVE_SYS_QUOTAS */
3991 case SMB_FS_OBJECTID_INFORMATION:
3993 unsigned char objid[16];
3994 struct smb_extended_info extended_info;
3995 memcpy(pdata,create_volume_objectid(conn, objid),16);
3996 samba_extended_info_version (&extended_info);
3997 SIVAL(pdata,16,extended_info.samba_magic);
3998 SIVAL(pdata,20,extended_info.samba_version);
3999 SIVAL(pdata,24,extended_info.samba_subversion);
4000 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
4001 memcpy(pdata+36,extended_info.samba_version_string,28);
4006 case SMB_FS_SECTOR_SIZE_INFORMATION:
4010 * These values match a physical Windows Server 2012
4011 * share backed by NTFS atop spinning rust.
4013 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
4014 /* logical_bytes_per_sector */
4015 SIVAL(pdata, 0, bytes_per_sector);
4016 /* phys_bytes_per_sector_atomic */
4017 SIVAL(pdata, 4, bytes_per_sector);
4018 /* phys_bytes_per_sector_perf */
4019 SIVAL(pdata, 8, bytes_per_sector);
4020 /* fs_effective_phys_bytes_per_sector_atomic */
4021 SIVAL(pdata, 12, bytes_per_sector);
4023 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4024 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4025 /* byte_off_sector_align */
4026 SIVAL(pdata, 20, 0);
4027 /* byte_off_partition_align */
4028 SIVAL(pdata, 24, 0);
4029 *fixed_portion = 28;
4035 * Query the version and capabilities of the CIFS UNIX extensions
4039 case SMB_QUERY_CIFS_UNIX_INFO:
4041 bool large_write = lp_min_receive_file_size() &&
4042 !srv_is_signing_active(xconn);
4043 bool large_read = !srv_is_signing_active(xconn);
4044 int encrypt_caps = 0;
4046 if (!lp_unix_extensions()) {
4047 return NT_STATUS_INVALID_LEVEL;
4050 switch (conn->encrypt_level) {
4051 case SMB_SIGNING_OFF:
4054 case SMB_SIGNING_DESIRED:
4055 case SMB_SIGNING_IF_REQUIRED:
4056 case SMB_SIGNING_DEFAULT:
4057 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4059 case SMB_SIGNING_REQUIRED:
4060 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4061 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4062 large_write = false;
4068 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4069 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4071 /* We have POSIX ACLs, pathname, encryption,
4072 * large read/write, and locking capability. */
4074 SBIG_UINT(pdata,4,((uint64_t)(
4075 CIFS_UNIX_POSIX_ACLS_CAP|
4076 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4077 CIFS_UNIX_FCNTL_LOCKS_CAP|
4078 CIFS_UNIX_EXTATTR_CAP|
4079 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4081 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4083 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4087 case SMB_QUERY_POSIX_FS_INFO:
4090 vfs_statvfs_struct svfs;
4092 if (!lp_unix_extensions()) {
4093 return NT_STATUS_INVALID_LEVEL;
4096 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4100 SIVAL(pdata,0,svfs.OptimalTransferSize);
4101 SIVAL(pdata,4,svfs.BlockSize);
4102 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4103 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4104 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4105 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4106 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4107 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4108 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4110 } else if (rc == EOPNOTSUPP) {
4111 return NT_STATUS_INVALID_LEVEL;
4112 #endif /* EOPNOTSUPP */
4114 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4115 return NT_STATUS_DOS(ERRSRV, ERRerror);
4120 case SMB_QUERY_POSIX_WHOAMI:
4126 if (!lp_unix_extensions()) {
4127 return NT_STATUS_INVALID_LEVEL;
4130 if (max_data_bytes < 40) {
4131 return NT_STATUS_BUFFER_TOO_SMALL;
4134 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4135 flags |= SMB_WHOAMI_GUEST;
4138 /* NOTE: 8 bytes for UID/GID, irrespective of native
4139 * platform size. This matches
4140 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4142 data_len = 4 /* flags */
4149 + 4 /* pad/reserved */
4150 + (conn->session_info->unix_token->ngroups * 8)
4152 + (conn->session_info->security_token->num_sids *
4156 SIVAL(pdata, 0, flags);
4157 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4159 (uint64_t)conn->session_info->unix_token->uid);
4160 SBIG_UINT(pdata, 16,
4161 (uint64_t)conn->session_info->unix_token->gid);
4164 if (data_len >= max_data_bytes) {
4165 /* Potential overflow, skip the GIDs and SIDs. */
4167 SIVAL(pdata, 24, 0); /* num_groups */
4168 SIVAL(pdata, 28, 0); /* num_sids */
4169 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4170 SIVAL(pdata, 36, 0); /* reserved */
4176 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4177 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4179 /* We walk the SID list twice, but this call is fairly
4180 * infrequent, and I don't expect that it's performance
4181 * sensitive -- jpeach
4183 for (i = 0, sid_bytes = 0;
4184 i < conn->session_info->security_token->num_sids; ++i) {
4185 sid_bytes += ndr_size_dom_sid(
4186 &conn->session_info->security_token->sids[i],
4190 /* SID list byte count */
4191 SIVAL(pdata, 32, sid_bytes);
4193 /* 4 bytes pad/reserved - must be zero */
4194 SIVAL(pdata, 36, 0);
4198 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4199 SBIG_UINT(pdata, data_len,
4200 (uint64_t)conn->session_info->unix_token->groups[i]);
4206 i < conn->session_info->security_token->num_sids; ++i) {
4207 int sid_len = ndr_size_dom_sid(
4208 &conn->session_info->security_token->sids[i],
4211 sid_linearize((uint8_t *)(pdata + data_len),
4213 &conn->session_info->security_token->sids[i]);
4214 data_len += sid_len;
4220 case SMB_MAC_QUERY_FS_INFO:
4222 * Thursby MAC extension... ONLY on NTFS filesystems
4223 * once we do streams then we don't need this
4225 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4227 SIVAL(pdata,84,0x100); /* Don't support mac... */
4233 return NT_STATUS_INVALID_LEVEL;
4236 *ret_data_len = data_len;
4240 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4241 struct smb_request *req,
4243 const DATA_BLOB *qdata)
4245 const struct loadparm_substitution *lp_sub =
4246 loadparm_s3_global_substitution();
4248 SMB_NTQUOTA_STRUCT quotas;
4250 ZERO_STRUCT(quotas);
4253 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4254 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4255 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4256 conn->session_info->unix_info->unix_name));
4257 return NT_STATUS_ACCESS_DENIED;
4260 if (!check_fsp_ntquota_handle(conn, req,
4262 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4263 return NT_STATUS_INVALID_HANDLE;
4266 /* note: normally there're 48 bytes,
4267 * but we didn't use the last 6 bytes for now
4270 if (qdata->length < 42) {
4271 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4272 (unsigned int)qdata->length));
4273 return NT_STATUS_INVALID_PARAMETER;
4276 /* unknown_1 24 NULL bytes in pdata*/
4278 /* the soft quotas 8 bytes (uint64_t)*/
4279 quotas.softlim = BVAL(qdata->data,24);
4281 /* the hard quotas 8 bytes (uint64_t)*/
4282 quotas.hardlim = BVAL(qdata->data,32);
4284 /* quota_flags 2 bytes **/
4285 quotas.qflags = SVAL(qdata->data,40);
4287 /* unknown_2 6 NULL bytes follow*/
4289 /* now set the quotas */
4290 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4291 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4292 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4293 status = map_nt_error_from_unix(errno);
4295 status = NT_STATUS_OK;
4300 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4301 struct smb_request *req,
4302 TALLOC_CTX *mem_ctx,
4303 uint16_t info_level,
4305 const DATA_BLOB *pdata)
4307 switch (info_level) {
4308 case SMB_FS_QUOTA_INFORMATION:
4310 return smb_set_fsquota(conn,
4319 return NT_STATUS_INVALID_LEVEL;
4322 /****************************************************************************
4323 Reply to a TRANS2_QFSINFO (query filesystem info).
4324 ****************************************************************************/
4326 static void call_trans2qfsinfo(connection_struct *conn,
4327 struct smb_request *req,
4328 char **pparams, int total_params,
4329 char **ppdata, int total_data,
4330 unsigned int max_data_bytes)
4332 char *params = *pparams;
4333 uint16_t info_level;
4335 size_t fixed_portion;
4338 if (total_params < 2) {
4339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4343 info_level = SVAL(params,0);
4345 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4346 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4347 DEBUG(0,("call_trans2qfsinfo: encryption required "
4348 "and info level 0x%x sent.\n",
4349 (unsigned int)info_level));
4350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4355 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4357 status = smbd_do_qfsinfo(req->xconn, conn, req,
4364 if (!NT_STATUS_IS_OK(status)) {
4365 reply_nterror(req, status);
4369 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4372 DEBUG( 4, ( "%s info_level = %d\n",
4373 smb_fn_name(req->cmd), info_level) );
4378 /****************************************************************************
4379 Reply to a TRANS2_SETFSINFO (set filesystem info).
4380 ****************************************************************************/
4382 static void call_trans2setfsinfo(connection_struct *conn,
4383 struct smb_request *req,
4384 char **pparams, int total_params,
4385 char **ppdata, int total_data,
4386 unsigned int max_data_bytes)
4388 const struct loadparm_substitution *lp_sub =
4389 loadparm_s3_global_substitution();
4390 struct smbXsrv_connection *xconn = req->xconn;
4391 char *pdata = *ppdata;
4392 char *params = *pparams;
4393 uint16_t info_level;
4395 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4396 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4399 if (total_params < 4) {
4400 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 info_level = SVAL(params,2);
4409 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4410 info_level != SMB_SET_CIFS_UNIX_INFO) {
4411 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4412 "info level (0x%x) on IPC$.\n",
4413 (unsigned int)info_level));
4414 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4419 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4420 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4421 DEBUG(0,("call_trans2setfsinfo: encryption required "
4422 "and info level 0x%x sent.\n",
4423 (unsigned int)info_level));
4424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4429 switch(info_level) {
4430 case SMB_SET_CIFS_UNIX_INFO:
4431 if (!lp_unix_extensions()) {
4432 DEBUG(2,("call_trans2setfsinfo: "
4433 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4434 "unix extensions off\n"));
4436 NT_STATUS_INVALID_LEVEL);
4440 /* There should be 12 bytes of capabilities set. */
4441 if (total_data < 12) {
4444 NT_STATUS_INVALID_PARAMETER);
4447 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4448 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4449 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4450 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4451 /* Just print these values for now. */
4452 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4453 "major = %u, minor = %u cap_low = 0x%x, "
4455 (unsigned int)xconn->
4456 smb1.unix_info.client_major,
4457 (unsigned int)xconn->
4458 smb1.unix_info.client_minor,
4459 (unsigned int)xconn->
4460 smb1.unix_info.client_cap_low,
4461 (unsigned int)xconn->
4462 smb1.unix_info.client_cap_high));
4464 /* Here is where we must switch to posix pathname processing... */
4465 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4466 lp_set_posix_pathnames();
4467 mangle_change_to_posix();
4470 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4471 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4472 /* Client that knows how to do posix locks,
4473 * but not posix open/mkdir operations. Set a
4474 * default type for read/write checks. */
4476 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4481 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4484 size_t param_len = 0;
4485 size_t data_len = total_data;
4487 if (!lp_unix_extensions()) {
4490 NT_STATUS_INVALID_LEVEL);
4494 if (lp_server_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4497 NT_STATUS_NOT_SUPPORTED);
4501 if (xconn->smb1.echo_handler.trusted_fde) {
4502 DEBUG( 2,("call_trans2setfsinfo: "
4503 "request transport encryption disabled"
4504 "with 'fork echo handler = yes'\n"));
4507 NT_STATUS_NOT_SUPPORTED);
4511 DEBUG( 4,("call_trans2setfsinfo: "
4512 "request transport encryption.\n"));
4514 status = srv_request_encryption_setup(conn,
4515 (unsigned char **)ppdata,
4517 (unsigned char **)pparams,
4520 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4521 !NT_STATUS_IS_OK(status)) {
4522 reply_nterror(req, status);
4526 send_trans2_replies(conn, req,
4534 if (NT_STATUS_IS_OK(status)) {
4535 /* Server-side transport
4536 * encryption is now *on*. */
4537 status = srv_encryption_start(conn);
4538 if (!NT_STATUS_IS_OK(status)) {
4539 char *reason = talloc_asprintf(talloc_tos(),
4540 "Failure in setting "
4541 "up encrypted transport: %s",
4543 exit_server_cleanly(reason);
4549 case SMB_FS_QUOTA_INFORMATION:
4553 .data = (uint8_t *)pdata,
4554 .length = total_data
4556 files_struct *fsp = NULL;
4557 fsp = file_fsp(req, SVAL(params,0));
4559 status = smb_set_fsquota(conn,
4563 if (!NT_STATUS_IS_OK(status)) {
4564 reply_nterror(req, status);
4570 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4572 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4578 * sending this reply works fine,
4579 * but I'm not sure it's the same
4580 * like windows do...
4583 reply_outbuf(req, 10, 0);
4586 #if defined(HAVE_POSIX_ACLS)
4587 /****************************************************************************
4588 Utility function to count the number of entries in a POSIX acl.
4589 ****************************************************************************/
4591 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4593 unsigned int ace_count = 0;
4594 int entry_id = SMB_ACL_FIRST_ENTRY;
4595 SMB_ACL_ENTRY_T entry;
4597 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4599 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4600 entry_id = SMB_ACL_NEXT_ENTRY;
4607 /****************************************************************************
4608 Utility function to marshall a POSIX acl into wire format.
4609 ****************************************************************************/
4611 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4613 int entry_id = SMB_ACL_FIRST_ENTRY;
4614 SMB_ACL_ENTRY_T entry;
4616 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4617 SMB_ACL_TAG_T tagtype;
4618 SMB_ACL_PERMSET_T permset;
4619 unsigned char perms = 0;
4620 unsigned int own_grp;
4623 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4624 entry_id = SMB_ACL_NEXT_ENTRY;
4627 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4628 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4632 if (sys_acl_get_permset(entry, &permset) == -1) {
4633 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4637 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4638 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4639 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4641 SCVAL(pdata,1,perms);
4644 case SMB_ACL_USER_OBJ:
4645 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4646 own_grp = (unsigned int)pst->st_ex_uid;
4647 SIVAL(pdata,2,own_grp);
4652 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4654 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4657 own_grp = (unsigned int)*puid;
4658 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4659 SIVAL(pdata,2,own_grp);
4663 case SMB_ACL_GROUP_OBJ:
4664 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4665 own_grp = (unsigned int)pst->st_ex_gid;
4666 SIVAL(pdata,2,own_grp);
4671 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4673 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4676 own_grp = (unsigned int)*pgid;
4677 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4678 SIVAL(pdata,2,own_grp);
4683 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4684 SIVAL(pdata,2,0xFFFFFFFF);
4685 SIVAL(pdata,6,0xFFFFFFFF);
4688 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4689 SIVAL(pdata,2,0xFFFFFFFF);
4690 SIVAL(pdata,6,0xFFFFFFFF);
4693 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4696 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4703 /****************************************************************************
4704 Store the FILE_UNIX_BASIC info.
4705 ****************************************************************************/
4707 static char *store_file_unix_basic(connection_struct *conn,
4710 const SMB_STRUCT_STAT *psbuf)
4714 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4715 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4717 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4720 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4723 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4724 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4725 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4728 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4732 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4736 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4739 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4740 devno = psbuf->st_ex_rdev;
4742 devno = psbuf->st_ex_dev;
4745 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4749 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4753 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4756 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4760 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4767 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4768 * the chflags(2) (or equivalent) flags.
4770 * XXX: this really should be behind the VFS interface. To do this, we would
4771 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4772 * Each VFS module could then implement its own mapping as appropriate for the
4773 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4775 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4779 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4783 { UF_IMMUTABLE, EXT_IMMUTABLE },
4787 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4791 { UF_HIDDEN, EXT_HIDDEN },
4794 /* Do not remove. We need to guarantee that this array has at least one
4795 * entry to build on HP-UX.
4801 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4802 uint32_t *smb_fflags, uint32_t *smb_fmask)
4806 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4807 *smb_fmask |= info2_flags_map[i].smb_fflag;
4808 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4809 *smb_fflags |= info2_flags_map[i].smb_fflag;
4814 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4815 const uint32_t smb_fflags,
4816 const uint32_t smb_fmask,
4819 uint32_t max_fmask = 0;
4822 *stat_fflags = psbuf->st_ex_flags;
4824 /* For each flags requested in smb_fmask, check the state of the
4825 * corresponding flag in smb_fflags and set or clear the matching
4829 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4830 max_fmask |= info2_flags_map[i].smb_fflag;
4831 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4832 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4833 *stat_fflags |= info2_flags_map[i].stat_fflag;
4835 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4840 /* If smb_fmask is asking to set any bits that are not supported by
4841 * our flag mappings, we should fail.
4843 if ((smb_fmask & max_fmask) != smb_fmask) {
4851 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4852 * of file flags and birth (create) time.
4854 static char *store_file_unix_basic_info2(connection_struct *conn,
4857 const SMB_STRUCT_STAT *psbuf)
4859 uint32_t file_flags = 0;
4860 uint32_t flags_mask = 0;
4862 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4864 /* Create (birth) time 64 bit */
4865 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4868 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4869 SIVAL(pdata, 0, file_flags); /* flags */
4870 SIVAL(pdata, 4, flags_mask); /* mask */
4876 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4877 const struct stream_struct *streams,
4879 unsigned int max_data_bytes,
4880 unsigned int *data_size)
4883 unsigned int ofs = 0;
4885 if (max_data_bytes < 32) {
4886 return NT_STATUS_INFO_LENGTH_MISMATCH;
4889 for (i = 0; i < num_streams; i++) {
4890 unsigned int next_offset;
4892 smb_ucs2_t *namebuf;
4894 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4895 streams[i].name, &namelen) ||
4898 return NT_STATUS_INVALID_PARAMETER;
4902 * name_buf is now null-terminated, we need to marshall as not
4909 * We cannot overflow ...
4911 if ((ofs + 24 + namelen) > max_data_bytes) {
4912 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4914 TALLOC_FREE(namebuf);
4915 return STATUS_BUFFER_OVERFLOW;
4918 SIVAL(data, ofs+4, namelen);
4919 SOFF_T(data, ofs+8, streams[i].size);
4920 SOFF_T(data, ofs+16, streams[i].alloc_size);
4921 memcpy(data+ofs+24, namebuf, namelen);
4922 TALLOC_FREE(namebuf);
4924 next_offset = ofs + 24 + namelen;
4926 if (i == num_streams-1) {
4927 SIVAL(data, ofs, 0);
4930 unsigned int align = ndr_align_size(next_offset, 8);
4932 if ((next_offset + align) > max_data_bytes) {
4933 DEBUG(10, ("refusing to overflow align "
4934 "reply at stream %u\n",
4936 TALLOC_FREE(namebuf);
4937 return STATUS_BUFFER_OVERFLOW;
4940 memset(data+next_offset, 0, align);
4941 next_offset += align;
4943 SIVAL(data, ofs, next_offset - ofs);
4950 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4954 return NT_STATUS_OK;
4957 #if defined(HAVE_POSIX_ACLS)
4958 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4959 struct smb_request *req,
4961 struct smb_filename *smb_fname,
4963 unsigned int data_size_in,
4964 unsigned int *pdata_size_out)
4966 SMB_ACL_T file_acl = NULL;
4967 SMB_ACL_T def_acl = NULL;
4968 uint16_t num_file_acls = 0;
4969 uint16_t num_def_acls = 0;
4970 unsigned int size_needed = 0;
4973 bool close_fsp = false;
4976 * Ensure we always operate on a file descriptor, not just
4980 uint32_t access_mask = SEC_STD_READ_CONTROL|
4981 FILE_READ_ATTRIBUTES|
4982 FILE_WRITE_ATTRIBUTES;
4984 status = get_posix_fsp(conn,
4990 if (!NT_STATUS_IS_OK(status)) {
4996 SMB_ASSERT(fsp != NULL);
4998 status = refuse_symlink(conn,
5001 if (!NT_STATUS_IS_OK(status)) {
5005 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5008 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5009 DBG_INFO("ACLs not implemented on "
5010 "filesystem containing %s\n",
5012 status = NT_STATUS_NOT_IMPLEMENTED;
5016 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5018 * We can only have default POSIX ACLs on
5021 if (!fsp->fsp_flags.is_directory) {
5022 DBG_INFO("Non-directory open %s\n",
5024 status = NT_STATUS_INVALID_HANDLE;
5027 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5029 SMB_ACL_TYPE_DEFAULT,
5031 def_acl = free_empty_sys_acl(conn, def_acl);
5034 num_file_acls = count_acl_entries(conn, file_acl);
5035 num_def_acls = count_acl_entries(conn, def_acl);
5038 if (num_file_acls + num_def_acls < num_file_acls) {
5039 status = NT_STATUS_INVALID_PARAMETER;
5043 size_needed = num_file_acls + num_def_acls;
5046 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5047 * than UINT_MAX, so check by division.
5049 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5050 status = NT_STATUS_INVALID_PARAMETER;
5054 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5055 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5056 status = NT_STATUS_INVALID_PARAMETER;
5059 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5061 if ( data_size_in < size_needed) {
5062 DBG_INFO("data_size too small (%u) need %u\n",
5065 status = NT_STATUS_BUFFER_TOO_SMALL;
5069 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5070 SSVAL(pdata,2,num_file_acls);
5071 SSVAL(pdata,4,num_def_acls);
5072 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5074 ok = marshall_posix_acl(conn,
5079 status = NT_STATUS_INTERNAL_ERROR;
5082 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5084 ok = marshall_posix_acl(conn,
5089 status = NT_STATUS_INTERNAL_ERROR;
5093 *pdata_size_out = size_needed;
5094 status = NT_STATUS_OK;
5100 * Ensure the stat struct in smb_fname is up to
5101 * date. Structure copy.
5103 smb_fname->st = fsp->fsp_name->st;
5104 (void)close_file(req, fsp, NORMAL_CLOSE);
5108 TALLOC_FREE(file_acl);
5109 TALLOC_FREE(def_acl);
5114 /****************************************************************************
5115 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5116 ****************************************************************************/
5118 static void call_trans2qpipeinfo(connection_struct *conn,
5119 struct smb_request *req,
5120 unsigned int tran_call,
5121 char **pparams, int total_params,
5122 char **ppdata, int total_data,
5123 unsigned int max_data_bytes)
5125 char *params = *pparams;
5126 char *pdata = *ppdata;
5127 unsigned int data_size = 0;
5128 unsigned int param_size = 2;
5129 uint16_t info_level;
5133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5137 if (total_params < 4) {
5138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5142 fsp = file_fsp(req, SVAL(params,0));
5143 if (!fsp_is_np(fsp)) {
5144 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5148 info_level = SVAL(params,2);
5150 *pparams = (char *)SMB_REALLOC(*pparams,2);
5151 if (*pparams == NULL) {
5152 reply_nterror(req, NT_STATUS_NO_MEMORY);
5157 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5161 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5162 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5163 if (*ppdata == NULL ) {
5164 reply_nterror(req, NT_STATUS_NO_MEMORY);
5169 switch (info_level) {
5170 case SMB_FILE_STANDARD_INFORMATION:
5172 SOFF_T(pdata,0,4096LL);
5179 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5183 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5189 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5190 TALLOC_CTX *mem_ctx,
5191 struct smb_request *req,
5192 uint16_t info_level,
5194 struct smb_filename *smb_fname,
5195 bool delete_pending,
5196 struct timespec write_time_ts,
5197 struct ea_list *ea_list,
5198 int lock_data_count,
5201 unsigned int max_data_bytes,
5202 size_t *fixed_portion,
5204 unsigned int *pdata_size)
5206 char *pdata = *ppdata;
5207 char *dstart, *dend;
5208 unsigned int data_size;
5209 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5210 time_t create_time, mtime, atime, c_time;
5211 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5218 uint64_t file_size = 0;
5220 uint64_t allocation_size = 0;
5221 uint64_t file_id = 0;
5222 uint32_t access_mask = 0;
5225 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5226 return NT_STATUS_INVALID_LEVEL;
5229 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5230 smb_fname_str_dbg(smb_fname),
5232 info_level, max_data_bytes));
5234 mode = dos_mode(conn, smb_fname);
5235 nlink = psbuf->st_ex_nlink;
5237 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5241 if ((nlink > 0) && delete_pending) {
5245 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5246 return NT_STATUS_INVALID_PARAMETER;
5249 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5250 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5251 if (*ppdata == NULL) {
5252 return NT_STATUS_NO_MEMORY;
5256 dend = dstart + data_size - 1;
5258 if (!is_omit_timespec(&write_time_ts) &&
5259 !INFO_LEVEL_IS_UNIX(info_level))
5261 update_stat_ex_mtime(psbuf, write_time_ts);
5264 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5265 mtime_ts = psbuf->st_ex_mtime;
5266 atime_ts = psbuf->st_ex_atime;
5267 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5269 if (lp_dos_filetime_resolution(SNUM(conn))) {
5270 dos_filetime_timespec(&create_time_ts);
5271 dos_filetime_timespec(&mtime_ts);
5272 dos_filetime_timespec(&atime_ts);
5273 dos_filetime_timespec(&ctime_ts);
5276 create_time = convert_timespec_to_time_t(create_time_ts);
5277 mtime = convert_timespec_to_time_t(mtime_ts);
5278 atime = convert_timespec_to_time_t(atime_ts);
5279 c_time = convert_timespec_to_time_t(ctime_ts);
5281 p = strrchr_m(smb_fname->base_name,'/');
5283 base_name = smb_fname->base_name;
5287 /* NT expects the name to be in an exact form of the *full*
5288 filename. See the trans2 torture test */
5289 if (ISDOT(base_name)) {
5290 dos_fname = talloc_strdup(mem_ctx, "\\");
5292 return NT_STATUS_NO_MEMORY;
5295 dos_fname = talloc_asprintf(mem_ctx,
5297 smb_fname->base_name);
5299 return NT_STATUS_NO_MEMORY;
5301 if (is_ntfs_stream_smb_fname(smb_fname)) {
5302 dos_fname = talloc_asprintf(dos_fname, "%s",
5303 smb_fname->stream_name);
5305 return NT_STATUS_NO_MEMORY;
5309 string_replace(dos_fname, '/', '\\');
5312 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5315 /* Do we have this path open ? */
5317 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5318 fsp1 = file_find_di_first(conn->sconn, fileid);
5319 if (fsp1 && fsp1->initial_allocation_size) {
5320 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5324 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5325 file_size = get_file_size_stat(psbuf);
5329 pos = fsp->fh->position_information;
5333 access_mask = fsp->access_mask;
5335 /* GENERIC_EXECUTE mapping from Windows */
5336 access_mask = 0x12019F;
5339 /* This should be an index number - looks like
5342 I think this causes us to fail the IFSKIT
5343 BasicFileInformationTest. -tpot */
5344 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5348 switch (info_level) {
5349 case SMB_INFO_STANDARD:
5350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5352 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5353 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5354 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5355 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5356 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5357 SSVAL(pdata,l1_attrFile,mode);
5360 case SMB_INFO_QUERY_EA_SIZE:
5362 unsigned int ea_size =
5363 estimate_ea_size(conn, fsp,
5365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5367 srv_put_dos_date2(pdata,0,create_time);
5368 srv_put_dos_date2(pdata,4,atime);
5369 srv_put_dos_date2(pdata,8,mtime); /* write time */
5370 SIVAL(pdata,12,(uint32_t)file_size);
5371 SIVAL(pdata,16,(uint32_t)allocation_size);
5372 SSVAL(pdata,20,mode);
5373 SIVAL(pdata,22,ea_size);
5377 case SMB_INFO_IS_NAME_VALID:
5378 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5380 /* os/2 needs this ? really ?*/
5381 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5383 /* This is only reached for qpathinfo */
5387 case SMB_INFO_QUERY_EAS_FROM_LIST:
5389 size_t total_ea_len = 0;
5390 struct ea_list *ea_file_list = NULL;
5391 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5394 get_ea_list_from_file(mem_ctx, conn, fsp,
5396 &total_ea_len, &ea_file_list);
5397 if (!NT_STATUS_IS_OK(status)) {
5401 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5403 if (!ea_list || (total_ea_len > data_size)) {
5405 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5409 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5413 case SMB_INFO_QUERY_ALL_EAS:
5415 /* We have data_size bytes to put EA's into. */
5416 size_t total_ea_len = 0;
5417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5419 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5421 &total_ea_len, &ea_list);
5422 if (!NT_STATUS_IS_OK(status)) {
5426 if (!ea_list || (total_ea_len > data_size)) {
5428 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5432 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5436 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5438 /* This is FileFullEaInformation - 0xF which maps to
5439 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5441 /* We have data_size bytes to put EA's into. */
5442 size_t total_ea_len = 0;
5443 struct ea_list *ea_file_list = NULL;
5445 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5447 /*TODO: add filtering and index handling */
5450 get_ea_list_from_file(mem_ctx, conn, fsp,
5452 &total_ea_len, &ea_file_list);
5453 if (!NT_STATUS_IS_OK(status)) {
5456 if (!ea_file_list) {
5457 return NT_STATUS_NO_EAS_ON_FILE;
5460 status = fill_ea_chained_buffer(mem_ctx,
5464 conn, ea_file_list);
5465 if (!NT_STATUS_IS_OK(status)) {
5471 case SMB_FILE_BASIC_INFORMATION:
5472 case SMB_QUERY_FILE_BASIC_INFO:
5474 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5476 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5482 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5483 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5484 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5485 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5486 SIVAL(pdata,32,mode);
5488 DEBUG(5,("SMB_QFBI - "));
5489 DEBUG(5,("create: %s ", ctime(&create_time)));
5490 DEBUG(5,("access: %s ", ctime(&atime)));
5491 DEBUG(5,("write: %s ", ctime(&mtime)));
5492 DEBUG(5,("change: %s ", ctime(&c_time)));
5493 DEBUG(5,("mode: %x\n", mode));
5494 *fixed_portion = data_size;
5497 case SMB_FILE_STANDARD_INFORMATION:
5498 case SMB_QUERY_FILE_STANDARD_INFO:
5500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5502 SOFF_T(pdata,0,allocation_size);
5503 SOFF_T(pdata,8,file_size);
5504 SIVAL(pdata,16,nlink);
5505 SCVAL(pdata,20,delete_pending?1:0);
5506 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5507 SSVAL(pdata,22,0); /* Padding. */
5508 *fixed_portion = 24;
5511 case SMB_FILE_EA_INFORMATION:
5512 case SMB_QUERY_FILE_EA_INFO:
5514 unsigned int ea_size =
5515 estimate_ea_size(conn, fsp, smb_fname);
5516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5519 SIVAL(pdata,0,ea_size);
5523 /* Get the 8.3 name - used if NT SMB was negotiated. */
5524 case SMB_QUERY_FILE_ALT_NAME_INFO:
5525 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5527 char mangled_name[13];
5528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5529 if (!name_to_8_3(base_name,mangled_name,
5530 True,conn->params)) {
5531 return NT_STATUS_NO_MEMORY;
5533 status = srvstr_push(dstart, flags2,
5534 pdata+4, mangled_name,
5535 PTR_DIFF(dend, pdata+4),
5537 if (!NT_STATUS_IS_OK(status)) {
5540 data_size = 4 + len;
5546 case SMB_QUERY_FILE_NAME_INFO:
5549 this must be *exactly* right for ACLs on mapped drives to work
5551 status = srvstr_push(dstart, flags2,
5553 PTR_DIFF(dend, pdata+4),
5555 if (!NT_STATUS_IS_OK(status)) {
5558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5559 data_size = 4 + len;
5564 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5566 char *nfname = NULL;
5568 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5569 return NT_STATUS_INVALID_LEVEL;
5572 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5573 if (nfname == NULL) {
5574 return NT_STATUS_NO_MEMORY;
5577 if (ISDOT(nfname)) {
5580 string_replace(nfname, '/', '\\');
5582 if (smb_fname->stream_name != NULL) {
5583 const char *s = smb_fname->stream_name;
5584 const char *e = NULL;
5587 SMB_ASSERT(s[0] != '\0');
5590 * smb_fname->stream_name is in form
5591 * of ':StrEam:$DATA', but we should only
5592 * append ':StrEam' here.
5595 e = strchr(&s[1], ':');
5601 nfname = talloc_strndup_append(nfname, s, n);
5602 if (nfname == NULL) {
5603 return NT_STATUS_NO_MEMORY;
5607 status = srvstr_push(dstart, flags2,
5609 PTR_DIFF(dend, pdata+4),
5611 if (!NT_STATUS_IS_OK(status)) {
5614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5615 data_size = 4 + len;
5621 case SMB_FILE_ALLOCATION_INFORMATION:
5622 case SMB_QUERY_FILE_ALLOCATION_INFO:
5623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5625 SOFF_T(pdata,0,allocation_size);
5628 case SMB_FILE_END_OF_FILE_INFORMATION:
5629 case SMB_QUERY_FILE_END_OF_FILEINFO:
5630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5632 SOFF_T(pdata,0,file_size);
5635 case SMB_QUERY_FILE_ALL_INFO:
5636 case SMB_FILE_ALL_INFORMATION:
5638 unsigned int ea_size =
5639 estimate_ea_size(conn, fsp, smb_fname);
5640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5641 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5642 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5643 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5644 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5645 SIVAL(pdata,32,mode);
5646 SIVAL(pdata,36,0); /* padding. */
5648 SOFF_T(pdata,0,allocation_size);
5649 SOFF_T(pdata,8,file_size);
5650 SIVAL(pdata,16,nlink);
5651 SCVAL(pdata,20,delete_pending);
5652 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5655 SIVAL(pdata,0,ea_size);
5656 pdata += 4; /* EA info */
5657 status = srvstr_push(dstart, flags2,
5659 PTR_DIFF(dend, pdata+4),
5661 if (!NT_STATUS_IS_OK(status)) {
5666 data_size = PTR_DIFF(pdata,(*ppdata));
5667 *fixed_portion = 10;
5671 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5673 unsigned int ea_size =
5674 estimate_ea_size(conn, fsp, smb_fname);
5675 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5676 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5677 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5678 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5679 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5680 SIVAL(pdata, 0x20, mode);
5681 SIVAL(pdata, 0x24, 0); /* padding. */
5682 SBVAL(pdata, 0x28, allocation_size);
5683 SBVAL(pdata, 0x30, file_size);
5684 SIVAL(pdata, 0x38, nlink);
5685 SCVAL(pdata, 0x3C, delete_pending);
5686 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5687 SSVAL(pdata, 0x3E, 0); /* padding */
5688 SBVAL(pdata, 0x40, file_id);
5689 SIVAL(pdata, 0x48, ea_size);
5690 SIVAL(pdata, 0x4C, access_mask);
5691 SBVAL(pdata, 0x50, pos);
5692 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5693 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5697 status = srvstr_push(dstart, flags2,
5699 PTR_DIFF(dend, pdata+4),
5701 if (!NT_STATUS_IS_OK(status)) {
5706 data_size = PTR_DIFF(pdata,(*ppdata));
5707 *fixed_portion = 104;
5710 case SMB_FILE_INTERNAL_INFORMATION:
5712 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5713 SBVAL(pdata, 0, file_id);
5718 case SMB_FILE_ACCESS_INFORMATION:
5719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5720 SIVAL(pdata, 0, access_mask);
5725 case SMB_FILE_NAME_INFORMATION:
5726 /* Pathname with leading '\'. */
5729 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5731 SIVAL(pdata,0,byte_len);
5732 data_size = 4 + byte_len;
5736 case SMB_FILE_DISPOSITION_INFORMATION:
5737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5739 SCVAL(pdata,0,delete_pending);
5743 case SMB_FILE_POSITION_INFORMATION:
5744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5746 SOFF_T(pdata,0,pos);
5750 case SMB_FILE_MODE_INFORMATION:
5751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5752 SIVAL(pdata,0,mode);
5757 case SMB_FILE_ALIGNMENT_INFORMATION:
5758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5759 SIVAL(pdata,0,0); /* No alignment needed. */
5765 * NT4 server just returns "invalid query" to this - if we try
5766 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5769 /* The first statement above is false - verified using Thursby
5770 * client against NT4 -- gcolley.
5772 case SMB_QUERY_FILE_STREAM_INFO:
5773 case SMB_FILE_STREAM_INFORMATION: {
5774 unsigned int num_streams = 0;
5775 struct stream_struct *streams = NULL;
5777 DEBUG(10,("smbd_do_qfilepathinfo: "
5778 "SMB_FILE_STREAM_INFORMATION\n"));
5780 if (is_ntfs_stream_smb_fname(smb_fname)) {
5781 return NT_STATUS_INVALID_PARAMETER;
5784 status = vfs_streaminfo(conn,
5791 if (!NT_STATUS_IS_OK(status)) {
5792 DEBUG(10, ("could not get stream info: %s\n",
5793 nt_errstr(status)));
5797 status = marshall_stream_info(num_streams, streams,
5798 pdata, max_data_bytes,
5801 if (!NT_STATUS_IS_OK(status)) {
5802 DEBUG(10, ("marshall_stream_info failed: %s\n",
5803 nt_errstr(status)));
5804 TALLOC_FREE(streams);
5808 TALLOC_FREE(streams);
5810 *fixed_portion = 32;
5814 case SMB_QUERY_COMPRESSION_INFO:
5815 case SMB_FILE_COMPRESSION_INFORMATION:
5816 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5817 SOFF_T(pdata,0,file_size);
5818 SIVAL(pdata,8,0); /* ??? */
5819 SIVAL(pdata,12,0); /* ??? */
5821 *fixed_portion = 16;
5824 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5826 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5827 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5828 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5829 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5830 SOFF_T(pdata,32,allocation_size);
5831 SOFF_T(pdata,40,file_size);
5832 SIVAL(pdata,48,mode);
5833 SIVAL(pdata,52,0); /* ??? */
5835 *fixed_portion = 56;
5838 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5839 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5840 SIVAL(pdata,0,mode);
5847 * CIFS UNIX Extensions.
5850 case SMB_QUERY_FILE_UNIX_BASIC:
5852 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5853 data_size = PTR_DIFF(pdata,(*ppdata));
5855 DEBUG(4,("smbd_do_qfilepathinfo: "
5856 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5857 dump_data(4, (uint8_t *)(*ppdata), data_size);
5861 case SMB_QUERY_FILE_UNIX_INFO2:
5863 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5864 data_size = PTR_DIFF(pdata,(*ppdata));
5868 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5870 for (i=0; i<100; i++)
5871 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5877 case SMB_QUERY_FILE_UNIX_LINK:
5880 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5883 return NT_STATUS_NO_MEMORY;
5886 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5888 if(!S_ISLNK(psbuf->st_ex_mode)) {
5889 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5892 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5894 link_len = SMB_VFS_READLINKAT(conn,
5900 if (link_len == -1) {
5901 return map_nt_error_from_unix(errno);
5903 buffer[link_len] = 0;
5904 status = srvstr_push(dstart, flags2,
5906 PTR_DIFF(dend, pdata),
5907 STR_TERMINATE, &len);
5908 if (!NT_STATUS_IS_OK(status)) {
5912 data_size = PTR_DIFF(pdata,(*ppdata));
5917 #if defined(HAVE_POSIX_ACLS)
5918 case SMB_QUERY_POSIX_ACL:
5920 status = smb_query_posix_acl(conn,
5927 if (!NT_STATUS_IS_OK(status)) {
5935 case SMB_QUERY_POSIX_LOCK:
5940 enum brl_type lock_type;
5942 /* We need an open file with a real fd for this. */
5943 if (!fsp || fsp->fh->fd == -1) {
5944 return NT_STATUS_INVALID_LEVEL;
5947 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5948 return NT_STATUS_INVALID_PARAMETER;
5951 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5952 case POSIX_LOCK_TYPE_READ:
5953 lock_type = READ_LOCK;
5955 case POSIX_LOCK_TYPE_WRITE:
5956 lock_type = WRITE_LOCK;
5958 case POSIX_LOCK_TYPE_UNLOCK:
5960 /* There's no point in asking for an unlock... */
5961 return NT_STATUS_INVALID_PARAMETER;
5964 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5965 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5966 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5968 status = query_lock(fsp,
5975 if (ERROR_WAS_LOCK_DENIED(status)) {
5976 /* Here we need to report who has it locked... */
5977 data_size = POSIX_LOCK_DATA_SIZE;
5979 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5980 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5981 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5982 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5983 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5985 } else if (NT_STATUS_IS_OK(status)) {
5986 /* For success we just return a copy of what we sent
5987 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5988 data_size = POSIX_LOCK_DATA_SIZE;
5989 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5990 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5998 return NT_STATUS_INVALID_LEVEL;
6001 *pdata_size = data_size;
6002 return NT_STATUS_OK;
6005 /****************************************************************************
6006 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6007 file name or file id).
6008 ****************************************************************************/
6010 static void call_trans2qfilepathinfo(connection_struct *conn,
6011 struct smb_request *req,
6012 unsigned int tran_call,
6013 char **pparams, int total_params,
6014 char **ppdata, int total_data,
6015 unsigned int max_data_bytes)
6017 char *params = *pparams;
6018 char *pdata = *ppdata;
6019 uint16_t info_level;
6020 unsigned int data_size = 0;
6021 unsigned int param_size = 2;
6022 struct smb_filename *smb_fname = NULL;
6023 bool delete_pending = False;
6024 struct timespec write_time_ts;
6025 files_struct *fsp = NULL;
6026 struct file_id fileid;
6027 struct ea_list *ea_list = NULL;
6028 int lock_data_count = 0;
6029 char *lock_data = NULL;
6030 size_t fixed_portion;
6031 NTSTATUS status = NT_STATUS_OK;
6034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6038 ZERO_STRUCT(write_time_ts);
6040 if (tran_call == TRANSACT2_QFILEINFO) {
6041 if (total_params < 4) {
6042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6047 call_trans2qpipeinfo(conn, req, tran_call,
6048 pparams, total_params,
6054 fsp = file_fsp(req, SVAL(params,0));
6055 info_level = SVAL(params,2);
6057 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6059 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6060 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6064 /* Initial check for valid fsp ptr. */
6065 if (!check_fsp_open(conn, req, fsp)) {
6069 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6070 if (smb_fname == NULL) {
6071 reply_nterror(req, NT_STATUS_NO_MEMORY);
6075 if(fsp->fake_file_handle) {
6077 * This is actually for the QUOTA_FAKE_FILE --metze
6080 /* We know this name is ok, it's already passed the checks. */
6082 } else if(fsp->fh->fd == -1) {
6084 * This is actually a QFILEINFO on a directory
6085 * handle (returned from an NT SMB). NT5.0 seems
6086 * to do this call. JRA.
6089 if (INFO_LEVEL_IS_UNIX(info_level)) {
6090 /* Always do lstat for UNIX calls. */
6091 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6092 DEBUG(3,("call_trans2qfilepathinfo: "
6093 "SMB_VFS_LSTAT of %s failed "
6095 smb_fname_str_dbg(smb_fname),
6098 map_nt_error_from_unix(errno));
6101 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6102 DEBUG(3,("call_trans2qfilepathinfo: "
6103 "SMB_VFS_STAT of %s failed (%s)\n",
6104 smb_fname_str_dbg(smb_fname),
6107 map_nt_error_from_unix(errno));
6111 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6112 fileid = vfs_file_id_from_sbuf(
6113 conn, &smb_fname->st);
6114 get_file_infos(fileid, fsp->name_hash,
6120 * Original code - this is an open file.
6122 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6123 DEBUG(3, ("fstat of %s failed (%s)\n",
6124 fsp_fnum_dbg(fsp), strerror(errno)));
6126 map_nt_error_from_unix(errno));
6129 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6130 fileid = vfs_file_id_from_sbuf(
6131 conn, &smb_fname->st);
6132 get_file_infos(fileid, fsp->name_hash,
6141 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6144 if (total_params < 7) {
6145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6149 info_level = SVAL(params,0);
6151 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6153 if (INFO_LEVEL_IS_UNIX(info_level)) {
6154 if (!lp_unix_extensions()) {
6155 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6158 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6159 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6160 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6161 req->posix_pathnames) {
6162 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6166 if (req->posix_pathnames) {
6167 srvstr_get_path_posix(req,
6176 srvstr_get_path(req,
6185 if (!NT_STATUS_IS_OK(status)) {
6186 reply_nterror(req, status);
6190 status = filename_convert(req,
6197 if (!NT_STATUS_IS_OK(status)) {
6198 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6199 reply_botherror(req,
6200 NT_STATUS_PATH_NOT_COVERED,
6201 ERRSRV, ERRbadpath);
6204 reply_nterror(req, status);
6208 /* If this is a stream, check if there is a delete_pending. */
6209 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6210 && is_ntfs_stream_smb_fname(smb_fname)) {
6211 struct smb_filename *smb_fname_base;
6213 /* Create an smb_filename with stream_name == NULL. */
6214 smb_fname_base = synthetic_smb_fname(
6216 smb_fname->base_name,
6221 if (smb_fname_base == NULL) {
6222 reply_nterror(req, NT_STATUS_NO_MEMORY);
6226 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6227 /* Always do lstat for UNIX calls. */
6228 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6229 DEBUG(3,("call_trans2qfilepathinfo: "
6230 "SMB_VFS_LSTAT of %s failed "
6232 smb_fname_str_dbg(smb_fname_base),
6234 TALLOC_FREE(smb_fname_base);
6236 map_nt_error_from_unix(errno));
6240 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6241 DEBUG(3,("call_trans2qfilepathinfo: "
6242 "fileinfo of %s failed "
6244 smb_fname_str_dbg(smb_fname_base),
6246 TALLOC_FREE(smb_fname_base);
6248 map_nt_error_from_unix(errno));
6253 status = file_name_hash(conn,
6254 smb_fname_str_dbg(smb_fname_base),
6256 if (!NT_STATUS_IS_OK(status)) {
6257 TALLOC_FREE(smb_fname_base);
6258 reply_nterror(req, status);
6262 fileid = vfs_file_id_from_sbuf(conn,
6263 &smb_fname_base->st);
6264 TALLOC_FREE(smb_fname_base);
6265 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6266 if (delete_pending) {
6267 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6272 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6273 /* Always do lstat for UNIX calls. */
6274 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6275 DEBUG(3,("call_trans2qfilepathinfo: "
6276 "SMB_VFS_LSTAT of %s failed (%s)\n",
6277 smb_fname_str_dbg(smb_fname),
6280 map_nt_error_from_unix(errno));
6285 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6286 DEBUG(3,("call_trans2qfilepathinfo: "
6287 "SMB_VFS_STAT of %s failed (%s)\n",
6288 smb_fname_str_dbg(smb_fname),
6291 map_nt_error_from_unix(errno));
6296 status = file_name_hash(conn,
6297 smb_fname_str_dbg(smb_fname),
6299 if (!NT_STATUS_IS_OK(status)) {
6300 reply_nterror(req, status);
6304 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6305 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6306 get_file_infos(fileid, name_hash, &delete_pending,
6310 if (delete_pending) {
6311 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6316 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6317 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6319 info_level,tran_call,total_data));
6321 /* Pull out any data sent here before we realloc. */
6322 switch (info_level) {
6323 case SMB_INFO_QUERY_EAS_FROM_LIST:
6325 /* Pull any EA list from the data portion. */
6328 if (total_data < 4) {
6330 req, NT_STATUS_INVALID_PARAMETER);
6333 ea_size = IVAL(pdata,0);
6335 if (total_data > 0 && ea_size != total_data) {
6336 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6339 req, NT_STATUS_INVALID_PARAMETER);
6343 if (!lp_ea_support(SNUM(conn))) {
6344 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6348 /* Pull out the list of names. */
6349 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6352 req, NT_STATUS_INVALID_PARAMETER);
6358 case SMB_QUERY_POSIX_LOCK:
6360 if (fsp == NULL || fsp->fh->fd == -1) {
6361 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6365 if (total_data != POSIX_LOCK_DATA_SIZE) {
6367 req, NT_STATUS_INVALID_PARAMETER);
6371 /* Copy the lock range data. */
6372 lock_data = (char *)talloc_memdup(
6373 req, pdata, total_data);
6375 reply_nterror(req, NT_STATUS_NO_MEMORY);
6378 lock_data_count = total_data;
6384 *pparams = (char *)SMB_REALLOC(*pparams,2);
6385 if (*pparams == NULL) {
6386 reply_nterror(req, NT_STATUS_NO_MEMORY);
6393 * draft-leach-cifs-v1-spec-02.txt
6394 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6397 * The requested information is placed in the Data portion of the
6398 * transaction response. For the information levels greater than 0x100,
6399 * the transaction response has 1 parameter word which should be
6400 * ignored by the client.
6402 * However Windows only follows this rule for the IS_NAME_VALID call.
6404 switch (info_level) {
6405 case SMB_INFO_IS_NAME_VALID:
6410 if ((info_level & 0xFF00) == 0xFF00) {
6412 * We use levels that start with 0xFF00
6413 * internally to represent SMB2 specific levels
6415 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6419 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6421 delete_pending, write_time_ts,
6423 lock_data_count, lock_data,
6424 req->flags2, max_data_bytes,
6426 ppdata, &data_size);
6427 if (!NT_STATUS_IS_OK(status)) {
6428 if (open_was_deferred(req->xconn, req->mid)) {
6429 /* We have re-scheduled this call. */
6432 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6433 bool ok = defer_smb1_sharing_violation(req);
6438 reply_nterror(req, status);
6441 if (fixed_portion > max_data_bytes) {
6442 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6446 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6452 /****************************************************************************
6453 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6455 ****************************************************************************/
6457 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6458 connection_struct *conn,
6459 struct smb_request *req,
6460 bool overwrite_if_exists,
6461 const struct smb_filename *smb_fname_old,
6462 struct smb_filename *smb_fname_new)
6464 NTSTATUS status = NT_STATUS_OK;
6468 /* source must already exist. */
6469 if (!VALID_STAT(smb_fname_old->st)) {
6470 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6473 if (VALID_STAT(smb_fname_new->st)) {
6474 if (overwrite_if_exists) {
6475 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6476 return NT_STATUS_FILE_IS_A_DIRECTORY;
6478 status = unlink_internals(conn,
6480 FILE_ATTRIBUTE_NORMAL,
6483 if (!NT_STATUS_IS_OK(status)) {
6487 /* Disallow if newname already exists. */
6488 return NT_STATUS_OBJECT_NAME_COLLISION;
6492 /* No links from a directory. */
6493 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6494 return NT_STATUS_FILE_IS_A_DIRECTORY;
6497 /* Setting a hardlink to/from a stream isn't currently supported. */
6498 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6500 DBG_DEBUG("Old name has streams\n");
6501 return NT_STATUS_INVALID_PARAMETER;
6503 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6505 DBG_DEBUG("New name has streams\n");
6506 return NT_STATUS_INVALID_PARAMETER;
6509 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6510 smb_fname_old->base_name, smb_fname_new->base_name));
6512 ret = SMB_VFS_LINKAT(conn,
6520 status = map_nt_error_from_unix(errno);
6521 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6522 nt_errstr(status), smb_fname_old->base_name,
6523 smb_fname_new->base_name));
6528 /****************************************************************************
6529 Deal with setting the time from any of the setfilepathinfo functions.
6530 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6531 calling this function.
6532 ****************************************************************************/
6534 NTSTATUS smb_set_file_time(connection_struct *conn,
6536 const struct smb_filename *smb_fname,
6537 struct smb_file_time *ft,
6538 bool setting_write_time)
6540 struct smb_filename smb_fname_base;
6541 struct timeval_buf tbuf[4];
6543 FILE_NOTIFY_CHANGE_LAST_ACCESS
6544 |FILE_NOTIFY_CHANGE_LAST_WRITE
6545 |FILE_NOTIFY_CHANGE_CREATION;
6547 if (!VALID_STAT(smb_fname->st)) {
6548 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6551 /* get some defaults (no modifications) if any info is zero or -1. */
6552 if (is_omit_timespec(&ft->create_time)) {
6553 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6556 if (is_omit_timespec(&ft->atime)) {
6557 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6560 if (is_omit_timespec(&ft->mtime)) {
6561 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6564 if (!setting_write_time) {
6565 /* ft->mtime comes from change time, not write time. */
6566 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6569 /* Ensure the resolution is the correct for
6570 * what we can store on this filesystem. */
6572 round_timespec(conn->ts_res, &ft->create_time);
6573 round_timespec(conn->ts_res, &ft->ctime);
6574 round_timespec(conn->ts_res, &ft->atime);
6575 round_timespec(conn->ts_res, &ft->mtime);
6577 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6578 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6579 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6580 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6581 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6582 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6583 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6584 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6586 if (setting_write_time) {
6588 * This was a Windows setfileinfo on an open file.
6589 * NT does this a lot. We also need to
6590 * set the time here, as it can be read by
6591 * FindFirst/FindNext and with the patch for bug #2045
6592 * in smbd/fileio.c it ensures that this timestamp is
6593 * kept sticky even after a write. We save the request
6594 * away and will set it on file close and after a write. JRA.
6597 DBG_DEBUG("setting pending modtime to %s\n",
6598 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6601 if (fsp->base_fsp) {
6602 set_sticky_write_time_fsp(fsp->base_fsp,
6605 set_sticky_write_time_fsp(fsp, ft->mtime);
6608 set_sticky_write_time_path(
6609 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6614 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6616 /* Always call ntimes on the base, even if a stream was passed in. */
6617 smb_fname_base = *smb_fname;
6618 smb_fname_base.stream_name = NULL;
6620 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6621 return map_nt_error_from_unix(errno);
6624 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6625 smb_fname->base_name);
6626 return NT_STATUS_OK;
6629 /****************************************************************************
6630 Deal with setting the dosmode from any of the setfilepathinfo functions.
6631 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6632 done before calling this function.
6633 ****************************************************************************/
6635 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6636 const struct smb_filename *smb_fname,
6639 struct smb_filename *smb_fname_base;
6642 if (!VALID_STAT(smb_fname->st)) {
6643 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6646 /* Always operate on the base_name, even if a stream was passed in. */
6647 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6648 smb_fname->base_name,
6653 if (smb_fname_base == NULL) {
6654 return NT_STATUS_NO_MEMORY;
6658 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6659 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6661 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6665 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6667 /* check the mode isn't different, before changing it */
6668 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6669 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6670 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6671 (unsigned int)dosmode));
6673 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6675 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6677 smb_fname_str_dbg(smb_fname_base),
6679 status = map_nt_error_from_unix(errno);
6683 status = NT_STATUS_OK;
6685 TALLOC_FREE(smb_fname_base);
6689 /****************************************************************************
6690 Deal with setting the size from any of the setfilepathinfo functions.
6691 ****************************************************************************/
6693 static NTSTATUS smb_set_file_size(connection_struct *conn,
6694 struct smb_request *req,
6696 const struct smb_filename *smb_fname,
6697 const SMB_STRUCT_STAT *psbuf,
6699 bool fail_after_createfile)
6701 NTSTATUS status = NT_STATUS_OK;
6702 struct smb_filename *smb_fname_tmp = NULL;
6703 files_struct *new_fsp = NULL;
6705 if (!VALID_STAT(*psbuf)) {
6706 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6709 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6711 get_file_size_stat(psbuf));
6713 if (size == get_file_size_stat(psbuf)) {
6715 return NT_STATUS_OK;
6717 if (!fsp->fsp_flags.modified) {
6718 return NT_STATUS_OK;
6720 trigger_write_time_update_immediate(fsp);
6721 return NT_STATUS_OK;
6724 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6725 smb_fname_str_dbg(smb_fname), (double)size));
6727 if (fsp && fsp->fh->fd != -1) {
6728 /* Handle based call. */
6729 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6730 return NT_STATUS_ACCESS_DENIED;
6733 if (vfs_set_filelen(fsp, size) == -1) {
6734 return map_nt_error_from_unix(errno);
6736 trigger_write_time_update_immediate(fsp);
6737 return NT_STATUS_OK;
6740 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6741 if (smb_fname_tmp == NULL) {
6742 return NT_STATUS_NO_MEMORY;
6745 smb_fname_tmp->st = *psbuf;
6747 status = SMB_VFS_CREATE_FILE(
6750 &conn->cwd_fsp, /* dirfsp */
6751 smb_fname_tmp, /* fname */
6752 FILE_WRITE_DATA, /* access_mask */
6753 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6755 FILE_OPEN, /* create_disposition*/
6756 0, /* create_options */
6757 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6758 0, /* oplock_request */
6760 0, /* allocation_size */
6761 0, /* private_flags */
6764 &new_fsp, /* result */
6766 NULL, NULL); /* create context */
6768 TALLOC_FREE(smb_fname_tmp);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 /* NB. We check for open_was_deferred in the caller. */
6775 /* See RAW-SFILEINFO-END-OF-FILE */
6776 if (fail_after_createfile) {
6777 close_file(req, new_fsp,NORMAL_CLOSE);
6778 return NT_STATUS_INVALID_LEVEL;
6781 if (vfs_set_filelen(new_fsp, size) == -1) {
6782 status = map_nt_error_from_unix(errno);
6783 close_file(req, new_fsp,NORMAL_CLOSE);
6787 trigger_write_time_update_immediate(new_fsp);
6788 close_file(req, new_fsp,NORMAL_CLOSE);
6789 return NT_STATUS_OK;
6792 /****************************************************************************
6793 Deal with SMB_INFO_SET_EA.
6794 ****************************************************************************/
6796 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6800 const struct smb_filename *smb_fname)
6802 struct ea_list *ea_list = NULL;
6803 TALLOC_CTX *ctx = NULL;
6804 NTSTATUS status = NT_STATUS_OK;
6806 if (total_data < 10) {
6808 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6809 length. They seem to have no effect. Bug #3212. JRA */
6811 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6812 /* We're done. We only get EA info in this call. */
6813 return NT_STATUS_OK;
6816 return NT_STATUS_INVALID_PARAMETER;
6819 if (IVAL(pdata,0) > total_data) {
6820 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6821 IVAL(pdata,0), (unsigned int)total_data));
6822 return NT_STATUS_INVALID_PARAMETER;
6826 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6828 return NT_STATUS_INVALID_PARAMETER;
6831 status = set_ea(conn, fsp, smb_fname, ea_list);
6836 /****************************************************************************
6837 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6838 ****************************************************************************/
6840 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6845 struct ea_list *ea_list = NULL;
6849 return NT_STATUS_INVALID_HANDLE;
6852 if (!lp_ea_support(SNUM(conn))) {
6853 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6854 "EA's not supported.\n",
6855 (unsigned int)total_data));
6856 return NT_STATUS_EAS_NOT_SUPPORTED;
6859 if (total_data < 10) {
6860 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6862 (unsigned int)total_data));
6863 return NT_STATUS_INVALID_PARAMETER;
6866 ea_list = read_nttrans_ea_list(talloc_tos(),
6871 return NT_STATUS_INVALID_PARAMETER;
6874 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6876 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6877 smb_fname_str_dbg(fsp->fsp_name),
6878 nt_errstr(status) ));
6884 /****************************************************************************
6885 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6886 ****************************************************************************/
6888 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6892 struct smb_filename *smb_fname)
6894 NTSTATUS status = NT_STATUS_OK;
6895 bool delete_on_close;
6896 uint32_t dosmode = 0;
6898 if (total_data < 1) {
6899 return NT_STATUS_INVALID_PARAMETER;
6903 return NT_STATUS_INVALID_HANDLE;
6906 delete_on_close = (CVAL(pdata,0) ? True : False);
6907 dosmode = dos_mode(conn, smb_fname);
6909 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6910 "delete_on_close = %u\n",
6911 smb_fname_str_dbg(smb_fname),
6912 (unsigned int)dosmode,
6913 (unsigned int)delete_on_close ));
6915 if (delete_on_close) {
6916 status = can_set_delete_on_close(fsp, dosmode);
6917 if (!NT_STATUS_IS_OK(status)) {
6922 /* The set is across all open files on this dev/inode pair. */
6923 if (!set_delete_on_close(fsp, delete_on_close,
6924 conn->session_info->security_token,
6925 conn->session_info->unix_token)) {
6926 return NT_STATUS_ACCESS_DENIED;
6928 return NT_STATUS_OK;
6931 /****************************************************************************
6932 Deal with SMB_FILE_POSITION_INFORMATION.
6933 ****************************************************************************/
6935 static NTSTATUS smb_file_position_information(connection_struct *conn,
6940 uint64_t position_information;
6942 if (total_data < 8) {
6943 return NT_STATUS_INVALID_PARAMETER;
6947 /* Ignore on pathname based set. */
6948 return NT_STATUS_OK;
6951 position_information = (uint64_t)IVAL(pdata,0);
6952 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6954 DEBUG(10,("smb_file_position_information: Set file position "
6955 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6956 (double)position_information));
6957 fsp->fh->position_information = position_information;
6958 return NT_STATUS_OK;
6961 /****************************************************************************
6962 Deal with SMB_FILE_MODE_INFORMATION.
6963 ****************************************************************************/
6965 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6971 if (total_data < 4) {
6972 return NT_STATUS_INVALID_PARAMETER;
6974 mode = IVAL(pdata,0);
6975 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6976 return NT_STATUS_INVALID_PARAMETER;
6978 return NT_STATUS_OK;
6981 /****************************************************************************
6982 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6983 ****************************************************************************/
6985 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6986 struct smb_request *req,
6989 const struct smb_filename *new_smb_fname)
6991 char *link_target = NULL;
6992 struct smb_filename target_fname;
6993 TALLOC_CTX *ctx = talloc_tos();
6997 /* Set a symbolic link. */
6998 /* Don't allow this if follow links is false. */
7000 if (total_data == 0) {
7001 return NT_STATUS_INVALID_PARAMETER;
7004 if (!lp_follow_symlinks(SNUM(conn))) {
7005 return NT_STATUS_ACCESS_DENIED;
7008 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
7009 total_data, STR_TERMINATE);
7012 return NT_STATUS_INVALID_PARAMETER;
7015 target_fname = (struct smb_filename) {
7016 .base_name = link_target,
7019 /* Removes @GMT tokens if any */
7020 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7021 if (!NT_STATUS_IS_OK(status)) {
7025 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7026 new_smb_fname->base_name, link_target ));
7028 ret = SMB_VFS_SYMLINKAT(conn,
7033 return map_nt_error_from_unix(errno);
7036 return NT_STATUS_OK;
7039 /****************************************************************************
7040 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7041 ****************************************************************************/
7043 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7044 struct smb_request *req,
7045 const char *pdata, int total_data,
7046 struct smb_filename *smb_fname_new)
7048 char *oldname = NULL;
7049 struct smb_filename *smb_fname_old = NULL;
7050 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7051 TALLOC_CTX *ctx = talloc_tos();
7052 NTSTATUS status = NT_STATUS_OK;
7054 /* Set a hard link. */
7055 if (total_data == 0) {
7056 return NT_STATUS_INVALID_PARAMETER;
7059 if (req->posix_pathnames) {
7060 srvstr_get_path_posix(ctx,
7069 srvstr_get_path(ctx,
7078 if (!NT_STATUS_IS_OK(status)) {
7082 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7083 smb_fname_str_dbg(smb_fname_new), oldname));
7085 status = filename_convert(ctx,
7092 if (!NT_STATUS_IS_OK(status)) {
7096 return hardlink_internals(ctx, conn, req, false,
7097 smb_fname_old, smb_fname_new);
7100 /****************************************************************************
7101 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7102 ****************************************************************************/
7104 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7105 struct smb_request *req,
7109 struct smb_filename *smb_fname_src)
7113 char *newname = NULL;
7114 struct smb_filename *smb_fname_dst = NULL;
7115 const char *dst_original_lcomp = NULL;
7116 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7117 NTSTATUS status = NT_STATUS_OK;
7118 TALLOC_CTX *ctx = talloc_tos();
7121 return NT_STATUS_INVALID_HANDLE;
7124 if (total_data < 20) {
7125 return NT_STATUS_INVALID_PARAMETER;
7128 overwrite = (CVAL(pdata,0) ? True : False);
7129 len = IVAL(pdata,16);
7131 if (len > (total_data - 20) || (len == 0)) {
7132 return NT_STATUS_INVALID_PARAMETER;
7135 if (req->posix_pathnames) {
7136 srvstr_get_path_posix(ctx,
7145 srvstr_get_path(ctx,
7154 if (!NT_STATUS_IS_OK(status)) {
7158 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7161 status = filename_convert(ctx,
7168 if (!NT_STATUS_IS_OK(status)) {
7172 if (fsp->base_fsp) {
7173 /* newname must be a stream name. */
7174 if (newname[0] != ':') {
7175 return NT_STATUS_NOT_SUPPORTED;
7178 /* Create an smb_fname to call rename_internals_fsp() with. */
7179 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7180 fsp->base_fsp->fsp_name->base_name,
7183 fsp->base_fsp->fsp_name->twrp,
7184 fsp->base_fsp->fsp_name->flags);
7185 if (smb_fname_dst == NULL) {
7186 status = NT_STATUS_NO_MEMORY;
7192 * Set the original last component, since
7193 * rename_internals_fsp() requires it.
7195 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7199 if (dst_original_lcomp == NULL) {
7200 status = NT_STATUS_NO_MEMORY;
7204 DEBUG(10,("smb2_file_rename_information: "
7205 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7206 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7207 smb_fname_str_dbg(smb_fname_dst)));
7208 status = rename_internals_fsp(conn,
7212 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7216 TALLOC_FREE(smb_fname_dst);
7220 static NTSTATUS smb_file_link_information(connection_struct *conn,
7221 struct smb_request *req,
7225 struct smb_filename *smb_fname_src)
7229 char *newname = NULL;
7230 struct smb_filename *smb_fname_dst = NULL;
7231 NTSTATUS status = NT_STATUS_OK;
7232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7233 TALLOC_CTX *ctx = talloc_tos();
7236 return NT_STATUS_INVALID_HANDLE;
7239 if (total_data < 20) {
7240 return NT_STATUS_INVALID_PARAMETER;
7243 overwrite = (CVAL(pdata,0) ? true : false);
7244 len = IVAL(pdata,16);
7246 if (len > (total_data - 20) || (len == 0)) {
7247 return NT_STATUS_INVALID_PARAMETER;
7250 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7251 srvstr_get_path_posix(ctx,
7259 ucf_flags |= UCF_POSIX_PATHNAMES;
7261 srvstr_get_path(ctx,
7270 if (!NT_STATUS_IS_OK(status)) {
7274 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7277 status = filename_convert(ctx,
7284 if (!NT_STATUS_IS_OK(status)) {
7288 if (fsp->base_fsp) {
7289 /* No stream names. */
7290 return NT_STATUS_NOT_SUPPORTED;
7293 DEBUG(10,("smb_file_link_information: "
7294 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7295 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7296 smb_fname_str_dbg(smb_fname_dst)));
7297 status = hardlink_internals(ctx,
7304 TALLOC_FREE(smb_fname_dst);
7308 /****************************************************************************
7309 Deal with SMB_FILE_RENAME_INFORMATION.
7310 ****************************************************************************/
7312 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7313 struct smb_request *req,
7317 struct smb_filename *smb_fname_src)
7322 char *newname = NULL;
7323 struct smb_filename *smb_fname_dst = NULL;
7324 const char *dst_original_lcomp = NULL;
7325 bool dest_has_wcard = False;
7326 NTSTATUS status = NT_STATUS_OK;
7328 TALLOC_CTX *ctx = talloc_tos();
7330 if (total_data < 13) {
7331 return NT_STATUS_INVALID_PARAMETER;
7334 overwrite = (CVAL(pdata,0) ? True : False);
7335 root_fid = IVAL(pdata,4);
7336 len = IVAL(pdata,8);
7338 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7339 return NT_STATUS_INVALID_PARAMETER;
7342 if (req->posix_pathnames) {
7343 srvstr_get_path_wcard_posix(ctx,
7353 srvstr_get_path_wcard(ctx,
7363 if (!NT_STATUS_IS_OK(status)) {
7367 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7370 /* Check the new name has no '/' characters. */
7371 if (strchr_m(newname, '/')) {
7372 return NT_STATUS_NOT_SUPPORTED;
7375 if (fsp && fsp->base_fsp) {
7376 /* newname must be a stream name. */
7377 if (newname[0] != ':') {
7378 return NT_STATUS_NOT_SUPPORTED;
7381 /* Create an smb_fname to call rename_internals_fsp() with. */
7382 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7383 fsp->base_fsp->fsp_name->base_name,
7386 fsp->base_fsp->fsp_name->twrp,
7387 fsp->base_fsp->fsp_name->flags);
7388 if (smb_fname_dst == NULL) {
7389 status = NT_STATUS_NO_MEMORY;
7394 * Get the original last component, since
7395 * rename_internals_fsp() requires it.
7397 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7401 if (dst_original_lcomp == NULL) {
7402 status = NT_STATUS_NO_MEMORY;
7408 * Build up an smb_fname_dst based on the filename passed in.
7409 * We basically just strip off the last component, and put on
7410 * the newname instead.
7412 char *base_name = NULL;
7413 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7415 if (dest_has_wcard) {
7416 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7419 /* newname must *not* be a stream name. */
7420 if (newname[0] == ':') {
7421 return NT_STATUS_NOT_SUPPORTED;
7425 * Strip off the last component (filename) of the path passed
7428 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7430 return NT_STATUS_NO_MEMORY;
7432 p = strrchr_m(base_name, '/');
7436 base_name = talloc_strdup(ctx, "");
7438 return NT_STATUS_NO_MEMORY;
7441 /* Append the new name. */
7442 base_name = talloc_asprintf_append(base_name,
7446 return NT_STATUS_NO_MEMORY;
7449 status = filename_convert(ctx,
7457 /* If an error we expect this to be
7458 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7460 if (!NT_STATUS_IS_OK(status)) {
7461 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7465 /* Create an smb_fname to call rename_internals_fsp() */
7466 smb_fname_dst = synthetic_smb_fname(ctx,
7470 smb_fname_src->twrp,
7471 smb_fname_src->flags);
7472 if (smb_fname_dst == NULL) {
7473 status = NT_STATUS_NO_MEMORY;
7477 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7481 if (dst_original_lcomp == NULL) {
7482 status = NT_STATUS_NO_MEMORY;
7488 DEBUG(10,("smb_file_rename_information: "
7489 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7490 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7491 smb_fname_str_dbg(smb_fname_dst)));
7492 status = rename_internals_fsp(conn,
7499 DEBUG(10,("smb_file_rename_information: "
7500 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7501 smb_fname_str_dbg(smb_fname_src),
7502 smb_fname_str_dbg(smb_fname_dst)));
7503 status = rename_internals(ctx,
7513 FILE_WRITE_ATTRIBUTES);
7516 TALLOC_FREE(smb_fname_dst);
7520 /****************************************************************************
7521 Deal with SMB_SET_POSIX_ACL.
7522 ****************************************************************************/
7524 #if defined(HAVE_POSIX_ACLS)
7525 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7526 struct smb_request *req,
7530 const struct smb_filename *smb_fname)
7532 uint16_t posix_acl_version;
7533 uint16_t num_file_acls;
7534 uint16_t num_def_acls;
7535 bool valid_file_acls = true;
7536 bool valid_def_acls = true;
7538 unsigned int size_needed;
7539 unsigned int total_data;
7540 bool close_fsp = false;
7542 if (total_data_in < 0) {
7543 status = NT_STATUS_INVALID_PARAMETER;
7547 total_data = total_data_in;
7549 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7550 status = NT_STATUS_INVALID_PARAMETER;
7553 posix_acl_version = SVAL(pdata,0);
7554 num_file_acls = SVAL(pdata,2);
7555 num_def_acls = SVAL(pdata,4);
7557 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7558 valid_file_acls = false;
7562 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7563 valid_def_acls = false;
7567 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7568 status = NT_STATUS_INVALID_PARAMETER;
7573 if (num_file_acls + num_def_acls < num_file_acls) {
7574 status = NT_STATUS_INVALID_PARAMETER;
7578 size_needed = num_file_acls + num_def_acls;
7581 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7582 * than UINT_MAX, so check by division.
7584 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7585 status = NT_STATUS_INVALID_PARAMETER;
7589 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7590 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7591 status = NT_STATUS_INVALID_PARAMETER;
7594 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7596 if (total_data < size_needed) {
7597 status = NT_STATUS_INVALID_PARAMETER;
7602 * Ensure we always operate on a file descriptor, not just
7606 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7608 SEC_STD_READ_CONTROL|
7609 FILE_READ_ATTRIBUTES|
7610 FILE_WRITE_ATTRIBUTES;
7612 status = get_posix_fsp(conn,
7618 if (!NT_STATUS_IS_OK(status)) {
7624 /* Here we know fsp != NULL */
7625 SMB_ASSERT(fsp != NULL);
7627 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7628 if (!NT_STATUS_IS_OK(status)) {
7632 /* If we have a default acl, this *must* be a directory. */
7633 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7634 DBG_INFO("Can't set default acls on "
7635 "non-directory %s\n",
7637 return NT_STATUS_INVALID_HANDLE;
7640 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7641 "num_def_acls = %"PRIu16"\n",
7646 /* Move pdata to the start of the file ACL entries. */
7647 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7649 if (valid_file_acls) {
7650 status = set_unix_posix_acl(conn,
7654 if (!NT_STATUS_IS_OK(status)) {
7659 /* Move pdata to the start of the default ACL entries. */
7660 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7662 if (valid_def_acls) {
7663 status = set_unix_posix_default_acl(conn,
7667 if (!NT_STATUS_IS_OK(status)) {
7672 status = NT_STATUS_OK;
7677 (void)close_file(req, fsp, NORMAL_CLOSE);
7684 /****************************************************************************
7685 Deal with SMB_SET_POSIX_LOCK.
7686 ****************************************************************************/
7688 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7690 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7691 struct smb_request *req,
7696 struct tevent_req *subreq = NULL;
7697 struct smbd_lock_element *lck = NULL;
7701 bool blocking_lock = False;
7702 enum brl_type lock_type;
7704 NTSTATUS status = NT_STATUS_OK;
7706 if (fsp == NULL || fsp->fh->fd == -1) {
7707 return NT_STATUS_INVALID_HANDLE;
7710 if (total_data != POSIX_LOCK_DATA_SIZE) {
7711 return NT_STATUS_INVALID_PARAMETER;
7714 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7715 case POSIX_LOCK_TYPE_READ:
7716 lock_type = READ_LOCK;
7718 case POSIX_LOCK_TYPE_WRITE:
7719 /* Return the right POSIX-mappable error code for files opened read-only. */
7720 if (!fsp->fsp_flags.can_write) {
7721 return NT_STATUS_INVALID_HANDLE;
7723 lock_type = WRITE_LOCK;
7725 case POSIX_LOCK_TYPE_UNLOCK:
7726 lock_type = UNLOCK_LOCK;
7729 return NT_STATUS_INVALID_PARAMETER;
7732 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7733 case POSIX_LOCK_FLAG_NOWAIT:
7734 blocking_lock = false;
7736 case POSIX_LOCK_FLAG_WAIT:
7737 blocking_lock = true;
7740 return NT_STATUS_INVALID_PARAMETER;
7743 if (!lp_blocking_locks(SNUM(conn))) {
7744 blocking_lock = False;
7747 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7748 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7749 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7750 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7751 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7753 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7754 "count = %"PRIu64", offset = %"PRIu64"\n",
7756 (unsigned int)lock_type,
7761 if (lock_type == UNLOCK_LOCK) {
7762 struct smbd_lock_element l = {
7763 .req_guid = smbd_request_guid(req, 0),
7765 .brltype = UNLOCK_LOCK,
7769 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7773 lck = talloc(req, struct smbd_lock_element);
7775 return NT_STATUS_NO_MEMORY;
7778 *lck = (struct smbd_lock_element) {
7779 .req_guid = smbd_request_guid(req, 0),
7781 .brltype = lock_type,
7786 subreq = smbd_smb1_do_locks_send(
7791 blocking_lock ? UINT32_MAX : 0,
7792 true, /* large_offset */
7796 if (subreq == NULL) {
7798 return NT_STATUS_NO_MEMORY;
7800 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7801 return NT_STATUS_EVENT_PENDING;
7804 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7806 struct smb_request *req = NULL;
7810 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7813 status = smbd_smb1_do_locks_recv(subreq);
7814 TALLOC_FREE(subreq);
7816 if (NT_STATUS_IS_OK(status)) {
7817 char params[2] = {0};
7818 /* Fake up max_data_bytes here - we know it fits. */
7819 send_trans2_replies(
7829 reply_nterror(req, status);
7832 (char *)req->outbuf,
7835 IS_CONN_ENCRYPTED(req->conn),
7838 exit_server_cleanly("smb_set_posix_lock_done: "
7839 "srv_send_smb failed.");
7847 /****************************************************************************
7848 Deal with SMB_SET_FILE_BASIC_INFO.
7849 ****************************************************************************/
7851 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7855 const struct smb_filename *smb_fname)
7857 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7858 struct smb_file_time ft;
7859 uint32_t dosmode = 0;
7860 NTSTATUS status = NT_STATUS_OK;
7862 init_smb_file_time(&ft);
7864 if (total_data < 36) {
7865 return NT_STATUS_INVALID_PARAMETER;
7869 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7871 status = check_access(conn,
7874 FILE_WRITE_ATTRIBUTES);
7876 if (!NT_STATUS_IS_OK(status)) {
7880 /* Set the attributes */
7881 dosmode = IVAL(pdata,32);
7882 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7883 if (!NT_STATUS_IS_OK(status)) {
7888 ft.create_time = pull_long_date_full_timespec(pdata);
7891 ft.atime = pull_long_date_full_timespec(pdata+8);
7894 ft.mtime = pull_long_date_full_timespec(pdata+16);
7897 ft.ctime = pull_long_date_full_timespec(pdata+24);
7899 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7900 smb_fname_str_dbg(smb_fname)));
7902 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7903 if (!NT_STATUS_IS_OK(status)) {
7907 if (fsp != NULL && fsp->fsp_flags.modified) {
7908 trigger_write_time_update_immediate(fsp);
7910 return NT_STATUS_OK;
7913 /****************************************************************************
7914 Deal with SMB_INFO_STANDARD.
7915 ****************************************************************************/
7917 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7921 const struct smb_filename *smb_fname)
7924 struct smb_file_time ft;
7926 init_smb_file_time(&ft);
7928 if (total_data < 12) {
7929 return NT_STATUS_INVALID_PARAMETER;
7933 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7935 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7937 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7939 DEBUG(10,("smb_set_info_standard: file %s\n",
7940 smb_fname_str_dbg(smb_fname)));
7943 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7945 status = check_access(conn,
7948 FILE_WRITE_ATTRIBUTES);
7950 if (!NT_STATUS_IS_OK(status)) {
7954 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7955 if (!NT_STATUS_IS_OK(status)) {
7959 if (fsp != NULL && fsp->fsp_flags.modified) {
7960 trigger_write_time_update_immediate(fsp);
7962 return NT_STATUS_OK;
7965 /****************************************************************************
7966 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7967 ****************************************************************************/
7969 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7970 struct smb_request *req,
7974 struct smb_filename *smb_fname)
7976 uint64_t allocation_size = 0;
7977 NTSTATUS status = NT_STATUS_OK;
7978 files_struct *new_fsp = NULL;
7980 if (!VALID_STAT(smb_fname->st)) {
7981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7984 if (total_data < 8) {
7985 return NT_STATUS_INVALID_PARAMETER;
7988 allocation_size = (uint64_t)IVAL(pdata,0);
7989 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7990 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7991 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7992 (double)allocation_size));
7994 if (allocation_size) {
7995 allocation_size = smb_roundup(conn, allocation_size);
7998 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7999 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
8000 (double)allocation_size));
8002 if (fsp && fsp->fh->fd != -1) {
8003 /* Open file handle. */
8004 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
8005 return NT_STATUS_ACCESS_DENIED;
8008 /* Only change if needed. */
8009 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8010 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
8011 return map_nt_error_from_unix(errno);
8014 /* But always update the time. */
8016 * This is equivalent to a write. Ensure it's seen immediately
8017 * if there are no pending writes.
8019 trigger_write_time_update_immediate(fsp);
8020 return NT_STATUS_OK;
8023 /* Pathname or stat or directory file. */
8024 status = SMB_VFS_CREATE_FILE(
8027 &conn->cwd_fsp, /* dirfsp */
8028 smb_fname, /* fname */
8029 FILE_WRITE_DATA, /* access_mask */
8030 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8032 FILE_OPEN, /* create_disposition*/
8033 0, /* create_options */
8034 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8035 0, /* oplock_request */
8037 0, /* allocation_size */
8038 0, /* private_flags */
8041 &new_fsp, /* result */
8043 NULL, NULL); /* create context */
8045 if (!NT_STATUS_IS_OK(status)) {
8046 /* NB. We check for open_was_deferred in the caller. */
8050 /* Only change if needed. */
8051 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8052 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8053 status = map_nt_error_from_unix(errno);
8054 close_file(req, new_fsp, NORMAL_CLOSE);
8059 /* Changing the allocation size should set the last mod time. */
8061 * This is equivalent to a write. Ensure it's seen immediately
8062 * if there are no pending writes.
8064 trigger_write_time_update_immediate(new_fsp);
8065 close_file(req, new_fsp, NORMAL_CLOSE);
8066 return NT_STATUS_OK;
8069 /****************************************************************************
8070 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8071 ****************************************************************************/
8073 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8074 struct smb_request *req,
8078 const struct smb_filename *smb_fname,
8079 bool fail_after_createfile)
8083 if (total_data < 8) {
8084 return NT_STATUS_INVALID_PARAMETER;
8087 size = IVAL(pdata,0);
8088 size |= (((off_t)IVAL(pdata,4)) << 32);
8089 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8090 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8093 return smb_set_file_size(conn, req,
8098 fail_after_createfile);
8101 /****************************************************************************
8102 Allow a UNIX info mknod.
8103 ****************************************************************************/
8105 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8108 const struct smb_filename *smb_fname)
8110 uint32_t file_type = IVAL(pdata,56);
8111 #if defined(HAVE_MAKEDEV)
8112 uint32_t dev_major = IVAL(pdata,60);
8113 uint32_t dev_minor = IVAL(pdata,68);
8115 SMB_DEV_T dev = (SMB_DEV_T)0;
8116 uint32_t raw_unixmode = IVAL(pdata,84);
8121 if (total_data < 100) {
8122 return NT_STATUS_INVALID_PARAMETER;
8125 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8126 PERM_NEW_FILE, &unixmode);
8127 if (!NT_STATUS_IS_OK(status)) {
8131 #if defined(HAVE_MAKEDEV)
8132 dev = makedev(dev_major, dev_minor);
8135 switch (file_type) {
8136 /* We can't create other objects here. */
8137 case UNIX_TYPE_FILE:
8139 case UNIX_TYPE_SYMLINK:
8140 return NT_STATUS_ACCESS_DENIED;
8141 #if defined(S_IFIFO)
8142 case UNIX_TYPE_FIFO:
8143 unixmode |= S_IFIFO;
8146 #if defined(S_IFSOCK)
8147 case UNIX_TYPE_SOCKET:
8148 unixmode |= S_IFSOCK;
8151 #if defined(S_IFCHR)
8152 case UNIX_TYPE_CHARDEV:
8153 /* This is only allowed for root. */
8154 if (get_current_uid(conn) != sec_initial_uid()) {
8155 return NT_STATUS_ACCESS_DENIED;
8157 unixmode |= S_IFCHR;
8160 #if defined(S_IFBLK)
8161 case UNIX_TYPE_BLKDEV:
8162 if (get_current_uid(conn) != sec_initial_uid()) {
8163 return NT_STATUS_ACCESS_DENIED;
8165 unixmode |= S_IFBLK;
8169 return NT_STATUS_INVALID_PARAMETER;
8172 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8173 "%.0f mode 0%o for file %s\n", (double)dev,
8174 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8176 /* Ok - do the mknod. */
8177 ret = SMB_VFS_MKNODAT(conn,
8184 return map_nt_error_from_unix(errno);
8187 /* If any of the other "set" calls fail we
8188 * don't want to end up with a half-constructed mknod.
8191 if (lp_inherit_permissions(SNUM(conn))) {
8192 struct smb_filename *parent_fname = NULL;
8195 ok = parent_smb_fname(talloc_tos(),
8200 return NT_STATUS_NO_MEMORY;
8202 inherit_access_posix_acl(conn,
8206 TALLOC_FREE(parent_fname);
8209 return NT_STATUS_OK;
8212 /****************************************************************************
8213 Deal with SMB_SET_FILE_UNIX_BASIC.
8214 ****************************************************************************/
8216 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8217 struct smb_request *req,
8221 const struct smb_filename *smb_fname)
8223 struct smb_file_time ft;
8224 uint32_t raw_unixmode;
8227 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8228 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8229 NTSTATUS status = NT_STATUS_OK;
8230 enum perm_type ptype;
8231 files_struct *all_fsps = NULL;
8232 bool modify_mtime = true;
8234 SMB_STRUCT_STAT sbuf;
8236 init_smb_file_time(&ft);
8238 if (total_data < 100) {
8239 return NT_STATUS_INVALID_PARAMETER;
8242 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8243 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8244 size=IVAL(pdata,0); /* first 8 Bytes are size */
8245 size |= (((off_t)IVAL(pdata,4)) << 32);
8248 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8249 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8250 set_owner = (uid_t)IVAL(pdata,40);
8251 set_grp = (gid_t)IVAL(pdata,48);
8252 raw_unixmode = IVAL(pdata,84);
8254 if (VALID_STAT(smb_fname->st)) {
8255 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8256 ptype = PERM_EXISTING_DIR;
8258 ptype = PERM_EXISTING_FILE;
8261 ptype = PERM_NEW_FILE;
8264 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8266 if (!NT_STATUS_IS_OK(status)) {
8270 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8271 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8272 smb_fname_str_dbg(smb_fname), (double)size,
8273 (unsigned int)set_owner, (unsigned int)set_grp,
8274 (int)raw_unixmode));
8276 sbuf = smb_fname->st;
8278 if (!VALID_STAT(sbuf)) {
8280 * The only valid use of this is to create character and block
8281 * devices, and named pipes. This is deprecated (IMHO) and
8282 * a new info level should be used for mknod. JRA.
8285 return smb_unix_mknod(conn,
8292 /* Horrible backwards compatibility hack as an old server bug
8293 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8297 size = get_file_size_stat(&sbuf);
8302 * Deal with the UNIX specific mode set.
8305 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8308 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8309 "setting mode 0%o for file %s\n",
8310 (unsigned int)unixmode,
8311 smb_fname_str_dbg(smb_fname)));
8312 if (fsp && fsp->fh->fd != -1) {
8313 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8315 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8318 return map_nt_error_from_unix(errno);
8323 * Deal with the UNIX specific uid set.
8326 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8327 (sbuf.st_ex_uid != set_owner)) {
8330 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8331 "changing owner %u for path %s\n",
8332 (unsigned int)set_owner,
8333 smb_fname_str_dbg(smb_fname)));
8335 if (fsp && fsp->fh->fd != -1) {
8336 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8339 * UNIX extensions calls must always operate
8342 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8343 set_owner, (gid_t)-1);
8347 status = map_nt_error_from_unix(errno);
8353 * Deal with the UNIX specific gid set.
8356 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8357 (sbuf.st_ex_gid != set_grp)) {
8360 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8361 "changing group %u for file %s\n",
8362 (unsigned int)set_grp,
8363 smb_fname_str_dbg(smb_fname)));
8364 if (fsp && fsp->fh->fd != -1) {
8365 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8368 * UNIX extensions calls must always operate
8371 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8375 status = map_nt_error_from_unix(errno);
8380 /* Deal with any size changes. */
8382 if (S_ISREG(sbuf.st_ex_mode)) {
8383 status = smb_set_file_size(conn, req,
8389 if (!NT_STATUS_IS_OK(status)) {
8394 /* Deal with any time changes. */
8395 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8396 /* No change, don't cancel anything. */
8400 id = vfs_file_id_from_sbuf(conn, &sbuf);
8401 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8402 all_fsps = file_find_di_next(all_fsps)) {
8404 * We're setting the time explicitly for UNIX.
8405 * Cancel any pending changes over all handles.
8407 all_fsps->fsp_flags.update_write_time_on_close = false;
8408 TALLOC_FREE(all_fsps->update_write_time_event);
8412 * Override the "setting_write_time"
8413 * parameter here as it almost does what
8414 * we need. Just remember if we modified
8415 * mtime and send the notify ourselves.
8417 if (is_omit_timespec(&ft.mtime)) {
8418 modify_mtime = false;
8421 status = smb_set_file_time(conn,
8427 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8428 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8433 /****************************************************************************
8434 Deal with SMB_SET_FILE_UNIX_INFO2.
8435 ****************************************************************************/
8437 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8438 struct smb_request *req,
8442 const struct smb_filename *smb_fname)
8445 uint32_t smb_fflags;
8448 if (total_data < 116) {
8449 return NT_STATUS_INVALID_PARAMETER;
8452 /* Start by setting all the fields that are common between UNIX_BASIC
8455 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8457 if (!NT_STATUS_IS_OK(status)) {
8461 smb_fflags = IVAL(pdata, 108);
8462 smb_fmask = IVAL(pdata, 112);
8464 /* NB: We should only attempt to alter the file flags if the client
8465 * sends a non-zero mask.
8467 if (smb_fmask != 0) {
8468 int stat_fflags = 0;
8470 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8471 smb_fmask, &stat_fflags)) {
8472 /* Client asked to alter a flag we don't understand. */
8473 return NT_STATUS_INVALID_PARAMETER;
8476 if (fsp && fsp->fh->fd != -1) {
8477 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8478 return NT_STATUS_NOT_SUPPORTED;
8480 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8481 stat_fflags) != 0) {
8482 return map_nt_error_from_unix(errno);
8487 /* XXX: need to add support for changing the create_time here. You
8488 * can do this for paths on Darwin with setattrlist(2). The right way
8489 * to hook this up is probably by extending the VFS utimes interface.
8492 return NT_STATUS_OK;
8495 /****************************************************************************
8496 Create a directory with POSIX semantics.
8497 ****************************************************************************/
8499 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8500 struct smb_request *req,
8503 struct smb_filename *smb_fname,
8504 int *pdata_return_size)
8506 NTSTATUS status = NT_STATUS_OK;
8507 uint32_t raw_unixmode = 0;
8508 mode_t unixmode = (mode_t)0;
8509 files_struct *fsp = NULL;
8510 uint16_t info_level_return = 0;
8512 char *pdata = *ppdata;
8513 struct smb2_create_blobs *posx = NULL;
8515 if (total_data < 18) {
8516 return NT_STATUS_INVALID_PARAMETER;
8519 raw_unixmode = IVAL(pdata,8);
8520 /* Next 4 bytes are not yet defined. */
8522 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8523 PERM_NEW_DIR, &unixmode);
8524 if (!NT_STATUS_IS_OK(status)) {
8528 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8529 if (!NT_STATUS_IS_OK(status)) {
8530 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8535 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8536 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8538 status = SMB_VFS_CREATE_FILE(
8541 &conn->cwd_fsp, /* dirfsp */
8542 smb_fname, /* fname */
8543 FILE_READ_ATTRIBUTES, /* access_mask */
8544 FILE_SHARE_NONE, /* share_access */
8545 FILE_CREATE, /* create_disposition*/
8546 FILE_DIRECTORY_FILE, /* create_options */
8547 0, /* file_attributes */
8548 0, /* oplock_request */
8550 0, /* allocation_size */
8551 0, /* private_flags */
8556 posx, /* in_context_blobs */
8557 NULL); /* out_context_blobs */
8561 if (NT_STATUS_IS_OK(status)) {
8562 close_file(req, fsp, NORMAL_CLOSE);
8565 info_level_return = SVAL(pdata,16);
8567 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8568 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8569 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8570 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8572 *pdata_return_size = 12;
8575 /* Realloc the data size */
8576 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8577 if (*ppdata == NULL) {
8578 *pdata_return_size = 0;
8579 return NT_STATUS_NO_MEMORY;
8583 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8584 SSVAL(pdata,2,0); /* No fnum. */
8585 SIVAL(pdata,4,info); /* Was directory created. */
8587 switch (info_level_return) {
8588 case SMB_QUERY_FILE_UNIX_BASIC:
8589 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8590 SSVAL(pdata,10,0); /* Padding. */
8591 store_file_unix_basic(conn, pdata + 12, fsp,
8594 case SMB_QUERY_FILE_UNIX_INFO2:
8595 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8596 SSVAL(pdata,10,0); /* Padding. */
8597 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8601 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8602 SSVAL(pdata,10,0); /* Padding. */
8609 /****************************************************************************
8610 Open/Create a file with POSIX semantics.
8611 ****************************************************************************/
8613 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8614 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8616 static NTSTATUS smb_posix_open(connection_struct *conn,
8617 struct smb_request *req,
8620 struct smb_filename *smb_fname,
8621 int *pdata_return_size)
8623 bool extended_oplock_granted = False;
8624 char *pdata = *ppdata;
8626 uint32_t wire_open_mode = 0;
8627 uint32_t raw_unixmode = 0;
8628 uint32_t attributes = 0;
8629 uint32_t create_disp = 0;
8630 uint32_t access_mask = 0;
8631 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8632 NTSTATUS status = NT_STATUS_OK;
8633 mode_t unixmode = (mode_t)0;
8634 files_struct *fsp = NULL;
8635 int oplock_request = 0;
8637 uint16_t info_level_return = 0;
8638 struct smb2_create_blobs *posx = NULL;
8640 if (total_data < 18) {
8641 return NT_STATUS_INVALID_PARAMETER;
8644 flags = IVAL(pdata,0);
8645 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8646 if (oplock_request) {
8647 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8650 wire_open_mode = IVAL(pdata,4);
8652 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8653 return smb_posix_mkdir(conn, req,
8660 switch (wire_open_mode & SMB_ACCMODE) {
8662 access_mask = SMB_O_RDONLY_MAPPING;
8665 access_mask = SMB_O_WRONLY_MAPPING;
8668 access_mask = (SMB_O_RDONLY_MAPPING|
8669 SMB_O_WRONLY_MAPPING);
8672 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8673 (unsigned int)wire_open_mode ));
8674 return NT_STATUS_INVALID_PARAMETER;
8677 wire_open_mode &= ~SMB_ACCMODE;
8679 /* First take care of O_CREAT|O_EXCL interactions. */
8680 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8681 case (SMB_O_CREAT | SMB_O_EXCL):
8682 /* File exists fail. File not exist create. */
8683 create_disp = FILE_CREATE;
8686 /* File exists open. File not exist create. */
8687 create_disp = FILE_OPEN_IF;
8690 /* O_EXCL on its own without O_CREAT is undefined.
8691 We deliberately ignore it as some versions of
8692 Linux CIFSFS can send a bare O_EXCL on the
8693 wire which other filesystems in the kernel
8694 ignore. See bug 9519 for details. */
8699 /* File exists open. File not exist fail. */
8700 create_disp = FILE_OPEN;
8703 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8704 (unsigned int)wire_open_mode ));
8705 return NT_STATUS_INVALID_PARAMETER;
8708 /* Next factor in the effects of O_TRUNC. */
8709 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8711 if (wire_open_mode & SMB_O_TRUNC) {
8712 switch (create_disp) {
8714 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8715 /* Leave create_disp alone as
8716 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8718 /* File exists fail. File not exist create. */
8721 /* SMB_O_CREAT | SMB_O_TRUNC */
8722 /* File exists overwrite. File not exist create. */
8723 create_disp = FILE_OVERWRITE_IF;
8727 /* File exists overwrite. File not exist fail. */
8728 create_disp = FILE_OVERWRITE;
8731 /* Cannot get here. */
8732 smb_panic("smb_posix_open: logic error");
8733 return NT_STATUS_INVALID_PARAMETER;
8737 raw_unixmode = IVAL(pdata,8);
8738 /* Next 4 bytes are not yet defined. */
8740 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8741 (VALID_STAT(smb_fname->st) ?
8742 PERM_EXISTING_FILE : PERM_NEW_FILE),
8745 if (!NT_STATUS_IS_OK(status)) {
8749 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8750 if (!NT_STATUS_IS_OK(status)) {
8751 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8756 if (wire_open_mode & SMB_O_SYNC) {
8757 create_options |= FILE_WRITE_THROUGH;
8759 if (wire_open_mode & SMB_O_APPEND) {
8760 access_mask |= FILE_APPEND_DATA;
8762 if (wire_open_mode & SMB_O_DIRECT) {
8763 attributes |= FILE_FLAG_NO_BUFFERING;
8766 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8767 VALID_STAT_OF_DIR(smb_fname->st)) {
8768 if (access_mask != SMB_O_RDONLY_MAPPING) {
8769 return NT_STATUS_FILE_IS_A_DIRECTORY;
8771 create_options &= ~FILE_NON_DIRECTORY_FILE;
8772 create_options |= FILE_DIRECTORY_FILE;
8775 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8776 smb_fname_str_dbg(smb_fname),
8777 (unsigned int)wire_open_mode,
8778 (unsigned int)unixmode ));
8780 status = SMB_VFS_CREATE_FILE(
8783 &conn->cwd_fsp, /* dirfsp */
8784 smb_fname, /* fname */
8785 access_mask, /* access_mask */
8786 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8788 create_disp, /* create_disposition*/
8789 create_options, /* create_options */
8790 attributes, /* file_attributes */
8791 oplock_request, /* oplock_request */
8793 0, /* allocation_size */
8794 0, /* private_flags */
8799 posx, /* in_context_blobs */
8800 NULL); /* out_context_blobs */
8804 if (!NT_STATUS_IS_OK(status)) {
8808 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8809 extended_oplock_granted = True;
8812 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8813 extended_oplock_granted = True;
8816 info_level_return = SVAL(pdata,16);
8818 /* Allocate the correct return size. */
8820 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8821 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8822 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8823 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8825 *pdata_return_size = 12;
8828 /* Realloc the data size */
8829 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8830 if (*ppdata == NULL) {
8831 close_file(req, fsp, ERROR_CLOSE);
8832 *pdata_return_size = 0;
8833 return NT_STATUS_NO_MEMORY;
8837 if (extended_oplock_granted) {
8838 if (flags & REQUEST_BATCH_OPLOCK) {
8839 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8841 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8843 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8844 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8846 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8849 SSVAL(pdata,2,fsp->fnum);
8850 SIVAL(pdata,4,info); /* Was file created etc. */
8852 switch (info_level_return) {
8853 case SMB_QUERY_FILE_UNIX_BASIC:
8854 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8855 SSVAL(pdata,10,0); /* padding. */
8856 store_file_unix_basic(conn, pdata + 12, fsp,
8859 case SMB_QUERY_FILE_UNIX_INFO2:
8860 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8861 SSVAL(pdata,10,0); /* padding. */
8862 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8866 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8867 SSVAL(pdata,10,0); /* padding. */
8870 return NT_STATUS_OK;
8873 /****************************************************************************
8874 Delete a file with POSIX semantics.
8875 ****************************************************************************/
8877 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8878 struct smb_request *req,
8881 struct smb_filename *smb_fname)
8883 NTSTATUS status = NT_STATUS_OK;
8884 files_struct *fsp = NULL;
8888 int create_options = 0;
8889 struct share_mode_lock *lck = NULL;
8890 bool other_nonposix_opens;
8891 struct smb2_create_blobs *posx = NULL;
8893 if (total_data < 2) {
8894 return NT_STATUS_INVALID_PARAMETER;
8897 flags = SVAL(pdata,0);
8899 if (!VALID_STAT(smb_fname->st)) {
8900 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8903 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8904 !VALID_STAT_OF_DIR(smb_fname->st)) {
8905 return NT_STATUS_NOT_A_DIRECTORY;
8908 DEBUG(10,("smb_posix_unlink: %s %s\n",
8909 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8910 smb_fname_str_dbg(smb_fname)));
8912 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8913 create_options |= FILE_DIRECTORY_FILE;
8916 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8917 if (!NT_STATUS_IS_OK(status)) {
8918 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8923 status = SMB_VFS_CREATE_FILE(
8926 &conn->cwd_fsp, /* dirfsp */
8927 smb_fname, /* fname */
8928 DELETE_ACCESS, /* access_mask */
8929 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8931 FILE_OPEN, /* create_disposition*/
8932 create_options, /* create_options */
8933 0, /* file_attributes */
8934 0, /* oplock_request */
8936 0, /* allocation_size */
8937 0, /* private_flags */
8942 posx, /* in_context_blobs */
8943 NULL); /* out_context_blobs */
8947 if (!NT_STATUS_IS_OK(status)) {
8952 * Don't lie to client. If we can't really delete due to
8953 * non-POSIX opens return SHARING_VIOLATION.
8956 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8958 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8959 "lock for file %s\n", fsp_str_dbg(fsp)));
8960 close_file(req, fsp, NORMAL_CLOSE);
8961 return NT_STATUS_INVALID_PARAMETER;
8964 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8965 if (other_nonposix_opens) {
8966 /* Fail with sharing violation. */
8968 close_file(req, fsp, NORMAL_CLOSE);
8969 return NT_STATUS_SHARING_VIOLATION;
8973 * Set the delete on close.
8975 status = smb_set_file_disposition_info(conn,
8983 if (!NT_STATUS_IS_OK(status)) {
8984 close_file(req, fsp, NORMAL_CLOSE);
8987 return close_file(req, fsp, NORMAL_CLOSE);
8990 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8991 struct smb_request *req,
8992 TALLOC_CTX *mem_ctx,
8993 uint16_t info_level,
8995 struct smb_filename *smb_fname,
8996 char **ppdata, int total_data,
8999 char *pdata = *ppdata;
9000 NTSTATUS status = NT_STATUS_OK;
9001 int data_return_size = 0;
9005 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
9006 return NT_STATUS_INVALID_LEVEL;
9009 if (!CAN_WRITE(conn)) {
9010 /* Allow POSIX opens. The open path will deny
9011 * any non-readonly opens. */
9012 if (info_level != SMB_POSIX_PATH_OPEN) {
9013 return NT_STATUS_DOS(ERRSRV, ERRaccess);
9017 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9018 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9020 info_level, total_data));
9022 switch (info_level) {
9024 case SMB_INFO_STANDARD:
9026 status = smb_set_info_standard(conn,
9034 case SMB_INFO_SET_EA:
9036 status = smb_info_set_ea(conn,
9044 case SMB_SET_FILE_BASIC_INFO:
9045 case SMB_FILE_BASIC_INFORMATION:
9047 status = smb_set_file_basic_info(conn,
9055 case SMB_FILE_ALLOCATION_INFORMATION:
9056 case SMB_SET_FILE_ALLOCATION_INFO:
9058 status = smb_set_file_allocation_info(conn, req,
9066 case SMB_FILE_END_OF_FILE_INFORMATION:
9067 case SMB_SET_FILE_END_OF_FILE_INFO:
9070 * XP/Win7 both fail after the createfile with
9071 * SMB_SET_FILE_END_OF_FILE_INFO but not
9072 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9073 * The level is known here, so pass it down
9077 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9079 status = smb_set_file_end_of_file_info(conn, req,
9088 case SMB_FILE_DISPOSITION_INFORMATION:
9089 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9092 /* JRA - We used to just ignore this on a path ?
9093 * Shouldn't this be invalid level on a pathname
9096 if (tran_call != TRANSACT2_SETFILEINFO) {
9097 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9100 status = smb_set_file_disposition_info(conn,
9108 case SMB_FILE_POSITION_INFORMATION:
9110 status = smb_file_position_information(conn,
9117 case SMB_FILE_FULL_EA_INFORMATION:
9119 status = smb_set_file_full_ea_info(conn,
9126 /* From tridge Samba4 :
9127 * MODE_INFORMATION in setfileinfo (I have no
9128 * idea what "mode information" on a file is - it takes a value of 0,
9129 * 2, 4 or 6. What could it be?).
9132 case SMB_FILE_MODE_INFORMATION:
9134 status = smb_file_mode_information(conn,
9140 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9141 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9142 case SMB_FILE_SHORT_NAME_INFORMATION:
9143 return NT_STATUS_NOT_SUPPORTED;
9146 * CIFS UNIX extensions.
9149 case SMB_SET_FILE_UNIX_BASIC:
9151 status = smb_set_file_unix_basic(conn, req,
9159 case SMB_SET_FILE_UNIX_INFO2:
9161 status = smb_set_file_unix_info2(conn, req,
9169 case SMB_SET_FILE_UNIX_LINK:
9172 /* We must have a pathname for this. */
9173 return NT_STATUS_INVALID_LEVEL;
9175 status = smb_set_file_unix_link(conn, req, pdata,
9176 total_data, smb_fname);
9180 case SMB_SET_FILE_UNIX_HLINK:
9183 /* We must have a pathname for this. */
9184 return NT_STATUS_INVALID_LEVEL;
9186 status = smb_set_file_unix_hlink(conn, req,
9192 case SMB_FILE_RENAME_INFORMATION:
9194 status = smb_file_rename_information(conn, req,
9200 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9202 /* SMB2 rename information. */
9203 status = smb2_file_rename_information(conn, req,
9209 case SMB_FILE_LINK_INFORMATION:
9211 status = smb_file_link_information(conn, req,
9217 #if defined(HAVE_POSIX_ACLS)
9218 case SMB_SET_POSIX_ACL:
9220 status = smb_set_posix_acl(conn,
9230 case SMB_SET_POSIX_LOCK:
9233 return NT_STATUS_INVALID_LEVEL;
9235 status = smb_set_posix_lock(conn, req,
9236 pdata, total_data, fsp);
9240 case SMB_POSIX_PATH_OPEN:
9243 /* We must have a pathname for this. */
9244 return NT_STATUS_INVALID_LEVEL;
9247 status = smb_posix_open(conn, req,
9255 case SMB_POSIX_PATH_UNLINK:
9258 /* We must have a pathname for this. */
9259 return NT_STATUS_INVALID_LEVEL;
9262 status = smb_posix_unlink(conn, req,
9270 return NT_STATUS_INVALID_LEVEL;
9273 if (!NT_STATUS_IS_OK(status)) {
9277 *ret_data_size = data_return_size;
9278 return NT_STATUS_OK;
9281 /****************************************************************************
9282 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9283 ****************************************************************************/
9285 static void call_trans2setfilepathinfo(connection_struct *conn,
9286 struct smb_request *req,
9287 unsigned int tran_call,
9288 char **pparams, int total_params,
9289 char **ppdata, int total_data,
9290 unsigned int max_data_bytes)
9292 char *params = *pparams;
9293 char *pdata = *ppdata;
9294 uint16_t info_level;
9295 struct smb_filename *smb_fname = NULL;
9296 files_struct *fsp = NULL;
9297 NTSTATUS status = NT_STATUS_OK;
9298 int data_return_size = 0;
9301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9305 if (tran_call == TRANSACT2_SETFILEINFO) {
9306 if (total_params < 4) {
9307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9311 fsp = file_fsp(req, SVAL(params,0));
9312 /* Basic check for non-null fsp. */
9313 if (!check_fsp_open(conn, req, fsp)) {
9316 info_level = SVAL(params,2);
9318 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9319 if (smb_fname == NULL) {
9320 reply_nterror(req, NT_STATUS_NO_MEMORY);
9324 if(fsp->fh->fd == -1) {
9326 * This is actually a SETFILEINFO on a directory
9327 * handle (returned from an NT SMB). NT5.0 seems
9328 * to do this call. JRA.
9330 if (INFO_LEVEL_IS_UNIX(info_level)) {
9331 /* Always do lstat for UNIX calls. */
9332 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9333 DEBUG(3,("call_trans2setfilepathinfo: "
9334 "SMB_VFS_LSTAT of %s failed "
9336 smb_fname_str_dbg(smb_fname),
9338 reply_nterror(req, map_nt_error_from_unix(errno));
9342 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9343 DEBUG(3,("call_trans2setfilepathinfo: "
9344 "fileinfo of %s failed (%s)\n",
9345 smb_fname_str_dbg(smb_fname),
9347 reply_nterror(req, map_nt_error_from_unix(errno));
9351 } else if (fsp->print_file) {
9353 * Doing a DELETE_ON_CLOSE should cancel a print job.
9355 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9356 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9358 DEBUG(3,("call_trans2setfilepathinfo: "
9359 "Cancelling print job (%s)\n",
9363 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9369 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9374 * Original code - this is an open file.
9376 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9377 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9378 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9380 reply_nterror(req, map_nt_error_from_unix(errno));
9386 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9389 if (total_params < 7) {
9390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9394 info_level = SVAL(params,0);
9395 if (req->posix_pathnames) {
9396 srvstr_get_path_posix(req,
9405 srvstr_get_path(req,
9414 if (!NT_STATUS_IS_OK(status)) {
9415 reply_nterror(req, status);
9419 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9420 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9421 info_level == SMB_FILE_RENAME_INFORMATION ||
9422 info_level == SMB_POSIX_PATH_OPEN ||
9423 info_level == SMB_POSIX_PATH_UNLINK) {
9424 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9427 status = filename_convert(req, conn,
9433 if (!NT_STATUS_IS_OK(status)) {
9434 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9435 reply_botherror(req,
9436 NT_STATUS_PATH_NOT_COVERED,
9437 ERRSRV, ERRbadpath);
9440 reply_nterror(req, status);
9444 if (INFO_LEVEL_IS_UNIX(info_level)) {
9446 * For CIFS UNIX extensions the target name may not exist.
9449 /* Always do lstat for UNIX calls. */
9450 SMB_VFS_LSTAT(conn, smb_fname);
9452 } else if (!VALID_STAT(smb_fname->st) &&
9453 SMB_VFS_STAT(conn, smb_fname)) {
9454 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9456 smb_fname_str_dbg(smb_fname),
9458 reply_nterror(req, map_nt_error_from_unix(errno));
9463 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9464 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9466 info_level,total_data));
9468 /* Realloc the parameter size */
9469 *pparams = (char *)SMB_REALLOC(*pparams,2);
9470 if (*pparams == NULL) {
9471 reply_nterror(req, NT_STATUS_NO_MEMORY);
9478 status = smbd_do_setfilepathinfo(conn, req, req,
9484 if (!NT_STATUS_IS_OK(status)) {
9485 if (open_was_deferred(req->xconn, req->mid)) {
9486 /* We have re-scheduled this call. */
9489 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9490 bool ok = defer_smb1_sharing_violation(req);
9495 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9496 /* We have re-scheduled this call. */
9499 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9501 ERRSRV, ERRbadpath);
9504 if (info_level == SMB_POSIX_PATH_OPEN) {
9505 reply_openerror(req, status);
9510 * Invalid EA name needs to return 2 param bytes,
9511 * not a zero-length error packet.
9513 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9514 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9517 reply_nterror(req, status);
9522 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9528 /****************************************************************************
9529 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9530 ****************************************************************************/
9532 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9533 char **pparams, int total_params,
9534 char **ppdata, int total_data,
9535 unsigned int max_data_bytes)
9537 struct smb_filename *smb_dname = NULL;
9538 char *params = *pparams;
9539 char *pdata = *ppdata;
9540 char *directory = NULL;
9541 NTSTATUS status = NT_STATUS_OK;
9542 struct ea_list *ea_list = NULL;
9543 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9544 TALLOC_CTX *ctx = talloc_tos();
9546 if (!CAN_WRITE(conn)) {
9547 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9551 if (total_params < 5) {
9552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9556 if (req->posix_pathnames) {
9557 srvstr_get_path_posix(ctx,
9566 srvstr_get_path(ctx,
9575 if (!NT_STATUS_IS_OK(status)) {
9576 reply_nterror(req, status);
9580 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9582 status = filename_convert(ctx,
9590 if (!NT_STATUS_IS_OK(status)) {
9591 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9592 reply_botherror(req,
9593 NT_STATUS_PATH_NOT_COVERED,
9594 ERRSRV, ERRbadpath);
9597 reply_nterror(req, status);
9602 * OS/2 workplace shell seems to send SET_EA requests of "null"
9603 * length (4 bytes containing IVAL 4).
9604 * They seem to have no effect. Bug #3212. JRA.
9607 if (total_data && (total_data != 4)) {
9608 /* Any data in this call is an EA list. */
9609 if (total_data < 10) {
9610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9614 if (IVAL(pdata,0) > total_data) {
9615 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9616 IVAL(pdata,0), (unsigned int)total_data));
9617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9621 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9628 if (!lp_ea_support(SNUM(conn))) {
9629 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9633 /* If total_data == 4 Windows doesn't care what values
9634 * are placed in that field, it just ignores them.
9635 * The System i QNTC IBM SMB client puts bad values here,
9636 * so ignore them. */
9638 status = create_directory(conn, req, smb_dname);
9640 if (!NT_STATUS_IS_OK(status)) {
9641 reply_nterror(req, status);
9645 /* Try and set any given EA. */
9647 status = set_ea(conn, NULL, smb_dname, ea_list);
9648 if (!NT_STATUS_IS_OK(status)) {
9649 reply_nterror(req, status);
9654 /* Realloc the parameter and data sizes */
9655 *pparams = (char *)SMB_REALLOC(*pparams,2);
9656 if(*pparams == NULL) {
9657 reply_nterror(req, NT_STATUS_NO_MEMORY);
9664 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9667 TALLOC_FREE(smb_dname);
9671 /****************************************************************************
9672 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9673 We don't actually do this - we just send a null response.
9674 ****************************************************************************/
9676 static void call_trans2findnotifyfirst(connection_struct *conn,
9677 struct smb_request *req,
9678 char **pparams, int total_params,
9679 char **ppdata, int total_data,
9680 unsigned int max_data_bytes)
9682 char *params = *pparams;
9683 uint16_t info_level;
9685 if (total_params < 6) {
9686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9690 info_level = SVAL(params,4);
9691 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9693 switch (info_level) {
9698 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9702 /* Realloc the parameter and data sizes */
9703 *pparams = (char *)SMB_REALLOC(*pparams,6);
9704 if (*pparams == NULL) {
9705 reply_nterror(req, NT_STATUS_NO_MEMORY);
9710 SSVAL(params,0,fnf_handle);
9711 SSVAL(params,2,0); /* No changes */
9712 SSVAL(params,4,0); /* No EA errors */
9719 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9724 /****************************************************************************
9725 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9726 changes). Currently this does nothing.
9727 ****************************************************************************/
9729 static void call_trans2findnotifynext(connection_struct *conn,
9730 struct smb_request *req,
9731 char **pparams, int total_params,
9732 char **ppdata, int total_data,
9733 unsigned int max_data_bytes)
9735 char *params = *pparams;
9737 DEBUG(3,("call_trans2findnotifynext\n"));
9739 /* Realloc the parameter and data sizes */
9740 *pparams = (char *)SMB_REALLOC(*pparams,4);
9741 if (*pparams == NULL) {
9742 reply_nterror(req, NT_STATUS_NO_MEMORY);
9747 SSVAL(params,0,0); /* No changes */
9748 SSVAL(params,2,0); /* No EA errors */
9750 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9755 /****************************************************************************
9756 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9757 ****************************************************************************/
9759 static void call_trans2getdfsreferral(connection_struct *conn,
9760 struct smb_request *req,
9761 char **pparams, int total_params,
9762 char **ppdata, int total_data,
9763 unsigned int max_data_bytes)
9765 char *params = *pparams;
9766 char *pathname = NULL;
9768 int max_referral_level;
9769 NTSTATUS status = NT_STATUS_OK;
9770 TALLOC_CTX *ctx = talloc_tos();
9772 DEBUG(10,("call_trans2getdfsreferral\n"));
9774 if (total_params < 3) {
9775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9779 max_referral_level = SVAL(params,0);
9781 if(!lp_host_msdfs()) {
9782 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9786 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9787 total_params - 2, STR_TERMINATE);
9789 reply_nterror(req, NT_STATUS_NOT_FOUND);
9792 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9793 ppdata,&status)) < 0) {
9794 reply_nterror(req, status);
9798 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9799 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9800 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9805 #define LMCAT_SPL 0x53
9806 #define LMFUNC_GETJOBID 0x60
9808 /****************************************************************************
9809 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9810 ****************************************************************************/
9812 static void call_trans2ioctl(connection_struct *conn,
9813 struct smb_request *req,
9814 char **pparams, int total_params,
9815 char **ppdata, int total_data,
9816 unsigned int max_data_bytes)
9818 const struct loadparm_substitution *lp_sub =
9819 loadparm_s3_global_substitution();
9820 char *pdata = *ppdata;
9821 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9825 /* check for an invalid fid before proceeding */
9828 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9832 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9833 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9834 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9835 if (*ppdata == NULL) {
9836 reply_nterror(req, NT_STATUS_NO_MEMORY);
9841 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9842 CAN ACCEPT THIS IN UNICODE. JRA. */
9845 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9847 status = srvstr_push(pdata, req->flags2, pdata + 2,
9848 lp_netbios_name(), 15,
9849 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9850 if (!NT_STATUS_IS_OK(status)) {
9851 reply_nterror(req, status);
9854 status = srvstr_push(pdata, req->flags2, pdata+18,
9855 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9856 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9857 if (!NT_STATUS_IS_OK(status)) {
9858 reply_nterror(req, status);
9861 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9866 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9867 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9870 /****************************************************************************
9871 Reply to a SMBfindclose (stop trans2 directory search).
9872 ****************************************************************************/
9874 void reply_findclose(struct smb_request *req)
9877 struct smbd_server_connection *sconn = req->sconn;
9878 files_struct *fsp = NULL;
9880 START_PROFILE(SMBfindclose);
9883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9884 END_PROFILE(SMBfindclose);
9888 dptr_num = SVALS(req->vwv+0, 0);
9890 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9893 * OS/2 seems to use -1 to indicate "close all directories"
9894 * This has to mean on this specific connection struct.
9896 if (dptr_num == -1) {
9897 dptr_closecnum(req->conn);
9899 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9902 close_file(NULL, fsp, NORMAL_CLOSE);
9907 reply_outbuf(req, 0, 0);
9909 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9911 END_PROFILE(SMBfindclose);
9915 /****************************************************************************
9916 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9917 ****************************************************************************/
9919 void reply_findnclose(struct smb_request *req)
9923 START_PROFILE(SMBfindnclose);
9926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9927 END_PROFILE(SMBfindnclose);
9931 dptr_num = SVAL(req->vwv+0, 0);
9933 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9935 /* We never give out valid handles for a
9936 findnotifyfirst - so any dptr_num is ok here.
9939 reply_outbuf(req, 0, 0);
9941 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9943 END_PROFILE(SMBfindnclose);
9947 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9948 struct trans_state *state)
9950 if (get_Protocol() >= PROTOCOL_NT1) {
9951 req->flags2 |= 0x40; /* IS_LONG_NAME */
9952 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9955 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9956 if (state->call != TRANSACT2_QFSINFO &&
9957 state->call != TRANSACT2_SETFSINFO) {
9958 DEBUG(0,("handle_trans2: encryption required "
9960 (unsigned int)state->call));
9961 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9966 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9968 /* Now we must call the relevant TRANS2 function */
9969 switch(state->call) {
9970 case TRANSACT2_OPEN:
9972 START_PROFILE(Trans2_open);
9973 call_trans2open(conn, req,
9974 &state->param, state->total_param,
9975 &state->data, state->total_data,
9976 state->max_data_return);
9977 END_PROFILE(Trans2_open);
9981 case TRANSACT2_FINDFIRST:
9983 START_PROFILE(Trans2_findfirst);
9984 call_trans2findfirst(conn, req,
9985 &state->param, state->total_param,
9986 &state->data, state->total_data,
9987 state->max_data_return);
9988 END_PROFILE(Trans2_findfirst);
9992 case TRANSACT2_FINDNEXT:
9994 START_PROFILE(Trans2_findnext);
9995 call_trans2findnext(conn, req,
9996 &state->param, state->total_param,
9997 &state->data, state->total_data,
9998 state->max_data_return);
9999 END_PROFILE(Trans2_findnext);
10003 case TRANSACT2_QFSINFO:
10005 START_PROFILE(Trans2_qfsinfo);
10006 call_trans2qfsinfo(conn, req,
10007 &state->param, state->total_param,
10008 &state->data, state->total_data,
10009 state->max_data_return);
10010 END_PROFILE(Trans2_qfsinfo);
10014 case TRANSACT2_SETFSINFO:
10016 START_PROFILE(Trans2_setfsinfo);
10017 call_trans2setfsinfo(conn, req,
10018 &state->param, state->total_param,
10019 &state->data, state->total_data,
10020 state->max_data_return);
10021 END_PROFILE(Trans2_setfsinfo);
10025 case TRANSACT2_QPATHINFO:
10026 case TRANSACT2_QFILEINFO:
10028 START_PROFILE(Trans2_qpathinfo);
10029 call_trans2qfilepathinfo(conn, req, state->call,
10030 &state->param, state->total_param,
10031 &state->data, state->total_data,
10032 state->max_data_return);
10033 END_PROFILE(Trans2_qpathinfo);
10037 case TRANSACT2_SETPATHINFO:
10038 case TRANSACT2_SETFILEINFO:
10040 START_PROFILE(Trans2_setpathinfo);
10041 call_trans2setfilepathinfo(conn, req, state->call,
10042 &state->param, state->total_param,
10043 &state->data, state->total_data,
10044 state->max_data_return);
10045 END_PROFILE(Trans2_setpathinfo);
10049 case TRANSACT2_FINDNOTIFYFIRST:
10051 START_PROFILE(Trans2_findnotifyfirst);
10052 call_trans2findnotifyfirst(conn, req,
10053 &state->param, state->total_param,
10054 &state->data, state->total_data,
10055 state->max_data_return);
10056 END_PROFILE(Trans2_findnotifyfirst);
10060 case TRANSACT2_FINDNOTIFYNEXT:
10062 START_PROFILE(Trans2_findnotifynext);
10063 call_trans2findnotifynext(conn, req,
10064 &state->param, state->total_param,
10065 &state->data, state->total_data,
10066 state->max_data_return);
10067 END_PROFILE(Trans2_findnotifynext);
10071 case TRANSACT2_MKDIR:
10073 START_PROFILE(Trans2_mkdir);
10074 call_trans2mkdir(conn, req,
10075 &state->param, state->total_param,
10076 &state->data, state->total_data,
10077 state->max_data_return);
10078 END_PROFILE(Trans2_mkdir);
10082 case TRANSACT2_GET_DFS_REFERRAL:
10084 START_PROFILE(Trans2_get_dfs_referral);
10085 call_trans2getdfsreferral(conn, req,
10086 &state->param, state->total_param,
10087 &state->data, state->total_data,
10088 state->max_data_return);
10089 END_PROFILE(Trans2_get_dfs_referral);
10093 case TRANSACT2_IOCTL:
10095 START_PROFILE(Trans2_ioctl);
10096 call_trans2ioctl(conn, req,
10097 &state->param, state->total_param,
10098 &state->data, state->total_data,
10099 state->max_data_return);
10100 END_PROFILE(Trans2_ioctl);
10105 /* Error in request */
10106 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10107 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10111 /****************************************************************************
10112 Reply to a SMBtrans2.
10113 ****************************************************************************/
10115 void reply_trans2(struct smb_request *req)
10117 connection_struct *conn = req->conn;
10118 unsigned int dsoff;
10119 unsigned int dscnt;
10120 unsigned int psoff;
10121 unsigned int pscnt;
10122 unsigned int tran_call;
10123 struct trans_state *state;
10126 START_PROFILE(SMBtrans2);
10128 if (req->wct < 14) {
10129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10130 END_PROFILE(SMBtrans2);
10134 dsoff = SVAL(req->vwv+12, 0);
10135 dscnt = SVAL(req->vwv+11, 0);
10136 psoff = SVAL(req->vwv+10, 0);
10137 pscnt = SVAL(req->vwv+9, 0);
10138 tran_call = SVAL(req->vwv+14, 0);
10140 result = allow_new_trans(conn->pending_trans, req->mid);
10141 if (!NT_STATUS_IS_OK(result)) {
10142 DEBUG(2, ("Got invalid trans2 request: %s\n",
10143 nt_errstr(result)));
10144 reply_nterror(req, result);
10145 END_PROFILE(SMBtrans2);
10149 if (IS_IPC(conn)) {
10150 switch (tran_call) {
10151 /* List the allowed trans2 calls on IPC$ */
10152 case TRANSACT2_OPEN:
10153 case TRANSACT2_GET_DFS_REFERRAL:
10154 case TRANSACT2_QFILEINFO:
10155 case TRANSACT2_QFSINFO:
10156 case TRANSACT2_SETFSINFO:
10159 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10160 END_PROFILE(SMBtrans2);
10165 if ((state = talloc(conn, struct trans_state)) == NULL) {
10166 DEBUG(0, ("talloc failed\n"));
10167 reply_nterror(req, NT_STATUS_NO_MEMORY);
10168 END_PROFILE(SMBtrans2);
10172 state->cmd = SMBtrans2;
10174 state->mid = req->mid;
10175 state->vuid = req->vuid;
10176 state->setup_count = SVAL(req->vwv+13, 0);
10177 state->setup = NULL;
10178 state->total_param = SVAL(req->vwv+0, 0);
10179 state->param = NULL;
10180 state->total_data = SVAL(req->vwv+1, 0);
10181 state->data = NULL;
10182 state->max_param_return = SVAL(req->vwv+2, 0);
10183 state->max_data_return = SVAL(req->vwv+3, 0);
10184 state->max_setup_return = SVAL(req->vwv+4, 0);
10185 state->close_on_completion = BITSETW(req->vwv+5, 0);
10186 state->one_way = BITSETW(req->vwv+5, 1);
10188 state->call = tran_call;
10190 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10191 is so as a sanity check */
10192 if (state->setup_count != 1) {
10194 * Need to have rc=0 for ioctl to get job id for OS/2.
10195 * Network printing will fail if function is not successful.
10196 * Similar function in reply.c will be used if protocol
10197 * is LANMAN1.0 instead of LM1.2X002.
10198 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10199 * outbuf doesn't have to be set(only job id is used).
10201 if ( (state->setup_count == 4)
10202 && (tran_call == TRANSACT2_IOCTL)
10203 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10204 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10205 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10207 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10208 DEBUG(2,("Transaction is %d\n",tran_call));
10209 TALLOC_FREE(state);
10210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10211 END_PROFILE(SMBtrans2);
10216 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10219 if (state->total_data) {
10221 if (trans_oob(state->total_data, 0, dscnt)
10222 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10226 /* Can't use talloc here, the core routines do realloc on the
10227 * params and data. */
10228 state->data = (char *)SMB_MALLOC(state->total_data);
10229 if (state->data == NULL) {
10230 DEBUG(0,("reply_trans2: data malloc fail for %u "
10231 "bytes !\n", (unsigned int)state->total_data));
10232 TALLOC_FREE(state);
10233 reply_nterror(req, NT_STATUS_NO_MEMORY);
10234 END_PROFILE(SMBtrans2);
10238 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10241 if (state->total_param) {
10243 if (trans_oob(state->total_param, 0, pscnt)
10244 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10248 /* Can't use talloc here, the core routines do realloc on the
10249 * params and data. */
10250 state->param = (char *)SMB_MALLOC(state->total_param);
10251 if (state->param == NULL) {
10252 DEBUG(0,("reply_trans: param malloc fail for %u "
10253 "bytes !\n", (unsigned int)state->total_param));
10254 SAFE_FREE(state->data);
10255 TALLOC_FREE(state);
10256 reply_nterror(req, NT_STATUS_NO_MEMORY);
10257 END_PROFILE(SMBtrans2);
10261 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10264 state->received_data = dscnt;
10265 state->received_param = pscnt;
10267 if ((state->received_param == state->total_param) &&
10268 (state->received_data == state->total_data)) {
10270 handle_trans2(conn, req, state);
10272 SAFE_FREE(state->data);
10273 SAFE_FREE(state->param);
10274 TALLOC_FREE(state);
10275 END_PROFILE(SMBtrans2);
10279 DLIST_ADD(conn->pending_trans, state);
10281 /* We need to send an interim response then receive the rest
10282 of the parameter/data bytes */
10283 reply_outbuf(req, 0, 0);
10284 show_msg((char *)req->outbuf);
10285 END_PROFILE(SMBtrans2);
10290 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10291 SAFE_FREE(state->data);
10292 SAFE_FREE(state->param);
10293 TALLOC_FREE(state);
10294 END_PROFILE(SMBtrans2);
10295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10299 /****************************************************************************
10300 Reply to a SMBtranss2
10301 ****************************************************************************/
10303 void reply_transs2(struct smb_request *req)
10305 connection_struct *conn = req->conn;
10306 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10307 struct trans_state *state;
10309 START_PROFILE(SMBtranss2);
10311 show_msg((const char *)req->inbuf);
10313 /* Windows clients expect all replies to
10314 a transact secondary (SMBtranss2 0x33)
10315 to have a command code of transact
10316 (SMBtrans2 0x32). See bug #8989
10317 and also [MS-CIFS] section 2.2.4.47.2
10320 req->cmd = SMBtrans2;
10322 if (req->wct < 8) {
10323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10324 END_PROFILE(SMBtranss2);
10328 for (state = conn->pending_trans; state != NULL;
10329 state = state->next) {
10330 if (state->mid == req->mid) {
10335 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10337 END_PROFILE(SMBtranss2);
10341 /* Revise state->total_param and state->total_data in case they have
10342 changed downwards */
10344 if (SVAL(req->vwv+0, 0) < state->total_param)
10345 state->total_param = SVAL(req->vwv+0, 0);
10346 if (SVAL(req->vwv+1, 0) < state->total_data)
10347 state->total_data = SVAL(req->vwv+1, 0);
10349 pcnt = SVAL(req->vwv+2, 0);
10350 poff = SVAL(req->vwv+3, 0);
10351 pdisp = SVAL(req->vwv+4, 0);
10353 dcnt = SVAL(req->vwv+5, 0);
10354 doff = SVAL(req->vwv+6, 0);
10355 ddisp = SVAL(req->vwv+7, 0);
10357 state->received_param += pcnt;
10358 state->received_data += dcnt;
10360 if ((state->received_data > state->total_data) ||
10361 (state->received_param > state->total_param))
10365 if (trans_oob(state->total_param, pdisp, pcnt)
10366 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10369 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10373 if (trans_oob(state->total_data, ddisp, dcnt)
10374 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10377 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10380 if ((state->received_param < state->total_param) ||
10381 (state->received_data < state->total_data)) {
10382 END_PROFILE(SMBtranss2);
10386 handle_trans2(conn, req, state);
10388 DLIST_REMOVE(conn->pending_trans, state);
10389 SAFE_FREE(state->data);
10390 SAFE_FREE(state->param);
10391 TALLOC_FREE(state);
10393 END_PROFILE(SMBtranss2);
10398 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10399 DLIST_REMOVE(conn->pending_trans, state);
10400 SAFE_FREE(state->data);
10401 SAFE_FREE(state->param);
10402 TALLOC_FREE(state);
10403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10404 END_PROFILE(SMBtranss2);