2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct *conn,
54 const SMB_STRUCT_STAT *psbuf);
56 static char *store_file_unix_basic_info2(connection_struct *conn,
59 const SMB_STRUCT_STAT *psbuf);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS refuse_symlink(connection_struct *conn,
66 const files_struct *fsp,
67 const struct smb_filename *smb_fname)
70 const SMB_STRUCT_STAT *pst = NULL;
73 pst = &fsp->fsp_name->st;
78 if (!VALID_STAT(*pst)) {
79 int ret = vfs_stat_smb_basename(conn,
82 if (ret == -1 && errno != ENOENT) {
83 return map_nt_error_from_unix(errno);
84 } else if (ret == -1) {
85 /* it's not a symlink.. */
91 if (S_ISLNK(pst->st_ex_mode)) {
92 return NT_STATUS_ACCESS_DENIED;
97 NTSTATUS check_access_fsp(const struct files_struct *fsp,
100 if (!(fsp->access_mask & access_mask)) {
101 return NT_STATUS_ACCESS_DENIED;
106 #if defined(HAVE_POSIX_ACLS)
107 /****************************************************************************
108 Utility function to open a fsp for a POSIX handle operation.
109 ****************************************************************************/
111 static NTSTATUS get_posix_fsp(connection_struct *conn,
112 struct smb_request *req,
113 const struct smb_filename *smb_fname,
114 uint32_t access_mask,
115 files_struct **ret_fsp)
118 struct smb_filename *smb_fname_tmp = NULL;
119 uint32_t create_disposition = FILE_OPEN;
120 uint32_t share_access = FILE_SHARE_READ|
123 struct smb2_create_blobs *posx = NULL;
126 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
127 * but set reasonable defaults.
129 uint32_t file_attributes = 0664;
130 uint32_t oplock = NO_OPLOCK;
131 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
133 /* File or directory must exist. */
134 if (!VALID_STAT(smb_fname->st)) {
135 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
137 /* Cannot be a symlink. */
138 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
139 return NT_STATUS_ACCESS_DENIED;
141 /* Set options correctly for directory open. */
142 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
144 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
145 * directories, but set reasonable defaults.
147 file_attributes = 0775;
148 create_options = FILE_DIRECTORY_FILE;
151 /* Createfile uses a non-const smb_fname. */
152 smb_fname_tmp = cp_smb_filename(talloc_tos(),
154 if (smb_fname_tmp == NULL) {
155 status = NT_STATUS_NO_MEMORY;
159 status = make_smb2_posix_create_ctx(
160 talloc_tos(), &posx, file_attributes);
161 if (!NT_STATUS_IS_OK(status)) {
162 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
167 status = SMB_VFS_CREATE_FILE(
170 smb_fname_tmp, /* fname */
171 access_mask, /* access_mask */
172 share_access, /* share_access */
173 create_disposition,/* create_disposition*/
174 create_options, /* create_options */
175 file_attributes,/* file_attributes */
176 oplock, /* oplock_request */
178 0, /* allocation_size */
179 0, /* private_flags */
182 ret_fsp, /* result */
184 posx, /* in_context */
185 NULL); /* out_context */
189 TALLOC_FREE(smb_fname_tmp);
194 /********************************************************************
195 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,
1368 if (!NT_STATUS_IS_OK(status)) {
1369 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1370 reply_botherror(req,
1371 NT_STATUS_PATH_NOT_COVERED,
1372 ERRSRV, ERRbadpath);
1375 reply_nterror(req, status);
1379 if (open_ofun == 0) {
1380 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1384 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1386 &access_mask, &share_mode,
1387 &create_disposition,
1390 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1394 /* Any data in this call is an EA list. */
1395 if (total_data && (total_data != 4)) {
1396 if (total_data < 10) {
1397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1401 if (IVAL(pdata,0) > total_data) {
1402 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1403 IVAL(pdata,0), (unsigned int)total_data));
1404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1408 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1415 if (!lp_ea_support(SNUM(conn))) {
1416 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1420 if (!req->posix_pathnames &&
1421 ea_list_has_invalid_name(ea_list)) {
1423 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1424 if(*pparams == NULL ) {
1425 reply_nterror(req, NT_STATUS_NO_MEMORY);
1429 memset(params, '\0', param_len);
1430 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1431 params, param_len, NULL, 0, max_data_bytes);
1436 status = SMB_VFS_CREATE_FILE(
1439 smb_fname, /* fname */
1440 access_mask, /* access_mask */
1441 share_mode, /* share_access */
1442 create_disposition, /* create_disposition*/
1443 create_options, /* create_options */
1444 open_attr, /* file_attributes */
1445 oplock_request, /* oplock_request */
1447 open_size, /* allocation_size */
1450 ea_list, /* ea_list */
1452 &smb_action, /* psbuf */
1453 NULL, NULL); /* create context */
1455 if (!NT_STATUS_IS_OK(status)) {
1456 if (open_was_deferred(req->xconn, req->mid)) {
1457 /* We have re-scheduled this call. */
1461 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1462 reply_openerror(req, status);
1466 fsp = fcb_or_dos_open(
1473 bool ok = defer_smb1_sharing_violation(req);
1477 reply_openerror(req, status);
1481 smb_action = FILE_WAS_OPENED;
1484 size = get_file_size_stat(&smb_fname->st);
1485 fattr = dos_mode(conn, smb_fname);
1486 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1487 inode = smb_fname->st.st_ex_ino;
1488 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1489 close_file(req, fsp, ERROR_CLOSE);
1490 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1494 /* Realloc the size of parameters and data we will return */
1495 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1496 if(*pparams == NULL ) {
1497 reply_nterror(req, NT_STATUS_NO_MEMORY);
1502 SSVAL(params,0,fsp->fnum);
1503 SSVAL(params,2,fattr);
1504 srv_put_dos_date2(params,4, mtime);
1505 SIVAL(params,8, (uint32_t)size);
1506 SSVAL(params,12,deny_mode);
1507 SSVAL(params,14,0); /* open_type - file or directory. */
1508 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1510 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1511 smb_action |= EXTENDED_OPLOCK_GRANTED;
1514 SSVAL(params,18,smb_action);
1517 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1519 SIVAL(params,20,inode);
1520 SSVAL(params,24,0); /* Padding. */
1522 uint32_t ea_size = estimate_ea_size(conn, fsp,
1524 SIVAL(params, 26, ea_size);
1526 SIVAL(params, 26, 0);
1529 /* Send the required number of replies */
1530 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1532 TALLOC_FREE(smb_fname);
1535 /*********************************************************
1536 Routine to check if a given string matches exactly.
1537 as a special case a mask of "." does NOT match. That
1538 is required for correct wildcard semantics
1539 Case can be significant or not.
1540 **********************************************************/
1542 static bool exact_match(bool has_wild,
1543 bool case_sensitive,
1547 if (mask[0] == '.' && mask[1] == 0) {
1555 if (case_sensitive) {
1556 return strcmp(str,mask)==0;
1558 return strcasecmp_m(str,mask) == 0;
1562 /****************************************************************************
1563 Return the filetype for UNIX extensions.
1564 ****************************************************************************/
1566 static uint32_t unix_filetype(mode_t mode)
1569 return UNIX_TYPE_FILE;
1570 else if(S_ISDIR(mode))
1571 return UNIX_TYPE_DIR;
1573 else if(S_ISLNK(mode))
1574 return UNIX_TYPE_SYMLINK;
1577 else if(S_ISCHR(mode))
1578 return UNIX_TYPE_CHARDEV;
1581 else if(S_ISBLK(mode))
1582 return UNIX_TYPE_BLKDEV;
1585 else if(S_ISFIFO(mode))
1586 return UNIX_TYPE_FIFO;
1589 else if(S_ISSOCK(mode))
1590 return UNIX_TYPE_SOCKET;
1593 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1594 return UNIX_TYPE_UNKNOWN;
1597 /****************************************************************************
1598 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1599 ****************************************************************************/
1601 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1602 const SMB_STRUCT_STAT *psbuf,
1604 enum perm_type ptype,
1609 if (perms == SMB_MODE_NO_CHANGE) {
1610 if (!VALID_STAT(*psbuf)) {
1611 return NT_STATUS_INVALID_PARAMETER;
1613 *ret_perms = psbuf->st_ex_mode;
1614 return NT_STATUS_OK;
1618 ret = wire_perms_to_unix(perms);
1620 if (ptype == PERM_NEW_FILE) {
1622 * "create mask"/"force create mode" are
1623 * only applied to new files, not existing ones.
1625 ret &= lp_create_mask(SNUM(conn));
1626 /* Add in force bits */
1627 ret |= lp_force_create_mode(SNUM(conn));
1628 } else if (ptype == PERM_NEW_DIR) {
1630 * "directory mask"/"force directory mode" are
1631 * only applied to new directories, not existing ones.
1633 ret &= lp_directory_mask(SNUM(conn));
1634 /* Add in force bits */
1635 ret |= lp_force_directory_mode(SNUM(conn));
1639 return NT_STATUS_OK;
1642 /****************************************************************************
1643 Needed to show the msdfs symlinks as directories. Modifies psbuf
1644 to be a directory if it's a msdfs link.
1645 ****************************************************************************/
1647 static bool check_msdfs_link(connection_struct *conn,
1648 struct smb_filename *smb_fname)
1650 int saved_errno = errno;
1651 if(lp_host_msdfs() &&
1652 lp_msdfs_root(SNUM(conn)) &&
1653 is_msdfs_link(conn, smb_fname)) {
1655 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1657 smb_fname->base_name));
1658 smb_fname->st.st_ex_mode =
1659 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1660 errno = saved_errno;
1663 errno = saved_errno;
1668 /****************************************************************************
1669 Get a level dependent lanman2 dir entry.
1670 ****************************************************************************/
1672 struct smbd_dirptr_lanman2_state {
1673 connection_struct *conn;
1674 uint32_t info_level;
1675 bool check_mangled_names;
1677 bool got_exact_match;
1680 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1686 struct smbd_dirptr_lanman2_state *state =
1687 (struct smbd_dirptr_lanman2_state *)private_data;
1689 char mangled_name[13]; /* mangled 8.3 name. */
1693 /* Mangle fname if it's an illegal name. */
1694 if (mangle_must_mangle(dname, state->conn->params)) {
1696 * Slow path - ensure we can push the original name as UCS2. If
1697 * not, then just don't return this name.
1701 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1702 uint8_t *tmp = talloc_array(talloc_tos(),
1706 status = srvstr_push(NULL,
1707 FLAGS2_UNICODE_STRINGS,
1716 if (!NT_STATUS_IS_OK(status)) {
1720 ok = name_to_8_3(dname, mangled_name,
1721 true, state->conn->params);
1725 fname = mangled_name;
1730 got_match = exact_match(state->has_wild,
1731 state->conn->case_sensitive,
1733 state->got_exact_match = got_match;
1735 got_match = mask_match(fname, mask,
1736 state->conn->case_sensitive);
1739 if(!got_match && state->check_mangled_names &&
1740 !mangle_is_8_3(fname, false, state->conn->params)) {
1742 * It turns out that NT matches wildcards against
1743 * both long *and* short names. This may explain some
1744 * of the wildcard wierdness from old DOS clients
1745 * that some people have been seeing.... JRA.
1747 /* Force the mangling into 8.3. */
1748 ok = name_to_8_3(fname, mangled_name,
1749 false, state->conn->params);
1754 got_match = exact_match(state->has_wild,
1755 state->conn->case_sensitive,
1756 mangled_name, mask);
1757 state->got_exact_match = got_match;
1759 got_match = mask_match(mangled_name, mask,
1760 state->conn->case_sensitive);
1768 *_fname = talloc_strdup(ctx, fname);
1769 if (*_fname == NULL) {
1776 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1778 struct smb_filename *smb_fname,
1782 struct smbd_dirptr_lanman2_state *state =
1783 (struct smbd_dirptr_lanman2_state *)private_data;
1784 bool ms_dfs_link = false;
1787 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1788 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1789 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1790 "Couldn't lstat [%s] (%s)\n",
1791 smb_fname_str_dbg(smb_fname),
1795 } else if (!VALID_STAT(smb_fname->st) &&
1796 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1797 /* Needed to show the msdfs symlinks as
1800 ms_dfs_link = check_msdfs_link(state->conn,
1803 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1804 "Couldn't stat [%s] (%s)\n",
1805 smb_fname_str_dbg(smb_fname),
1812 mode = dos_mode_msdfs(state->conn, smb_fname);
1813 } else if (get_dosmode) {
1814 mode = dos_mode(state->conn, smb_fname);
1821 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1822 connection_struct *conn,
1824 uint32_t info_level,
1825 struct ea_list *name_list,
1826 bool check_mangled_names,
1827 bool requires_resume_key,
1830 const struct smb_filename *smb_fname,
1831 int space_remaining,
1837 uint64_t *last_entry_off)
1839 char *p, *q, *pdata = *ppdata;
1841 uint64_t file_size = 0;
1842 uint64_t allocation_size = 0;
1843 uint64_t file_id = 0;
1845 struct timespec mdate_ts = {0};
1846 struct timespec adate_ts = {0};
1847 struct timespec cdate_ts = {0};
1848 struct timespec create_date_ts = {0};
1849 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1851 char *last_entry_ptr;
1856 struct readdir_attr_data *readdir_attr_data = NULL;
1858 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1859 file_size = get_file_size_stat(&smb_fname->st);
1861 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1863 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1870 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1872 mdate_ts = smb_fname->st.st_ex_mtime;
1873 adate_ts = smb_fname->st.st_ex_atime;
1874 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1875 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1877 if (lp_dos_filetime_resolution(SNUM(conn))) {
1878 dos_filetime_timespec(&create_date_ts);
1879 dos_filetime_timespec(&mdate_ts);
1880 dos_filetime_timespec(&adate_ts);
1881 dos_filetime_timespec(&cdate_ts);
1884 create_date = convert_timespec_to_time_t(create_date_ts);
1885 mdate = convert_timespec_to_time_t(mdate_ts);
1886 adate = convert_timespec_to_time_t(adate_ts);
1888 /* align the record */
1889 SMB_ASSERT(align >= 1);
1891 off = (int)PTR_DIFF(pdata, base_data);
1892 pad = (off + (align-1)) & ~(align-1);
1895 if (pad && pad > space_remaining) {
1896 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1897 "for padding (wanted %u, had %d)\n",
1900 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1904 /* initialize padding to 0 */
1906 memset(pdata, 0, pad);
1908 space_remaining -= pad;
1910 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1920 switch (info_level) {
1921 case SMB_FIND_INFO_STANDARD:
1922 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1923 if(requires_resume_key) {
1927 srv_put_dos_date2(p,0,create_date);
1928 srv_put_dos_date2(p,4,adate);
1929 srv_put_dos_date2(p,8,mdate);
1930 SIVAL(p,12,(uint32_t)file_size);
1931 SIVAL(p,16,(uint32_t)allocation_size);
1935 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1936 p += ucs2_align(base_data, p, 0);
1938 status = srvstr_push(base_data, flags2, p,
1939 fname, PTR_DIFF(end_data, p),
1940 STR_TERMINATE, &len);
1941 if (!NT_STATUS_IS_OK(status)) {
1944 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1946 SCVAL(nameptr, -1, len - 2);
1948 SCVAL(nameptr, -1, 0);
1952 SCVAL(nameptr, -1, len - 1);
1954 SCVAL(nameptr, -1, 0);
1960 case SMB_FIND_EA_SIZE:
1961 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1962 if (requires_resume_key) {
1966 srv_put_dos_date2(p,0,create_date);
1967 srv_put_dos_date2(p,4,adate);
1968 srv_put_dos_date2(p,8,mdate);
1969 SIVAL(p,12,(uint32_t)file_size);
1970 SIVAL(p,16,(uint32_t)allocation_size);
1973 unsigned int ea_size = estimate_ea_size(conn, NULL,
1975 SIVAL(p,22,ea_size); /* Extended attributes */
1979 status = srvstr_push(base_data, flags2,
1980 p, fname, PTR_DIFF(end_data, p),
1981 STR_TERMINATE | STR_NOALIGN, &len);
1982 if (!NT_STATUS_IS_OK(status)) {
1985 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1998 SCVAL(nameptr,0,len);
2000 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2003 case SMB_FIND_EA_LIST:
2005 struct ea_list *file_list = NULL;
2008 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2010 return NT_STATUS_INVALID_PARAMETER;
2012 if (requires_resume_key) {
2016 srv_put_dos_date2(p,0,create_date);
2017 srv_put_dos_date2(p,4,adate);
2018 srv_put_dos_date2(p,8,mdate);
2019 SIVAL(p,12,(uint32_t)file_size);
2020 SIVAL(p,16,(uint32_t)allocation_size);
2022 p += 22; /* p now points to the EA area. */
2024 status = get_ea_list_from_file(ctx, conn, NULL,
2026 &ea_len, &file_list);
2027 if (!NT_STATUS_IS_OK(status)) {
2030 name_list = ea_list_union(name_list, file_list, &ea_len);
2032 /* We need to determine if this entry will fit in the space available. */
2033 /* Max string size is 255 bytes. */
2034 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2035 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2036 "(wanted %u, had %d)\n",
2037 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2039 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2042 /* Push the ea_data followed by the name. */
2043 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2045 status = srvstr_push(base_data, flags2,
2046 p + 1, fname, PTR_DIFF(end_data, p+1),
2047 STR_TERMINATE | STR_NOALIGN, &len);
2048 if (!NT_STATUS_IS_OK(status)) {
2051 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2064 SCVAL(nameptr,0,len);
2066 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2070 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2071 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2072 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2074 SIVAL(p,0,reskey); p += 4;
2075 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2076 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2077 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2078 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2079 SOFF_T(p,0,file_size); p += 8;
2080 SOFF_T(p,0,allocation_size); p += 8;
2081 SIVAL(p,0,mode); p += 4;
2082 q = p; p += 4; /* q is placeholder for name length. */
2083 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2084 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2086 unsigned int ea_size = estimate_ea_size(conn, NULL,
2088 SIVAL(p,0,ea_size); /* Extended attributes */
2091 /* Clear the short name buffer. This is
2092 * IMPORTANT as not doing so will trigger
2093 * a Win2k client bug. JRA.
2095 if (!was_8_3 && check_mangled_names) {
2096 char mangled_name[13]; /* mangled 8.3 name. */
2097 if (!name_to_8_3(fname,mangled_name,True,
2099 /* Error - mangle failed ! */
2100 memset(mangled_name,'\0',12);
2102 mangled_name[12] = 0;
2103 status = srvstr_push(base_data, flags2,
2104 p+2, mangled_name, 24,
2105 STR_UPPER|STR_UNICODE, &len);
2106 if (!NT_STATUS_IS_OK(status)) {
2110 memset(p + 2 + len,'\0',24 - len);
2117 status = srvstr_push(base_data, flags2, p,
2118 fname, PTR_DIFF(end_data, p),
2119 STR_TERMINATE_ASCII, &len);
2120 if (!NT_STATUS_IS_OK(status)) {
2126 len = PTR_DIFF(p, pdata);
2127 pad = (len + (align-1)) & ~(align-1);
2129 * offset to the next entry, the caller
2130 * will overwrite it for the last entry
2131 * that's why we always include the padding
2135 * set padding to zero
2138 memset(p, 0, pad - len);
2145 case SMB_FIND_FILE_DIRECTORY_INFO:
2146 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2148 SIVAL(p,0,reskey); p += 4;
2149 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2150 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2151 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2152 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2153 SOFF_T(p,0,file_size); p += 8;
2154 SOFF_T(p,0,allocation_size); p += 8;
2155 SIVAL(p,0,mode); p += 4;
2156 status = srvstr_push(base_data, flags2,
2157 p + 4, fname, PTR_DIFF(end_data, p+4),
2158 STR_TERMINATE_ASCII, &len);
2159 if (!NT_STATUS_IS_OK(status)) {
2165 len = PTR_DIFF(p, pdata);
2166 pad = (len + (align-1)) & ~(align-1);
2168 * offset to the next entry, the caller
2169 * will overwrite it for the last entry
2170 * that's why we always include the padding
2174 * set padding to zero
2177 memset(p, 0, pad - len);
2184 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2185 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2187 SIVAL(p,0,reskey); p += 4;
2188 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2189 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2190 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2191 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2192 SOFF_T(p,0,file_size); p += 8;
2193 SOFF_T(p,0,allocation_size); p += 8;
2194 SIVAL(p,0,mode); p += 4;
2195 q = p; p += 4; /* q is placeholder for name length. */
2196 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2197 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2199 unsigned int ea_size = estimate_ea_size(conn, NULL,
2201 SIVAL(p,0,ea_size); /* Extended attributes */
2204 status = srvstr_push(base_data, flags2, p,
2205 fname, PTR_DIFF(end_data, p),
2206 STR_TERMINATE_ASCII, &len);
2207 if (!NT_STATUS_IS_OK(status)) {
2213 len = PTR_DIFF(p, pdata);
2214 pad = (len + (align-1)) & ~(align-1);
2216 * offset to the next entry, the caller
2217 * will overwrite it for the last entry
2218 * that's why we always include the padding
2222 * set padding to zero
2225 memset(p, 0, pad - len);
2232 case SMB_FIND_FILE_NAMES_INFO:
2233 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2235 SIVAL(p,0,reskey); p += 4;
2237 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2238 acl on a dir (tridge) */
2239 status = srvstr_push(base_data, flags2, p,
2240 fname, PTR_DIFF(end_data, p),
2241 STR_TERMINATE_ASCII, &len);
2242 if (!NT_STATUS_IS_OK(status)) {
2248 len = PTR_DIFF(p, pdata);
2249 pad = (len + (align-1)) & ~(align-1);
2251 * offset to the next entry, the caller
2252 * will overwrite it for the last entry
2253 * that's why we always include the padding
2257 * set padding to zero
2260 memset(p, 0, pad - len);
2267 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2268 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2270 SIVAL(p,0,reskey); p += 4;
2271 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2272 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2273 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2274 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2275 SOFF_T(p,0,file_size); p += 8;
2276 SOFF_T(p,0,allocation_size); p += 8;
2277 SIVAL(p,0,mode); p += 4;
2278 q = p; p += 4; /* q is placeholder for name length. */
2279 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2280 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2282 unsigned int ea_size = estimate_ea_size(conn, NULL,
2284 SIVAL(p,0,ea_size); /* Extended attributes */
2287 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2288 SBVAL(p,0,file_id); p += 8;
2289 status = srvstr_push(base_data, flags2, p,
2290 fname, PTR_DIFF(end_data, p),
2291 STR_TERMINATE_ASCII, &len);
2292 if (!NT_STATUS_IS_OK(status)) {
2298 len = PTR_DIFF(p, pdata);
2299 pad = (len + (align-1)) & ~(align-1);
2301 * offset to the next entry, the caller
2302 * will overwrite it for the last entry
2303 * that's why we always include the padding
2307 * set padding to zero
2310 memset(p, 0, pad - len);
2317 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2318 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2319 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2321 SIVAL(p,0,reskey); p += 4;
2322 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2323 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2324 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2325 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2326 SOFF_T(p,0,file_size); p += 8;
2327 SOFF_T(p,0,allocation_size); p += 8;
2328 SIVAL(p,0,mode); p += 4;
2329 q = p; p += 4; /* q is placeholder for name length */
2330 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2331 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2332 } else if (readdir_attr_data &&
2333 readdir_attr_data->type == RDATTR_AAPL) {
2335 * OS X specific SMB2 extension negotiated via
2336 * AAPL create context: return max_access in
2339 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2341 unsigned int ea_size = estimate_ea_size(conn, NULL,
2343 SIVAL(p,0,ea_size); /* Extended attributes */
2347 if (readdir_attr_data &&
2348 readdir_attr_data->type == RDATTR_AAPL) {
2350 * OS X specific SMB2 extension negotiated via
2351 * AAPL create context: return resource fork
2352 * length and compressed FinderInfo in
2355 * According to documentation short_name_len
2356 * should be 0, but on the wire behaviour
2357 * shows its set to 24 by clients.
2361 /* Resourefork length */
2362 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2364 /* Compressed FinderInfo */
2365 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2366 } else if (!was_8_3 && check_mangled_names) {
2367 char mangled_name[13]; /* mangled 8.3 name. */
2368 if (!name_to_8_3(fname,mangled_name,True,
2370 /* Error - mangle failed ! */
2371 memset(mangled_name,'\0',12);
2373 mangled_name[12] = 0;
2374 status = srvstr_push(base_data, flags2,
2375 p+2, mangled_name, 24,
2376 STR_UPPER|STR_UNICODE, &len);
2377 if (!NT_STATUS_IS_OK(status)) {
2382 memset(p + 2 + len,'\0',24 - len);
2386 /* Clear the short name buffer. This is
2387 * IMPORTANT as not doing so will trigger
2388 * a Win2k client bug. JRA.
2395 if (readdir_attr_data &&
2396 readdir_attr_data->type == RDATTR_AAPL) {
2398 * OS X specific SMB2 extension negotiated via
2399 * AAPL create context: return UNIX mode in
2402 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2403 SSVAL(p, 0, aapl_mode);
2409 SBVAL(p,0,file_id); p += 8;
2410 status = srvstr_push(base_data, flags2, p,
2411 fname, PTR_DIFF(end_data, p),
2412 STR_TERMINATE_ASCII, &len);
2413 if (!NT_STATUS_IS_OK(status)) {
2419 len = PTR_DIFF(p, pdata);
2420 pad = (len + (align-1)) & ~(align-1);
2422 * offset to the next entry, the caller
2423 * will overwrite it for the last entry
2424 * that's why we always include the padding
2428 * set padding to zero
2431 memset(p, 0, pad - len);
2438 /* CIFS UNIX Extension. */
2440 case SMB_FIND_FILE_UNIX:
2441 case SMB_FIND_FILE_UNIX_INFO2:
2443 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2445 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2447 if (info_level == SMB_FIND_FILE_UNIX) {
2448 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2449 p = store_file_unix_basic(conn, p,
2450 NULL, &smb_fname->st);
2451 status = srvstr_push(base_data, flags2, p,
2452 fname, PTR_DIFF(end_data, p),
2453 STR_TERMINATE, &len);
2454 if (!NT_STATUS_IS_OK(status)) {
2458 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2459 p = store_file_unix_basic_info2(conn, p,
2460 NULL, &smb_fname->st);
2463 status = srvstr_push(base_data, flags2, p, fname,
2464 PTR_DIFF(end_data, p), 0, &len);
2465 if (!NT_STATUS_IS_OK(status)) {
2468 SIVAL(nameptr, 0, len);
2473 len = PTR_DIFF(p, pdata);
2474 pad = (len + (align-1)) & ~(align-1);
2476 * offset to the next entry, the caller
2477 * will overwrite it for the last entry
2478 * that's why we always include the padding
2482 * set padding to zero
2485 memset(p, 0, pad - len);
2490 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2495 return NT_STATUS_INVALID_LEVEL;
2498 if (PTR_DIFF(p,pdata) > space_remaining) {
2499 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2500 "(wanted %u, had %d)\n",
2501 (unsigned int)PTR_DIFF(p,pdata),
2503 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2506 /* Setup the last entry pointer, as an offset from base_data */
2507 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2508 /* Advance the data pointer to the next slot */
2511 return NT_STATUS_OK;
2514 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2515 connection_struct *conn,
2516 struct dptr_struct *dirptr,
2518 const char *path_mask,
2521 int requires_resume_key,
2530 int space_remaining,
2531 struct smb_filename **_smb_fname,
2532 bool *got_exact_match,
2533 int *_last_entry_off,
2534 struct ea_list *name_list,
2535 struct file_id *file_id)
2538 const char *mask = NULL;
2539 long prev_dirpos = 0;
2542 struct smb_filename *smb_fname = NULL;
2543 struct smbd_dirptr_lanman2_state state;
2545 uint64_t last_entry_off = 0;
2547 enum mangled_names_options mangled_names;
2548 bool marshall_with_83_names;
2550 mangled_names = lp_mangled_names(conn->params);
2554 state.info_level = info_level;
2555 if (mangled_names != MANGLED_NAMES_NO) {
2556 state.check_mangled_names = true;
2558 state.has_wild = dptr_has_wild(dirptr);
2559 state.got_exact_match = false;
2561 *got_exact_match = false;
2563 p = strrchr_m(path_mask,'/');
2574 ok = smbd_dirptr_get_entry(ctx,
2581 smbd_dirptr_lanman2_match_fn,
2582 smbd_dirptr_lanman2_mode_fn,
2589 return NT_STATUS_END_OF_FILE;
2592 *got_exact_match = state.got_exact_match;
2594 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2596 status = smbd_marshall_dir_entry(ctx,
2601 marshall_with_83_names,
2602 requires_resume_key,
2613 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2614 DEBUG(1,("Conversion error: illegal character: %s\n",
2615 smb_fname_str_dbg(smb_fname)));
2618 if (file_id != NULL) {
2619 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2622 if (!NT_STATUS_IS_OK(status) &&
2623 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2625 TALLOC_FREE(smb_fname);
2630 if (_smb_fname != NULL) {
2631 struct smb_filename *name = NULL;
2633 name = synthetic_smb_fname(ctx,
2640 TALLOC_FREE(smb_fname);
2642 return NT_STATUS_NO_MEMORY;
2647 TALLOC_FREE(smb_fname);
2650 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2651 dptr_SeekDir(dirptr, prev_dirpos);
2655 *_last_entry_off = last_entry_off;
2656 return NT_STATUS_OK;
2659 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2660 connection_struct *conn,
2661 struct dptr_struct *dirptr,
2663 const char *path_mask,
2666 bool requires_resume_key,
2672 int space_remaining,
2673 bool *got_exact_match,
2674 int *last_entry_off,
2675 struct ea_list *name_list)
2678 const bool do_pad = true;
2680 if (info_level >= 1 && info_level <= 3) {
2681 /* No alignment on earlier info levels. */
2685 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2686 path_mask, dirtype, info_level,
2687 requires_resume_key, dont_descend, ask_sharemode,
2688 true, align, do_pad,
2689 ppdata, base_data, end_data,
2693 last_entry_off, name_list, NULL);
2696 /****************************************************************************
2697 Reply to a TRANS2_FINDFIRST.
2698 ****************************************************************************/
2700 static void call_trans2findfirst(connection_struct *conn,
2701 struct smb_request *req,
2702 char **pparams, int total_params,
2703 char **ppdata, int total_data,
2704 unsigned int max_data_bytes)
2706 /* We must be careful here that we don't return more than the
2707 allowed number of data bytes. If this means returning fewer than
2708 maxentries then so be it. We assume that the redirector has
2709 enough room for the fixed number of parameter bytes it has
2711 struct smb_filename *smb_dname = NULL;
2712 char *params = *pparams;
2713 char *pdata = *ppdata;
2717 uint16_t findfirst_flags;
2718 bool close_after_first;
2720 bool requires_resume_key;
2722 char *directory = NULL;
2725 int last_entry_off=0;
2729 bool finished = False;
2730 bool dont_descend = False;
2731 bool out_of_space = False;
2732 int space_remaining;
2733 struct ea_list *ea_list = NULL;
2734 NTSTATUS ntstatus = NT_STATUS_OK;
2735 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2736 struct smbd_server_connection *sconn = req->sconn;
2737 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2738 ucf_flags_from_smb_request(req);
2739 bool backup_priv = false;
2740 bool as_root = false;
2741 files_struct *fsp = NULL;
2742 const struct loadparm_substitution *lp_sub =
2743 loadparm_s3_global_substitution();
2746 if (total_params < 13) {
2747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2751 dirtype = SVAL(params,0);
2752 maxentries = SVAL(params,2);
2753 findfirst_flags = SVAL(params,4);
2754 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2755 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2756 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2757 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2758 security_token_has_privilege(get_current_nttok(conn),
2761 info_level = SVAL(params,6);
2763 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2764 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2765 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2767 info_level, max_data_bytes));
2770 /* W2K3 seems to treat zero as 1. */
2774 switch (info_level) {
2775 case SMB_FIND_INFO_STANDARD:
2776 case SMB_FIND_EA_SIZE:
2777 case SMB_FIND_EA_LIST:
2778 case SMB_FIND_FILE_DIRECTORY_INFO:
2779 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2780 case SMB_FIND_FILE_NAMES_INFO:
2781 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2782 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2783 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2785 case SMB_FIND_FILE_UNIX:
2786 case SMB_FIND_FILE_UNIX_INFO2:
2787 /* Always use filesystem for UNIX mtime query. */
2788 ask_sharemode = false;
2789 if (!lp_unix_extensions()) {
2790 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2793 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2796 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2800 if (req->posix_pathnames) {
2801 srvstr_get_path_posix(talloc_tos(),
2810 srvstr_get_path(talloc_tos(),
2819 if (!NT_STATUS_IS_OK(ntstatus)) {
2820 reply_nterror(req, ntstatus);
2827 ntstatus = filename_convert_with_privilege(talloc_tos(),
2834 ntstatus = filename_convert(talloc_tos(), conn,
2841 if (!NT_STATUS_IS_OK(ntstatus)) {
2842 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2843 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2844 ERRSRV, ERRbadpath);
2847 reply_nterror(req, ntstatus);
2851 mask = get_original_lcomp(talloc_tos(),
2856 reply_nterror(req, NT_STATUS_NO_MEMORY);
2860 directory = smb_dname->base_name;
2862 p = strrchr_m(directory,'/');
2864 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2865 if((directory[0] == '.') && (directory[1] == '\0')) {
2866 mask = talloc_strdup(talloc_tos(),"*");
2868 reply_nterror(req, NT_STATUS_NO_MEMORY);
2876 if (p == NULL || p == directory) {
2877 struct smb_filename *old_name = smb_dname;
2879 /* Ensure we don't have a directory name of "". */
2880 smb_dname = synthetic_smb_fname(talloc_tos(),
2886 TALLOC_FREE(old_name);
2887 if (smb_dname == NULL) {
2888 reply_nterror(req, NT_STATUS_NO_MEMORY);
2891 directory = smb_dname->base_name;
2894 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2896 if (info_level == SMB_FIND_EA_LIST) {
2899 if (total_data < 4) {
2900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2904 ea_size = IVAL(pdata,0);
2905 if (ea_size != total_data) {
2906 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2907 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2912 if (!lp_ea_support(SNUM(conn))) {
2913 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2917 /* Pull out the list of names. */
2918 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2925 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2930 *ppdata = (char *)SMB_REALLOC(
2931 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2932 if(*ppdata == NULL ) {
2933 reply_nterror(req, NT_STATUS_NO_MEMORY);
2937 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2939 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2942 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2943 /* Realloc the params space */
2944 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2945 if (*pparams == NULL) {
2946 reply_nterror(req, NT_STATUS_NO_MEMORY);
2952 * As we've cut off the last component from
2953 * smb_fname we need to re-stat smb_dname
2954 * so FILE_OPEN disposition knows the directory
2957 if (req->posix_pathnames) {
2958 ret = SMB_VFS_LSTAT(conn, smb_dname);
2960 ret = SMB_VFS_STAT(conn, smb_dname);
2964 ntstatus = map_nt_error_from_unix(errno);
2965 reply_nterror(req, ntstatus);
2970 * Open an fsp on this directory for the dptr.
2972 ntstatus = SMB_VFS_CREATE_FILE(
2975 smb_dname, /* dname */
2976 FILE_LIST_DIRECTORY, /* access_mask */
2978 FILE_SHARE_WRITE, /* share_access */
2979 FILE_OPEN, /* create_disposition*/
2980 FILE_DIRECTORY_FILE, /* create_options */
2981 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2982 NO_OPLOCK, /* oplock_request */
2984 0, /* allocation_size */
2985 0, /* private_flags */
2990 NULL, /* in_context */
2991 NULL);/* out_context */
2993 if (!NT_STATUS_IS_OK(ntstatus)) {
2994 DBG_ERR("failed to open directory %s\n",
2995 smb_fname_str_dbg(smb_dname));
2996 reply_nterror(req, ntstatus);
3000 /* Save the wildcard match and attribs we are using on this directory -
3001 needed as lanman2 assumes these are being saved between calls */
3003 ntstatus = dptr_create(conn,
3013 if (!NT_STATUS_IS_OK(ntstatus)) {
3015 * Use NULL here for the first parameter (req)
3016 * as this is not a client visible handle so
3017 * can'tbe part of an SMB1 chain.
3019 close_file(NULL, fsp, NORMAL_CLOSE);
3021 reply_nterror(req, ntstatus);
3026 /* Remember this in case we have
3027 to do a findnext. */
3028 dptr_set_priv(fsp->dptr);
3031 dptr_num = dptr_dnum(fsp->dptr);
3032 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3034 /* We don't need to check for VOL here as this is returned by
3035 a different TRANS2 call. */
3037 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3038 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3039 if (in_list(directory,
3040 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3041 conn->case_sensitive)) {
3042 dont_descend = True;
3046 space_remaining = max_data_bytes;
3047 out_of_space = False;
3049 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3050 bool got_exact_match = False;
3052 /* this is a heuristic to avoid seeking the dirptr except when
3053 absolutely necessary. It allows for a filename of about 40 chars */
3054 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3055 out_of_space = True;
3058 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3062 mask,dirtype,info_level,
3063 requires_resume_key,dont_descend,
3068 &last_entry_off, ea_list);
3069 if (NT_STATUS_EQUAL(ntstatus,
3070 NT_STATUS_ILLEGAL_CHARACTER)) {
3072 * Bad character conversion on name. Ignore this
3077 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3078 out_of_space = true;
3080 finished = !NT_STATUS_IS_OK(ntstatus);
3084 if (!finished && !out_of_space)
3088 * As an optimisation if we know we aren't looking
3089 * for a wildcard name (ie. the name matches the wildcard exactly)
3090 * then we can finish on any (first) match.
3091 * This speeds up large directory searches. JRA.
3097 /* Ensure space_remaining never goes -ve. */
3098 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3099 space_remaining = 0;
3100 out_of_space = true;
3102 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3106 /* Check if we can close the dirptr */
3107 if(close_after_first || (finished && close_if_end)) {
3108 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3110 close_file(NULL, fsp, NORMAL_CLOSE);
3115 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3116 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3117 * the protocol level is less than NT1. Tested with smbclient. JRA.
3118 * This should fix the OS/2 client bug #2335.
3121 if(numentries == 0) {
3124 * We may have already closed the file in the
3125 * close_after_first or finished case above.
3128 close_file(NULL, fsp, NORMAL_CLOSE);
3131 if (get_Protocol() < PROTOCOL_NT1) {
3132 reply_force_doserror(req, ERRDOS, ERRnofiles);
3135 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3136 ERRDOS, ERRbadfile);
3141 /* At this point pdata points to numentries directory entries. */
3143 /* Set up the return parameter block */
3144 SSVAL(params,0,dptr_num);
3145 SSVAL(params,2,numentries);
3146 SSVAL(params,4,finished);
3147 SSVAL(params,6,0); /* Never an EA error */
3148 SSVAL(params,8,last_entry_off);
3150 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3153 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3154 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3156 reply_nterror(req, NT_STATUS_NO_MEMORY);
3160 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3161 smb_fn_name(req->cmd),
3162 mask, directory, dirtype, numentries ) );
3165 * Force a name mangle here to ensure that the
3166 * mask as an 8.3 name is top of the mangled cache.
3167 * The reasons for this are subtle. Don't remove
3168 * this code unless you know what you are doing
3169 * (see PR#13758). JRA.
3172 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3173 char mangled_name[13];
3174 name_to_8_3(mask, mangled_name, True, conn->params);
3182 TALLOC_FREE(smb_dname);
3186 /****************************************************************************
3187 Reply to a TRANS2_FINDNEXT.
3188 ****************************************************************************/
3190 static void call_trans2findnext(connection_struct *conn,
3191 struct smb_request *req,
3192 char **pparams, int total_params,
3193 char **ppdata, int total_data,
3194 unsigned int max_data_bytes)
3196 /* We must be careful here that we don't return more than the
3197 allowed number of data bytes. If this means returning fewer than
3198 maxentries then so be it. We assume that the redirector has
3199 enough room for the fixed number of parameter bytes it has
3201 char *params = *pparams;
3202 char *pdata = *ppdata;
3206 uint16_t info_level;
3207 uint32_t resume_key;
3208 uint16_t findnext_flags;
3209 bool close_after_request;
3211 bool requires_resume_key;
3213 char *resume_name = NULL;
3214 const char *mask = NULL;
3215 const char *directory = NULL;
3219 int i, last_entry_off=0;
3220 bool finished = False;
3221 bool dont_descend = False;
3222 bool out_of_space = False;
3223 int space_remaining;
3224 struct ea_list *ea_list = NULL;
3225 NTSTATUS ntstatus = NT_STATUS_OK;
3226 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3227 TALLOC_CTX *ctx = talloc_tos();
3228 struct smbd_server_connection *sconn = req->sconn;
3229 bool backup_priv = false;
3230 bool as_root = false;
3231 files_struct *fsp = NULL;
3232 const struct loadparm_substitution *lp_sub =
3233 loadparm_s3_global_substitution();
3235 if (total_params < 13) {
3236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3240 dptr_num = SVAL(params,0);
3241 maxentries = SVAL(params,2);
3242 info_level = SVAL(params,4);
3243 resume_key = IVAL(params,6);
3244 findnext_flags = SVAL(params,10);
3245 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3246 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3247 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3248 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3250 if (!continue_bit) {
3251 /* We only need resume_name if continue_bit is zero. */
3252 if (req->posix_pathnames) {
3253 srvstr_get_path_posix(ctx,
3262 srvstr_get_path(ctx,
3271 if (!NT_STATUS_IS_OK(ntstatus)) {
3272 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3273 complain (it thinks we're asking for the directory above the shared
3274 path or an invalid name). Catch this as the resume name is only compared, never used in
3275 a file access. JRA. */
3276 srvstr_pull_talloc(ctx, params, req->flags2,
3277 &resume_name, params+12,
3281 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3282 reply_nterror(req, ntstatus);
3288 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3289 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3290 resume_key = %d resume name = %s continue=%d level = %d\n",
3291 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3292 requires_resume_key, resume_key,
3293 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3296 /* W2K3 seems to treat zero as 1. */
3300 switch (info_level) {
3301 case SMB_FIND_INFO_STANDARD:
3302 case SMB_FIND_EA_SIZE:
3303 case SMB_FIND_EA_LIST:
3304 case SMB_FIND_FILE_DIRECTORY_INFO:
3305 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3306 case SMB_FIND_FILE_NAMES_INFO:
3307 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3308 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3309 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3311 case SMB_FIND_FILE_UNIX:
3312 case SMB_FIND_FILE_UNIX_INFO2:
3313 /* Always use filesystem for UNIX mtime query. */
3314 ask_sharemode = false;
3315 if (!lp_unix_extensions()) {
3316 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3321 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3325 if (info_level == SMB_FIND_EA_LIST) {
3328 if (total_data < 4) {
3329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3333 ea_size = IVAL(pdata,0);
3334 if (ea_size != total_data) {
3335 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3336 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3341 if (!lp_ea_support(SNUM(conn))) {
3342 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3346 /* Pull out the list of names. */
3347 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3354 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3359 *ppdata = (char *)SMB_REALLOC(
3360 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3361 if(*ppdata == NULL) {
3362 reply_nterror(req, NT_STATUS_NO_MEMORY);
3367 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3370 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3373 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3374 /* Realloc the params space */
3375 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3376 if(*pparams == NULL ) {
3377 reply_nterror(req, NT_STATUS_NO_MEMORY);
3383 /* Check that the dptr is valid */
3384 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3386 reply_nterror(req, STATUS_NO_MORE_FILES);
3390 directory = dptr_path(sconn, dptr_num);
3392 /* Get the wildcard mask from the dptr */
3393 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3394 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3395 reply_nterror(req, STATUS_NO_MORE_FILES);
3399 /* Get the attr mask from the dptr */
3400 dirtype = dptr_attr(sconn, dptr_num);
3402 backup_priv = dptr_get_priv(fsp->dptr);
3404 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3405 "backup_priv = %d\n",
3406 dptr_num, mask, dirtype,
3408 dptr_TellDir(fsp->dptr),
3411 /* We don't need to check for VOL here as this is returned by
3412 a different TRANS2 call. */
3414 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3415 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3416 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3417 dont_descend = True;
3420 space_remaining = max_data_bytes;
3421 out_of_space = False;
3429 * Seek to the correct position. We no longer use the resume key but
3430 * depend on the last file name instead.
3433 if(!continue_bit && resume_name && *resume_name) {
3436 long current_pos = 0;
3438 * Remember, name_to_8_3 is called by
3439 * get_lanman2_dir_entry(), so the resume name
3440 * could be mangled. Ensure we check the unmangled name.
3443 if (mangle_is_mangled(resume_name, conn->params)) {
3444 char *new_resume_name = NULL;
3445 mangle_lookup_name_from_8_3(ctx,
3449 if (new_resume_name) {
3450 resume_name = new_resume_name;
3455 * Fix for NT redirector problem triggered by resume key indexes
3456 * changing between directory scans. We now return a resume key of 0
3457 * and instead look for the filename to continue from (also given
3458 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3459 * findfirst/findnext (as is usual) then the directory pointer
3460 * should already be at the correct place.
3463 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3464 } /* end if resume_name && !continue_bit */
3466 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3467 bool got_exact_match = False;
3469 /* this is a heuristic to avoid seeking the fsp->dptr except when
3470 absolutely necessary. It allows for a filename of about 40 chars */
3471 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3472 out_of_space = True;
3475 ntstatus = get_lanman2_dir_entry(ctx,
3479 mask,dirtype,info_level,
3480 requires_resume_key,dont_descend,
3485 &last_entry_off, ea_list);
3486 if (NT_STATUS_EQUAL(ntstatus,
3487 NT_STATUS_ILLEGAL_CHARACTER)) {
3489 * Bad character conversion on name. Ignore this
3494 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3495 out_of_space = true;
3497 finished = !NT_STATUS_IS_OK(ntstatus);
3501 if (!finished && !out_of_space)
3505 * As an optimisation if we know we aren't looking
3506 * for a wildcard name (ie. the name matches the wildcard exactly)
3507 * then we can finish on any (first) match.
3508 * This speeds up large directory searches. JRA.
3514 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3517 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3518 smb_fn_name(req->cmd),
3519 mask, directory, dirtype, numentries ) );
3521 /* Check if we can close the fsp->dptr */
3522 if(close_after_request || (finished && close_if_end)) {
3523 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3525 close_file(NULL, fsp, NORMAL_CLOSE);
3533 /* Set up the return parameter block */
3534 SSVAL(params,0,numentries);
3535 SSVAL(params,2,finished);
3536 SSVAL(params,4,0); /* Never an EA error */
3537 SSVAL(params,6,last_entry_off);
3539 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3545 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3547 const struct loadparm_substitution *lp_sub =
3548 loadparm_s3_global_substitution();
3550 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3554 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3556 SMB_ASSERT(extended_info != NULL);
3558 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3559 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3560 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3561 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3562 #ifdef SAMBA_VERSION_REVISION
3563 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3565 extended_info->samba_subversion = 0;
3566 #ifdef SAMBA_VERSION_RC_RELEASE
3567 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3569 #ifdef SAMBA_VERSION_PRE_RELEASE
3570 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3573 #ifdef SAMBA_VERSION_VENDOR_PATCH
3574 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3576 extended_info->samba_gitcommitdate = 0;
3577 #ifdef SAMBA_VERSION_COMMIT_TIME
3578 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3581 memset(extended_info->samba_version_string, 0,
3582 sizeof(extended_info->samba_version_string));
3584 snprintf (extended_info->samba_version_string,
3585 sizeof(extended_info->samba_version_string),
3586 "%s", samba_version_string());
3589 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3590 connection_struct *conn,
3591 TALLOC_CTX *mem_ctx,
3592 uint16_t info_level,
3594 unsigned int max_data_bytes,
3595 size_t *fixed_portion,
3596 struct smb_filename *fname,
3600 const struct loadparm_substitution *lp_sub =
3601 loadparm_s3_global_substitution();
3602 char *pdata, *end_data;
3605 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3606 int snum = SNUM(conn);
3607 const char *fstype = lp_fstype(SNUM(conn));
3608 const char *filename = NULL;
3609 const uint64_t bytes_per_sector = 512;
3610 uint32_t additional_flags = 0;
3611 struct smb_filename smb_fname;
3613 NTSTATUS status = NT_STATUS_OK;
3616 if (fname == NULL || fname->base_name == NULL) {
3619 filename = fname->base_name;
3623 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3624 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3625 "info level (0x%x) on IPC$.\n",
3626 (unsigned int)info_level));
3627 return NT_STATUS_ACCESS_DENIED;
3631 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3633 ZERO_STRUCT(smb_fname);
3634 smb_fname.base_name = discard_const_p(char, filename);
3636 if(info_level != SMB_FS_QUOTA_INFORMATION
3637 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3638 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3639 return map_nt_error_from_unix(errno);
3644 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3645 return NT_STATUS_INVALID_PARAMETER;
3648 *ppdata = (char *)SMB_REALLOC(
3649 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3650 if (*ppdata == NULL) {
3651 return NT_STATUS_NO_MEMORY;
3655 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3656 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3660 switch (info_level) {
3661 case SMB_INFO_ALLOCATION:
3663 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3665 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3667 if (df_ret == (uint64_t)-1) {
3668 return map_nt_error_from_unix(errno);
3671 block_size = lp_block_size(snum);
3672 if (bsize < block_size) {
3673 uint64_t factor = block_size/bsize;
3678 if (bsize > block_size) {
3679 uint64_t factor = bsize/block_size;
3684 sectors_per_unit = bsize/bytes_per_sector;
3686 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3687 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3688 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3691 * For large drives, return max values and not modulo.
3693 dsize = MIN(dsize, UINT32_MAX);
3694 dfree = MIN(dfree, UINT32_MAX);
3696 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3697 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3698 SIVAL(pdata,l1_cUnit,dsize);
3699 SIVAL(pdata,l1_cUnitAvail,dfree);
3700 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3704 case SMB_INFO_VOLUME:
3705 /* Return volume name */
3707 * Add volume serial number - hash of a combination of
3708 * the called hostname and the service name.
3710 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3712 * Win2k3 and previous mess this up by sending a name length
3713 * one byte short. I believe only older clients (OS/2 Win9x) use
3714 * this call so try fixing this by adding a terminating null to
3715 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3717 status = srvstr_push(
3719 pdata+l2_vol_szVolLabel, vname,
3720 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3721 STR_NOALIGN|STR_TERMINATE, &len);
3722 if (!NT_STATUS_IS_OK(status)) {
3725 SCVAL(pdata,l2_vol_cch,len);
3726 data_len = l2_vol_szVolLabel + len;
3727 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3728 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3729 (unsigned)len, vname));
3732 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3733 case SMB_FS_ATTRIBUTE_INFORMATION:
3735 additional_flags = 0;
3736 #if defined(HAVE_SYS_QUOTAS)
3737 additional_flags |= FILE_VOLUME_QUOTAS;
3740 if(lp_nt_acl_support(SNUM(conn))) {
3741 additional_flags |= FILE_PERSISTENT_ACLS;
3744 /* Capabilities are filled in at connection time through STATVFS call */
3745 additional_flags |= conn->fs_capabilities;
3746 additional_flags |= lp_parm_int(conn->params->service,
3747 "share", "fake_fscaps",
3750 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3751 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3752 additional_flags); /* FS ATTRIBUTES */
3754 SIVAL(pdata,4,255); /* Max filename component length */
3755 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3756 and will think we can't do long filenames */
3757 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3758 PTR_DIFF(end_data, pdata+12),
3760 if (!NT_STATUS_IS_OK(status)) {
3764 data_len = 12 + len;
3765 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3766 /* the client only requested a portion of the
3768 data_len = max_data_bytes;
3769 status = STATUS_BUFFER_OVERFLOW;
3771 *fixed_portion = 16;
3774 case SMB_QUERY_FS_LABEL_INFO:
3775 case SMB_FS_LABEL_INFORMATION:
3776 status = srvstr_push(pdata, flags2, pdata+4, vname,
3777 PTR_DIFF(end_data, pdata+4), 0, &len);
3778 if (!NT_STATUS_IS_OK(status)) {
3785 case SMB_QUERY_FS_VOLUME_INFO:
3786 case SMB_FS_VOLUME_INFORMATION:
3789 * Add volume serial number - hash of a combination of
3790 * the called hostname and the service name.
3792 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3793 (str_checksum(get_local_machine_name())<<16));
3795 /* Max label len is 32 characters. */
3796 status = srvstr_push(pdata, flags2, pdata+18, vname,
3797 PTR_DIFF(end_data, pdata+18),
3799 if (!NT_STATUS_IS_OK(status)) {
3802 SIVAL(pdata,12,len);
3805 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3806 (int)strlen(vname),vname,
3807 lp_servicename(talloc_tos(), lp_sub, snum)));
3808 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3809 /* the client only requested a portion of the
3811 data_len = max_data_bytes;
3812 status = STATUS_BUFFER_OVERFLOW;
3814 *fixed_portion = 24;
3817 case SMB_QUERY_FS_SIZE_INFO:
3818 case SMB_FS_SIZE_INFORMATION:
3820 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3822 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3824 if (df_ret == (uint64_t)-1) {
3825 return map_nt_error_from_unix(errno);
3827 block_size = lp_block_size(snum);
3828 if (bsize < block_size) {
3829 uint64_t factor = block_size/bsize;
3834 if (bsize > block_size) {
3835 uint64_t factor = bsize/block_size;
3840 sectors_per_unit = bsize/bytes_per_sector;
3841 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3842 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3843 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3844 SBIG_UINT(pdata,0,dsize);
3845 SBIG_UINT(pdata,8,dfree);
3846 SIVAL(pdata,16,sectors_per_unit);
3847 SIVAL(pdata,20,bytes_per_sector);
3848 *fixed_portion = 24;
3852 case SMB_FS_FULL_SIZE_INFORMATION:
3854 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3856 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3858 if (df_ret == (uint64_t)-1) {
3859 return map_nt_error_from_unix(errno);
3861 block_size = lp_block_size(snum);
3862 if (bsize < block_size) {
3863 uint64_t factor = block_size/bsize;
3868 if (bsize > block_size) {
3869 uint64_t factor = bsize/block_size;
3874 sectors_per_unit = bsize/bytes_per_sector;
3875 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3876 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3877 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3878 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3879 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3880 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3881 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3882 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3883 *fixed_portion = 32;
3887 case SMB_QUERY_FS_DEVICE_INFO:
3888 case SMB_FS_DEVICE_INFORMATION:
3890 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3892 if (!CAN_WRITE(conn)) {
3893 characteristics |= FILE_READ_ONLY_DEVICE;
3896 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3897 SIVAL(pdata,4,characteristics);
3902 #ifdef HAVE_SYS_QUOTAS
3903 case SMB_FS_QUOTA_INFORMATION:
3905 * what we have to send --metze:
3907 * Unknown1: 24 NULL bytes
3908 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3909 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3910 * Quota Flags: 2 byte :
3911 * Unknown3: 6 NULL bytes
3915 * details for Quota Flags:
3917 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3918 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3919 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3920 * 0x0001 Enable Quotas: enable quota for this fs
3924 /* we need to fake up a fsp here,
3925 * because its not send in this call
3928 SMB_NTQUOTA_STRUCT quotas;
3931 ZERO_STRUCT(quotas);
3934 fsp.fnum = FNUM_FIELD_INVALID;
3937 if (get_current_uid(conn) != 0) {
3938 DEBUG(0,("get_user_quota: access_denied "
3939 "service [%s] user [%s]\n",
3940 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3941 conn->session_info->unix_info->unix_name));
3942 return NT_STATUS_ACCESS_DENIED;
3945 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3947 if (!NT_STATUS_IS_OK(status)) {
3948 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3954 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3955 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3957 /* Unknown1 24 NULL bytes*/
3958 SBIG_UINT(pdata,0,(uint64_t)0);
3959 SBIG_UINT(pdata,8,(uint64_t)0);
3960 SBIG_UINT(pdata,16,(uint64_t)0);
3962 /* Default Soft Quota 8 bytes */
3963 SBIG_UINT(pdata,24,quotas.softlim);
3965 /* Default Hard Quota 8 bytes */
3966 SBIG_UINT(pdata,32,quotas.hardlim);
3968 /* Quota flag 2 bytes */
3969 SSVAL(pdata,40,quotas.qflags);
3971 /* Unknown3 6 NULL bytes */
3977 #endif /* HAVE_SYS_QUOTAS */
3978 case SMB_FS_OBJECTID_INFORMATION:
3980 unsigned char objid[16];
3981 struct smb_extended_info extended_info;
3982 memcpy(pdata,create_volume_objectid(conn, objid),16);
3983 samba_extended_info_version (&extended_info);
3984 SIVAL(pdata,16,extended_info.samba_magic);
3985 SIVAL(pdata,20,extended_info.samba_version);
3986 SIVAL(pdata,24,extended_info.samba_subversion);
3987 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3988 memcpy(pdata+36,extended_info.samba_version_string,28);
3993 case SMB_FS_SECTOR_SIZE_INFORMATION:
3997 * These values match a physical Windows Server 2012
3998 * share backed by NTFS atop spinning rust.
4000 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
4001 /* logical_bytes_per_sector */
4002 SIVAL(pdata, 0, bytes_per_sector);
4003 /* phys_bytes_per_sector_atomic */
4004 SIVAL(pdata, 4, bytes_per_sector);
4005 /* phys_bytes_per_sector_perf */
4006 SIVAL(pdata, 8, bytes_per_sector);
4007 /* fs_effective_phys_bytes_per_sector_atomic */
4008 SIVAL(pdata, 12, bytes_per_sector);
4010 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4011 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4012 /* byte_off_sector_align */
4013 SIVAL(pdata, 20, 0);
4014 /* byte_off_partition_align */
4015 SIVAL(pdata, 24, 0);
4016 *fixed_portion = 28;
4022 * Query the version and capabilities of the CIFS UNIX extensions
4026 case SMB_QUERY_CIFS_UNIX_INFO:
4028 bool large_write = lp_min_receive_file_size() &&
4029 !srv_is_signing_active(xconn);
4030 bool large_read = !srv_is_signing_active(xconn);
4031 int encrypt_caps = 0;
4033 if (!lp_unix_extensions()) {
4034 return NT_STATUS_INVALID_LEVEL;
4037 switch (conn->encrypt_level) {
4038 case SMB_SIGNING_OFF:
4041 case SMB_SIGNING_DESIRED:
4042 case SMB_SIGNING_IF_REQUIRED:
4043 case SMB_SIGNING_DEFAULT:
4044 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4046 case SMB_SIGNING_REQUIRED:
4047 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4048 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4049 large_write = false;
4055 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4056 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4058 /* We have POSIX ACLs, pathname, encryption,
4059 * large read/write, and locking capability. */
4061 SBIG_UINT(pdata,4,((uint64_t)(
4062 CIFS_UNIX_POSIX_ACLS_CAP|
4063 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4064 CIFS_UNIX_FCNTL_LOCKS_CAP|
4065 CIFS_UNIX_EXTATTR_CAP|
4066 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4068 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4070 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4074 case SMB_QUERY_POSIX_FS_INFO:
4077 vfs_statvfs_struct svfs;
4079 if (!lp_unix_extensions()) {
4080 return NT_STATUS_INVALID_LEVEL;
4083 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4087 SIVAL(pdata,0,svfs.OptimalTransferSize);
4088 SIVAL(pdata,4,svfs.BlockSize);
4089 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4090 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4091 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4092 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4093 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4094 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4095 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4097 } else if (rc == EOPNOTSUPP) {
4098 return NT_STATUS_INVALID_LEVEL;
4099 #endif /* EOPNOTSUPP */
4101 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4102 return NT_STATUS_DOS(ERRSRV, ERRerror);
4107 case SMB_QUERY_POSIX_WHOAMI:
4113 if (!lp_unix_extensions()) {
4114 return NT_STATUS_INVALID_LEVEL;
4117 if (max_data_bytes < 40) {
4118 return NT_STATUS_BUFFER_TOO_SMALL;
4121 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4122 flags |= SMB_WHOAMI_GUEST;
4125 /* NOTE: 8 bytes for UID/GID, irrespective of native
4126 * platform size. This matches
4127 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4129 data_len = 4 /* flags */
4136 + 4 /* pad/reserved */
4137 + (conn->session_info->unix_token->ngroups * 8)
4139 + (conn->session_info->security_token->num_sids *
4143 SIVAL(pdata, 0, flags);
4144 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4146 (uint64_t)conn->session_info->unix_token->uid);
4147 SBIG_UINT(pdata, 16,
4148 (uint64_t)conn->session_info->unix_token->gid);
4151 if (data_len >= max_data_bytes) {
4152 /* Potential overflow, skip the GIDs and SIDs. */
4154 SIVAL(pdata, 24, 0); /* num_groups */
4155 SIVAL(pdata, 28, 0); /* num_sids */
4156 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4157 SIVAL(pdata, 36, 0); /* reserved */
4163 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4164 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4166 /* We walk the SID list twice, but this call is fairly
4167 * infrequent, and I don't expect that it's performance
4168 * sensitive -- jpeach
4170 for (i = 0, sid_bytes = 0;
4171 i < conn->session_info->security_token->num_sids; ++i) {
4172 sid_bytes += ndr_size_dom_sid(
4173 &conn->session_info->security_token->sids[i],
4177 /* SID list byte count */
4178 SIVAL(pdata, 32, sid_bytes);
4180 /* 4 bytes pad/reserved - must be zero */
4181 SIVAL(pdata, 36, 0);
4185 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4186 SBIG_UINT(pdata, data_len,
4187 (uint64_t)conn->session_info->unix_token->groups[i]);
4193 i < conn->session_info->security_token->num_sids; ++i) {
4194 int sid_len = ndr_size_dom_sid(
4195 &conn->session_info->security_token->sids[i],
4198 sid_linearize((uint8_t *)(pdata + data_len),
4200 &conn->session_info->security_token->sids[i]);
4201 data_len += sid_len;
4207 case SMB_MAC_QUERY_FS_INFO:
4209 * Thursby MAC extension... ONLY on NTFS filesystems
4210 * once we do streams then we don't need this
4212 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4214 SIVAL(pdata,84,0x100); /* Don't support mac... */
4220 return NT_STATUS_INVALID_LEVEL;
4223 *ret_data_len = data_len;
4227 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4228 struct smb_request *req,
4230 const DATA_BLOB *qdata)
4232 const struct loadparm_substitution *lp_sub =
4233 loadparm_s3_global_substitution();
4235 SMB_NTQUOTA_STRUCT quotas;
4237 ZERO_STRUCT(quotas);
4240 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4241 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4242 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4243 conn->session_info->unix_info->unix_name));
4244 return NT_STATUS_ACCESS_DENIED;
4247 if (!check_fsp_ntquota_handle(conn, req,
4249 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4250 return NT_STATUS_INVALID_HANDLE;
4253 /* note: normally there're 48 bytes,
4254 * but we didn't use the last 6 bytes for now
4257 if (qdata->length < 42) {
4258 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4259 (unsigned int)qdata->length));
4260 return NT_STATUS_INVALID_PARAMETER;
4263 /* unknown_1 24 NULL bytes in pdata*/
4265 /* the soft quotas 8 bytes (uint64_t)*/
4266 quotas.softlim = BVAL(qdata->data,24);
4268 /* the hard quotas 8 bytes (uint64_t)*/
4269 quotas.hardlim = BVAL(qdata->data,32);
4271 /* quota_flags 2 bytes **/
4272 quotas.qflags = SVAL(qdata->data,40);
4274 /* unknown_2 6 NULL bytes follow*/
4276 /* now set the quotas */
4277 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4278 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4279 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4280 status = map_nt_error_from_unix(errno);
4282 status = NT_STATUS_OK;
4287 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4288 struct smb_request *req,
4289 TALLOC_CTX *mem_ctx,
4290 uint16_t info_level,
4292 const DATA_BLOB *pdata)
4294 switch (info_level) {
4295 case SMB_FS_QUOTA_INFORMATION:
4297 return smb_set_fsquota(conn,
4306 return NT_STATUS_INVALID_LEVEL;
4309 /****************************************************************************
4310 Reply to a TRANS2_QFSINFO (query filesystem info).
4311 ****************************************************************************/
4313 static void call_trans2qfsinfo(connection_struct *conn,
4314 struct smb_request *req,
4315 char **pparams, int total_params,
4316 char **ppdata, int total_data,
4317 unsigned int max_data_bytes)
4319 char *params = *pparams;
4320 uint16_t info_level;
4322 size_t fixed_portion;
4325 if (total_params < 2) {
4326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4330 info_level = SVAL(params,0);
4332 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4333 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4334 DEBUG(0,("call_trans2qfsinfo: encryption required "
4335 "and info level 0x%x sent.\n",
4336 (unsigned int)info_level));
4337 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4342 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4344 status = smbd_do_qfsinfo(req->xconn, conn, req,
4351 if (!NT_STATUS_IS_OK(status)) {
4352 reply_nterror(req, status);
4356 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4359 DEBUG( 4, ( "%s info_level = %d\n",
4360 smb_fn_name(req->cmd), info_level) );
4365 /****************************************************************************
4366 Reply to a TRANS2_SETFSINFO (set filesystem info).
4367 ****************************************************************************/
4369 static void call_trans2setfsinfo(connection_struct *conn,
4370 struct smb_request *req,
4371 char **pparams, int total_params,
4372 char **ppdata, int total_data,
4373 unsigned int max_data_bytes)
4375 const struct loadparm_substitution *lp_sub =
4376 loadparm_s3_global_substitution();
4377 struct smbXsrv_connection *xconn = req->xconn;
4378 char *pdata = *ppdata;
4379 char *params = *pparams;
4380 uint16_t info_level;
4382 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4383 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4386 if (total_params < 4) {
4387 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4393 info_level = SVAL(params,2);
4396 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4397 info_level != SMB_SET_CIFS_UNIX_INFO) {
4398 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4399 "info level (0x%x) on IPC$.\n",
4400 (unsigned int)info_level));
4401 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4406 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4407 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4408 DEBUG(0,("call_trans2setfsinfo: encryption required "
4409 "and info level 0x%x sent.\n",
4410 (unsigned int)info_level));
4411 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4416 switch(info_level) {
4417 case SMB_SET_CIFS_UNIX_INFO:
4418 if (!lp_unix_extensions()) {
4419 DEBUG(2,("call_trans2setfsinfo: "
4420 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4421 "unix extensions off\n"));
4423 NT_STATUS_INVALID_LEVEL);
4427 /* There should be 12 bytes of capabilities set. */
4428 if (total_data < 12) {
4431 NT_STATUS_INVALID_PARAMETER);
4434 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4435 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4436 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4437 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4438 /* Just print these values for now. */
4439 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4440 "major = %u, minor = %u cap_low = 0x%x, "
4442 (unsigned int)xconn->
4443 smb1.unix_info.client_major,
4444 (unsigned int)xconn->
4445 smb1.unix_info.client_minor,
4446 (unsigned int)xconn->
4447 smb1.unix_info.client_cap_low,
4448 (unsigned int)xconn->
4449 smb1.unix_info.client_cap_high));
4451 /* Here is where we must switch to posix pathname processing... */
4452 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4453 lp_set_posix_pathnames();
4454 mangle_change_to_posix();
4457 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4458 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4459 /* Client that knows how to do posix locks,
4460 * but not posix open/mkdir operations. Set a
4461 * default type for read/write checks. */
4463 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4468 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4471 size_t param_len = 0;
4472 size_t data_len = total_data;
4474 if (!lp_unix_extensions()) {
4477 NT_STATUS_INVALID_LEVEL);
4481 if (lp_server_smb_encrypt(SNUM(conn)) ==
4482 SMB_ENCRYPTION_OFF) {
4485 NT_STATUS_NOT_SUPPORTED);
4489 if (xconn->smb1.echo_handler.trusted_fde) {
4490 DEBUG( 2,("call_trans2setfsinfo: "
4491 "request transport encryption disabled"
4492 "with 'fork echo handler = yes'\n"));
4495 NT_STATUS_NOT_SUPPORTED);
4499 DEBUG( 4,("call_trans2setfsinfo: "
4500 "request transport encryption.\n"));
4502 status = srv_request_encryption_setup(conn,
4503 (unsigned char **)ppdata,
4505 (unsigned char **)pparams,
4508 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4509 !NT_STATUS_IS_OK(status)) {
4510 reply_nterror(req, status);
4514 send_trans2_replies(conn, req,
4522 if (NT_STATUS_IS_OK(status)) {
4523 /* Server-side transport
4524 * encryption is now *on*. */
4525 status = srv_encryption_start(conn);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 char *reason = talloc_asprintf(talloc_tos(),
4528 "Failure in setting "
4529 "up encrypted transport: %s",
4531 exit_server_cleanly(reason);
4537 case SMB_FS_QUOTA_INFORMATION:
4541 .data = (uint8_t *)pdata,
4542 .length = total_data
4544 files_struct *fsp = NULL;
4545 fsp = file_fsp(req, SVAL(params,0));
4547 status = smb_set_fsquota(conn,
4551 if (!NT_STATUS_IS_OK(status)) {
4552 reply_nterror(req, status);
4558 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4560 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4566 * sending this reply works fine,
4567 * but I'm not sure it's the same
4568 * like windows do...
4571 reply_outbuf(req, 10, 0);
4574 #if defined(HAVE_POSIX_ACLS)
4575 /****************************************************************************
4576 Utility function to count the number of entries in a POSIX acl.
4577 ****************************************************************************/
4579 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4581 unsigned int ace_count = 0;
4582 int entry_id = SMB_ACL_FIRST_ENTRY;
4583 SMB_ACL_ENTRY_T entry;
4585 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4587 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4588 entry_id = SMB_ACL_NEXT_ENTRY;
4595 /****************************************************************************
4596 Utility function to marshall a POSIX acl into wire format.
4597 ****************************************************************************/
4599 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4601 int entry_id = SMB_ACL_FIRST_ENTRY;
4602 SMB_ACL_ENTRY_T entry;
4604 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4605 SMB_ACL_TAG_T tagtype;
4606 SMB_ACL_PERMSET_T permset;
4607 unsigned char perms = 0;
4608 unsigned int own_grp;
4611 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4612 entry_id = SMB_ACL_NEXT_ENTRY;
4615 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4616 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4620 if (sys_acl_get_permset(entry, &permset) == -1) {
4621 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4625 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4626 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4627 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4629 SCVAL(pdata,1,perms);
4632 case SMB_ACL_USER_OBJ:
4633 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4634 own_grp = (unsigned int)pst->st_ex_uid;
4635 SIVAL(pdata,2,own_grp);
4640 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4642 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4645 own_grp = (unsigned int)*puid;
4646 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4647 SIVAL(pdata,2,own_grp);
4651 case SMB_ACL_GROUP_OBJ:
4652 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4653 own_grp = (unsigned int)pst->st_ex_gid;
4654 SIVAL(pdata,2,own_grp);
4659 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4661 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4664 own_grp = (unsigned int)*pgid;
4665 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4666 SIVAL(pdata,2,own_grp);
4671 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4672 SIVAL(pdata,2,0xFFFFFFFF);
4673 SIVAL(pdata,6,0xFFFFFFFF);
4676 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4677 SIVAL(pdata,2,0xFFFFFFFF);
4678 SIVAL(pdata,6,0xFFFFFFFF);
4681 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4684 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4691 /****************************************************************************
4692 Store the FILE_UNIX_BASIC info.
4693 ****************************************************************************/
4695 static char *store_file_unix_basic(connection_struct *conn,
4698 const SMB_STRUCT_STAT *psbuf)
4702 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4703 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4705 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4708 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4711 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4712 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4713 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4716 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4720 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4724 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4727 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4728 devno = psbuf->st_ex_rdev;
4730 devno = psbuf->st_ex_dev;
4733 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4737 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4741 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4744 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4748 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4755 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4756 * the chflags(2) (or equivalent) flags.
4758 * XXX: this really should be behind the VFS interface. To do this, we would
4759 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4760 * Each VFS module could then implement its own mapping as appropriate for the
4761 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4763 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4767 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4771 { UF_IMMUTABLE, EXT_IMMUTABLE },
4775 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4779 { UF_HIDDEN, EXT_HIDDEN },
4782 /* Do not remove. We need to guarantee that this array has at least one
4783 * entry to build on HP-UX.
4789 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4790 uint32_t *smb_fflags, uint32_t *smb_fmask)
4794 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4795 *smb_fmask |= info2_flags_map[i].smb_fflag;
4796 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4797 *smb_fflags |= info2_flags_map[i].smb_fflag;
4802 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4803 const uint32_t smb_fflags,
4804 const uint32_t smb_fmask,
4807 uint32_t max_fmask = 0;
4810 *stat_fflags = psbuf->st_ex_flags;
4812 /* For each flags requested in smb_fmask, check the state of the
4813 * corresponding flag in smb_fflags and set or clear the matching
4817 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4818 max_fmask |= info2_flags_map[i].smb_fflag;
4819 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4820 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4821 *stat_fflags |= info2_flags_map[i].stat_fflag;
4823 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4828 /* If smb_fmask is asking to set any bits that are not supported by
4829 * our flag mappings, we should fail.
4831 if ((smb_fmask & max_fmask) != smb_fmask) {
4839 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4840 * of file flags and birth (create) time.
4842 static char *store_file_unix_basic_info2(connection_struct *conn,
4845 const SMB_STRUCT_STAT *psbuf)
4847 uint32_t file_flags = 0;
4848 uint32_t flags_mask = 0;
4850 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4852 /* Create (birth) time 64 bit */
4853 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4856 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4857 SIVAL(pdata, 0, file_flags); /* flags */
4858 SIVAL(pdata, 4, flags_mask); /* mask */
4864 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4865 const struct stream_struct *streams,
4867 unsigned int max_data_bytes,
4868 unsigned int *data_size)
4871 unsigned int ofs = 0;
4873 if (max_data_bytes < 32) {
4874 return NT_STATUS_INFO_LENGTH_MISMATCH;
4877 for (i = 0; i < num_streams; i++) {
4878 unsigned int next_offset;
4880 smb_ucs2_t *namebuf;
4882 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4883 streams[i].name, &namelen) ||
4886 return NT_STATUS_INVALID_PARAMETER;
4890 * name_buf is now null-terminated, we need to marshall as not
4897 * We cannot overflow ...
4899 if ((ofs + 24 + namelen) > max_data_bytes) {
4900 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4902 TALLOC_FREE(namebuf);
4903 return STATUS_BUFFER_OVERFLOW;
4906 SIVAL(data, ofs+4, namelen);
4907 SOFF_T(data, ofs+8, streams[i].size);
4908 SOFF_T(data, ofs+16, streams[i].alloc_size);
4909 memcpy(data+ofs+24, namebuf, namelen);
4910 TALLOC_FREE(namebuf);
4912 next_offset = ofs + 24 + namelen;
4914 if (i == num_streams-1) {
4915 SIVAL(data, ofs, 0);
4918 unsigned int align = ndr_align_size(next_offset, 8);
4920 if ((next_offset + align) > max_data_bytes) {
4921 DEBUG(10, ("refusing to overflow align "
4922 "reply at stream %u\n",
4924 TALLOC_FREE(namebuf);
4925 return STATUS_BUFFER_OVERFLOW;
4928 memset(data+next_offset, 0, align);
4929 next_offset += align;
4931 SIVAL(data, ofs, next_offset - ofs);
4938 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4942 return NT_STATUS_OK;
4945 #if defined(HAVE_POSIX_ACLS)
4946 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4947 struct smb_request *req,
4949 struct smb_filename *smb_fname,
4951 unsigned int data_size_in,
4952 unsigned int *pdata_size_out)
4954 SMB_ACL_T file_acl = NULL;
4955 SMB_ACL_T def_acl = NULL;
4956 uint16_t num_file_acls = 0;
4957 uint16_t num_def_acls = 0;
4958 unsigned int size_needed = 0;
4961 bool close_fsp = false;
4964 * Ensure we always operate on a file descriptor, not just
4968 uint32_t access_mask = SEC_STD_READ_CONTROL|
4969 FILE_READ_ATTRIBUTES|
4970 FILE_WRITE_ATTRIBUTES;
4972 status = get_posix_fsp(conn,
4978 if (!NT_STATUS_IS_OK(status)) {
4984 SMB_ASSERT(fsp != NULL);
4986 status = refuse_symlink(conn,
4989 if (!NT_STATUS_IS_OK(status)) {
4993 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4996 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4997 DBG_INFO("ACLs not implemented on "
4998 "filesystem containing %s\n",
5000 status = NT_STATUS_NOT_IMPLEMENTED;
5004 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5006 * We can only have default POSIX ACLs on
5009 if (!fsp->fsp_flags.is_directory) {
5010 DBG_INFO("Non-directory open %s\n",
5012 status = NT_STATUS_INVALID_HANDLE;
5015 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5017 SMB_ACL_TYPE_DEFAULT,
5019 def_acl = free_empty_sys_acl(conn, def_acl);
5022 num_file_acls = count_acl_entries(conn, file_acl);
5023 num_def_acls = count_acl_entries(conn, def_acl);
5026 if (num_file_acls + num_def_acls < num_file_acls) {
5027 status = NT_STATUS_INVALID_PARAMETER;
5031 size_needed = num_file_acls + num_def_acls;
5034 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5035 * than UINT_MAX, so check by division.
5037 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5038 status = NT_STATUS_INVALID_PARAMETER;
5042 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5043 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5044 status = NT_STATUS_INVALID_PARAMETER;
5047 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5049 if ( data_size_in < size_needed) {
5050 DBG_INFO("data_size too small (%u) need %u\n",
5053 status = NT_STATUS_BUFFER_TOO_SMALL;
5057 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5058 SSVAL(pdata,2,num_file_acls);
5059 SSVAL(pdata,4,num_def_acls);
5060 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5062 ok = marshall_posix_acl(conn,
5067 status = NT_STATUS_INTERNAL_ERROR;
5070 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5072 ok = marshall_posix_acl(conn,
5077 status = NT_STATUS_INTERNAL_ERROR;
5081 *pdata_size_out = size_needed;
5082 status = NT_STATUS_OK;
5088 * Ensure the stat struct in smb_fname is up to
5089 * date. Structure copy.
5091 smb_fname->st = fsp->fsp_name->st;
5092 (void)close_file(req, fsp, NORMAL_CLOSE);
5096 TALLOC_FREE(file_acl);
5097 TALLOC_FREE(def_acl);
5102 /****************************************************************************
5103 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5104 ****************************************************************************/
5106 static void call_trans2qpipeinfo(connection_struct *conn,
5107 struct smb_request *req,
5108 unsigned int tran_call,
5109 char **pparams, int total_params,
5110 char **ppdata, int total_data,
5111 unsigned int max_data_bytes)
5113 char *params = *pparams;
5114 char *pdata = *ppdata;
5115 unsigned int data_size = 0;
5116 unsigned int param_size = 2;
5117 uint16_t info_level;
5121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5125 if (total_params < 4) {
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5130 fsp = file_fsp(req, SVAL(params,0));
5131 if (!fsp_is_np(fsp)) {
5132 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5136 info_level = SVAL(params,2);
5138 *pparams = (char *)SMB_REALLOC(*pparams,2);
5139 if (*pparams == NULL) {
5140 reply_nterror(req, NT_STATUS_NO_MEMORY);
5145 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5149 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5150 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5151 if (*ppdata == NULL ) {
5152 reply_nterror(req, NT_STATUS_NO_MEMORY);
5157 switch (info_level) {
5158 case SMB_FILE_STANDARD_INFORMATION:
5160 SOFF_T(pdata,0,4096LL);
5167 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5171 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5177 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5178 TALLOC_CTX *mem_ctx,
5179 struct smb_request *req,
5180 uint16_t info_level,
5182 struct smb_filename *smb_fname,
5183 bool delete_pending,
5184 struct timespec write_time_ts,
5185 struct ea_list *ea_list,
5186 int lock_data_count,
5189 unsigned int max_data_bytes,
5190 size_t *fixed_portion,
5192 unsigned int *pdata_size)
5194 char *pdata = *ppdata;
5195 char *dstart, *dend;
5196 unsigned int data_size;
5197 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5198 time_t create_time, mtime, atime, c_time;
5199 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5206 uint64_t file_size = 0;
5208 uint64_t allocation_size = 0;
5209 uint64_t file_id = 0;
5210 uint32_t access_mask = 0;
5213 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5214 return NT_STATUS_INVALID_LEVEL;
5217 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5218 smb_fname_str_dbg(smb_fname),
5220 info_level, max_data_bytes));
5222 mode = dos_mode(conn, smb_fname);
5223 nlink = psbuf->st_ex_nlink;
5225 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5229 if ((nlink > 0) && delete_pending) {
5233 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5234 return NT_STATUS_INVALID_PARAMETER;
5237 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5238 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5239 if (*ppdata == NULL) {
5240 return NT_STATUS_NO_MEMORY;
5244 dend = dstart + data_size - 1;
5246 if (!is_omit_timespec(&write_time_ts) &&
5247 !INFO_LEVEL_IS_UNIX(info_level))
5249 update_stat_ex_mtime(psbuf, write_time_ts);
5252 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5253 mtime_ts = psbuf->st_ex_mtime;
5254 atime_ts = psbuf->st_ex_atime;
5255 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5257 if (lp_dos_filetime_resolution(SNUM(conn))) {
5258 dos_filetime_timespec(&create_time_ts);
5259 dos_filetime_timespec(&mtime_ts);
5260 dos_filetime_timespec(&atime_ts);
5261 dos_filetime_timespec(&ctime_ts);
5264 create_time = convert_timespec_to_time_t(create_time_ts);
5265 mtime = convert_timespec_to_time_t(mtime_ts);
5266 atime = convert_timespec_to_time_t(atime_ts);
5267 c_time = convert_timespec_to_time_t(ctime_ts);
5269 p = strrchr_m(smb_fname->base_name,'/');
5271 base_name = smb_fname->base_name;
5275 /* NT expects the name to be in an exact form of the *full*
5276 filename. See the trans2 torture test */
5277 if (ISDOT(base_name)) {
5278 dos_fname = talloc_strdup(mem_ctx, "\\");
5280 return NT_STATUS_NO_MEMORY;
5283 dos_fname = talloc_asprintf(mem_ctx,
5285 smb_fname->base_name);
5287 return NT_STATUS_NO_MEMORY;
5289 if (is_ntfs_stream_smb_fname(smb_fname)) {
5290 dos_fname = talloc_asprintf(dos_fname, "%s",
5291 smb_fname->stream_name);
5293 return NT_STATUS_NO_MEMORY;
5297 string_replace(dos_fname, '/', '\\');
5300 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5303 /* Do we have this path open ? */
5305 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5306 fsp1 = file_find_di_first(conn->sconn, fileid);
5307 if (fsp1 && fsp1->initial_allocation_size) {
5308 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5312 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5313 file_size = get_file_size_stat(psbuf);
5317 pos = fsp->fh->position_information;
5321 access_mask = fsp->access_mask;
5323 /* GENERIC_EXECUTE mapping from Windows */
5324 access_mask = 0x12019F;
5327 /* This should be an index number - looks like
5330 I think this causes us to fail the IFSKIT
5331 BasicFileInformationTest. -tpot */
5332 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5336 switch (info_level) {
5337 case SMB_INFO_STANDARD:
5338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5340 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5341 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5342 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5343 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5344 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5345 SSVAL(pdata,l1_attrFile,mode);
5348 case SMB_INFO_QUERY_EA_SIZE:
5350 unsigned int ea_size =
5351 estimate_ea_size(conn, fsp,
5353 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5355 srv_put_dos_date2(pdata,0,create_time);
5356 srv_put_dos_date2(pdata,4,atime);
5357 srv_put_dos_date2(pdata,8,mtime); /* write time */
5358 SIVAL(pdata,12,(uint32_t)file_size);
5359 SIVAL(pdata,16,(uint32_t)allocation_size);
5360 SSVAL(pdata,20,mode);
5361 SIVAL(pdata,22,ea_size);
5365 case SMB_INFO_IS_NAME_VALID:
5366 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5368 /* os/2 needs this ? really ?*/
5369 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5371 /* This is only reached for qpathinfo */
5375 case SMB_INFO_QUERY_EAS_FROM_LIST:
5377 size_t total_ea_len = 0;
5378 struct ea_list *ea_file_list = NULL;
5379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5382 get_ea_list_from_file(mem_ctx, conn, fsp,
5384 &total_ea_len, &ea_file_list);
5385 if (!NT_STATUS_IS_OK(status)) {
5389 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5391 if (!ea_list || (total_ea_len > data_size)) {
5393 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5397 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5401 case SMB_INFO_QUERY_ALL_EAS:
5403 /* We have data_size bytes to put EA's into. */
5404 size_t total_ea_len = 0;
5405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5407 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5409 &total_ea_len, &ea_list);
5410 if (!NT_STATUS_IS_OK(status)) {
5414 if (!ea_list || (total_ea_len > data_size)) {
5416 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5420 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5424 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5426 /* This is FileFullEaInformation - 0xF which maps to
5427 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5429 /* We have data_size bytes to put EA's into. */
5430 size_t total_ea_len = 0;
5431 struct ea_list *ea_file_list = NULL;
5433 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5435 /*TODO: add filtering and index handling */
5438 get_ea_list_from_file(mem_ctx, conn, fsp,
5440 &total_ea_len, &ea_file_list);
5441 if (!NT_STATUS_IS_OK(status)) {
5444 if (!ea_file_list) {
5445 return NT_STATUS_NO_EAS_ON_FILE;
5448 status = fill_ea_chained_buffer(mem_ctx,
5452 conn, ea_file_list);
5453 if (!NT_STATUS_IS_OK(status)) {
5459 case SMB_FILE_BASIC_INFORMATION:
5460 case SMB_QUERY_FILE_BASIC_INFO:
5462 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5464 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5470 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5471 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5472 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5473 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5474 SIVAL(pdata,32,mode);
5476 DEBUG(5,("SMB_QFBI - "));
5477 DEBUG(5,("create: %s ", ctime(&create_time)));
5478 DEBUG(5,("access: %s ", ctime(&atime)));
5479 DEBUG(5,("write: %s ", ctime(&mtime)));
5480 DEBUG(5,("change: %s ", ctime(&c_time)));
5481 DEBUG(5,("mode: %x\n", mode));
5482 *fixed_portion = data_size;
5485 case SMB_FILE_STANDARD_INFORMATION:
5486 case SMB_QUERY_FILE_STANDARD_INFO:
5488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5490 SOFF_T(pdata,0,allocation_size);
5491 SOFF_T(pdata,8,file_size);
5492 SIVAL(pdata,16,nlink);
5493 SCVAL(pdata,20,delete_pending?1:0);
5494 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5495 SSVAL(pdata,22,0); /* Padding. */
5496 *fixed_portion = 24;
5499 case SMB_FILE_EA_INFORMATION:
5500 case SMB_QUERY_FILE_EA_INFO:
5502 unsigned int ea_size =
5503 estimate_ea_size(conn, fsp, smb_fname);
5504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5507 SIVAL(pdata,0,ea_size);
5511 /* Get the 8.3 name - used if NT SMB was negotiated. */
5512 case SMB_QUERY_FILE_ALT_NAME_INFO:
5513 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5515 char mangled_name[13];
5516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5517 if (!name_to_8_3(base_name,mangled_name,
5518 True,conn->params)) {
5519 return NT_STATUS_NO_MEMORY;
5521 status = srvstr_push(dstart, flags2,
5522 pdata+4, mangled_name,
5523 PTR_DIFF(dend, pdata+4),
5525 if (!NT_STATUS_IS_OK(status)) {
5528 data_size = 4 + len;
5534 case SMB_QUERY_FILE_NAME_INFO:
5537 this must be *exactly* right for ACLs on mapped drives to work
5539 status = srvstr_push(dstart, flags2,
5541 PTR_DIFF(dend, pdata+4),
5543 if (!NT_STATUS_IS_OK(status)) {
5546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5547 data_size = 4 + len;
5552 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5554 char *nfname = NULL;
5556 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5557 return NT_STATUS_INVALID_LEVEL;
5560 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5561 if (nfname == NULL) {
5562 return NT_STATUS_NO_MEMORY;
5565 if (ISDOT(nfname)) {
5568 string_replace(nfname, '/', '\\');
5570 if (smb_fname->stream_name != NULL) {
5571 const char *s = smb_fname->stream_name;
5572 const char *e = NULL;
5575 SMB_ASSERT(s[0] != '\0');
5578 * smb_fname->stream_name is in form
5579 * of ':StrEam:$DATA', but we should only
5580 * append ':StrEam' here.
5583 e = strchr(&s[1], ':');
5589 nfname = talloc_strndup_append(nfname, s, n);
5590 if (nfname == NULL) {
5591 return NT_STATUS_NO_MEMORY;
5595 status = srvstr_push(dstart, flags2,
5597 PTR_DIFF(dend, pdata+4),
5599 if (!NT_STATUS_IS_OK(status)) {
5602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5603 data_size = 4 + len;
5609 case SMB_FILE_ALLOCATION_INFORMATION:
5610 case SMB_QUERY_FILE_ALLOCATION_INFO:
5611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5613 SOFF_T(pdata,0,allocation_size);
5616 case SMB_FILE_END_OF_FILE_INFORMATION:
5617 case SMB_QUERY_FILE_END_OF_FILEINFO:
5618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5620 SOFF_T(pdata,0,file_size);
5623 case SMB_QUERY_FILE_ALL_INFO:
5624 case SMB_FILE_ALL_INFORMATION:
5626 unsigned int ea_size =
5627 estimate_ea_size(conn, fsp, smb_fname);
5628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5629 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5630 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5631 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5632 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5633 SIVAL(pdata,32,mode);
5634 SIVAL(pdata,36,0); /* padding. */
5636 SOFF_T(pdata,0,allocation_size);
5637 SOFF_T(pdata,8,file_size);
5638 SIVAL(pdata,16,nlink);
5639 SCVAL(pdata,20,delete_pending);
5640 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5643 SIVAL(pdata,0,ea_size);
5644 pdata += 4; /* EA info */
5645 status = srvstr_push(dstart, flags2,
5647 PTR_DIFF(dend, pdata+4),
5649 if (!NT_STATUS_IS_OK(status)) {
5654 data_size = PTR_DIFF(pdata,(*ppdata));
5655 *fixed_portion = 10;
5659 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5661 unsigned int ea_size =
5662 estimate_ea_size(conn, fsp, smb_fname);
5663 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5664 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5665 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5666 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5667 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5668 SIVAL(pdata, 0x20, mode);
5669 SIVAL(pdata, 0x24, 0); /* padding. */
5670 SBVAL(pdata, 0x28, allocation_size);
5671 SBVAL(pdata, 0x30, file_size);
5672 SIVAL(pdata, 0x38, nlink);
5673 SCVAL(pdata, 0x3C, delete_pending);
5674 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5675 SSVAL(pdata, 0x3E, 0); /* padding */
5676 SBVAL(pdata, 0x40, file_id);
5677 SIVAL(pdata, 0x48, ea_size);
5678 SIVAL(pdata, 0x4C, access_mask);
5679 SBVAL(pdata, 0x50, pos);
5680 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5681 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5685 status = srvstr_push(dstart, flags2,
5687 PTR_DIFF(dend, pdata+4),
5689 if (!NT_STATUS_IS_OK(status)) {
5694 data_size = PTR_DIFF(pdata,(*ppdata));
5695 *fixed_portion = 104;
5698 case SMB_FILE_INTERNAL_INFORMATION:
5700 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5701 SBVAL(pdata, 0, file_id);
5706 case SMB_FILE_ACCESS_INFORMATION:
5707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5708 SIVAL(pdata, 0, access_mask);
5713 case SMB_FILE_NAME_INFORMATION:
5714 /* Pathname with leading '\'. */
5717 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5719 SIVAL(pdata,0,byte_len);
5720 data_size = 4 + byte_len;
5724 case SMB_FILE_DISPOSITION_INFORMATION:
5725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5727 SCVAL(pdata,0,delete_pending);
5731 case SMB_FILE_POSITION_INFORMATION:
5732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5734 SOFF_T(pdata,0,pos);
5738 case SMB_FILE_MODE_INFORMATION:
5739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5740 SIVAL(pdata,0,mode);
5745 case SMB_FILE_ALIGNMENT_INFORMATION:
5746 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5747 SIVAL(pdata,0,0); /* No alignment needed. */
5753 * NT4 server just returns "invalid query" to this - if we try
5754 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5757 /* The first statement above is false - verified using Thursby
5758 * client against NT4 -- gcolley.
5760 case SMB_QUERY_FILE_STREAM_INFO:
5761 case SMB_FILE_STREAM_INFORMATION: {
5762 unsigned int num_streams = 0;
5763 struct stream_struct *streams = NULL;
5765 DEBUG(10,("smbd_do_qfilepathinfo: "
5766 "SMB_FILE_STREAM_INFORMATION\n"));
5768 if (is_ntfs_stream_smb_fname(smb_fname)) {
5769 return NT_STATUS_INVALID_PARAMETER;
5772 status = vfs_streaminfo(conn,
5779 if (!NT_STATUS_IS_OK(status)) {
5780 DEBUG(10, ("could not get stream info: %s\n",
5781 nt_errstr(status)));
5785 status = marshall_stream_info(num_streams, streams,
5786 pdata, max_data_bytes,
5789 if (!NT_STATUS_IS_OK(status)) {
5790 DEBUG(10, ("marshall_stream_info failed: %s\n",
5791 nt_errstr(status)));
5792 TALLOC_FREE(streams);
5796 TALLOC_FREE(streams);
5798 *fixed_portion = 32;
5802 case SMB_QUERY_COMPRESSION_INFO:
5803 case SMB_FILE_COMPRESSION_INFORMATION:
5804 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5805 SOFF_T(pdata,0,file_size);
5806 SIVAL(pdata,8,0); /* ??? */
5807 SIVAL(pdata,12,0); /* ??? */
5809 *fixed_portion = 16;
5812 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5814 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5815 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5816 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5817 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5818 SOFF_T(pdata,32,allocation_size);
5819 SOFF_T(pdata,40,file_size);
5820 SIVAL(pdata,48,mode);
5821 SIVAL(pdata,52,0); /* ??? */
5823 *fixed_portion = 56;
5826 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5827 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5828 SIVAL(pdata,0,mode);
5835 * CIFS UNIX Extensions.
5838 case SMB_QUERY_FILE_UNIX_BASIC:
5840 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5841 data_size = PTR_DIFF(pdata,(*ppdata));
5843 DEBUG(4,("smbd_do_qfilepathinfo: "
5844 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5845 dump_data(4, (uint8_t *)(*ppdata), data_size);
5849 case SMB_QUERY_FILE_UNIX_INFO2:
5851 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5852 data_size = PTR_DIFF(pdata,(*ppdata));
5856 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5858 for (i=0; i<100; i++)
5859 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5865 case SMB_QUERY_FILE_UNIX_LINK:
5868 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5871 return NT_STATUS_NO_MEMORY;
5874 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5876 if(!S_ISLNK(psbuf->st_ex_mode)) {
5877 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5880 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5882 link_len = SMB_VFS_READLINKAT(conn,
5888 if (link_len == -1) {
5889 return map_nt_error_from_unix(errno);
5891 buffer[link_len] = 0;
5892 status = srvstr_push(dstart, flags2,
5894 PTR_DIFF(dend, pdata),
5895 STR_TERMINATE, &len);
5896 if (!NT_STATUS_IS_OK(status)) {
5900 data_size = PTR_DIFF(pdata,(*ppdata));
5905 #if defined(HAVE_POSIX_ACLS)
5906 case SMB_QUERY_POSIX_ACL:
5908 status = smb_query_posix_acl(conn,
5915 if (!NT_STATUS_IS_OK(status)) {
5923 case SMB_QUERY_POSIX_LOCK:
5928 enum brl_type lock_type;
5930 /* We need an open file with a real fd for this. */
5931 if (!fsp || fsp->fh->fd == -1) {
5932 return NT_STATUS_INVALID_LEVEL;
5935 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5936 return NT_STATUS_INVALID_PARAMETER;
5939 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5940 case POSIX_LOCK_TYPE_READ:
5941 lock_type = READ_LOCK;
5943 case POSIX_LOCK_TYPE_WRITE:
5944 lock_type = WRITE_LOCK;
5946 case POSIX_LOCK_TYPE_UNLOCK:
5948 /* There's no point in asking for an unlock... */
5949 return NT_STATUS_INVALID_PARAMETER;
5952 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5953 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5954 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5956 status = query_lock(fsp,
5963 if (ERROR_WAS_LOCK_DENIED(status)) {
5964 /* Here we need to report who has it locked... */
5965 data_size = POSIX_LOCK_DATA_SIZE;
5967 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5968 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5969 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5970 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5971 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5973 } else if (NT_STATUS_IS_OK(status)) {
5974 /* For success we just return a copy of what we sent
5975 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5976 data_size = POSIX_LOCK_DATA_SIZE;
5977 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5978 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5986 return NT_STATUS_INVALID_LEVEL;
5989 *pdata_size = data_size;
5990 return NT_STATUS_OK;
5993 /****************************************************************************
5994 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5995 file name or file id).
5996 ****************************************************************************/
5998 static void call_trans2qfilepathinfo(connection_struct *conn,
5999 struct smb_request *req,
6000 unsigned int tran_call,
6001 char **pparams, int total_params,
6002 char **ppdata, int total_data,
6003 unsigned int max_data_bytes)
6005 char *params = *pparams;
6006 char *pdata = *ppdata;
6007 uint16_t info_level;
6008 unsigned int data_size = 0;
6009 unsigned int param_size = 2;
6010 struct smb_filename *smb_fname = NULL;
6011 bool delete_pending = False;
6012 struct timespec write_time_ts;
6013 files_struct *fsp = NULL;
6014 struct file_id fileid;
6015 struct ea_list *ea_list = NULL;
6016 int lock_data_count = 0;
6017 char *lock_data = NULL;
6018 size_t fixed_portion;
6019 NTSTATUS status = NT_STATUS_OK;
6022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6026 ZERO_STRUCT(write_time_ts);
6028 if (tran_call == TRANSACT2_QFILEINFO) {
6029 if (total_params < 4) {
6030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6035 call_trans2qpipeinfo(conn, req, tran_call,
6036 pparams, total_params,
6042 fsp = file_fsp(req, SVAL(params,0));
6043 info_level = SVAL(params,2);
6045 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6047 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6052 /* Initial check for valid fsp ptr. */
6053 if (!check_fsp_open(conn, req, fsp)) {
6057 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6058 if (smb_fname == NULL) {
6059 reply_nterror(req, NT_STATUS_NO_MEMORY);
6063 if(fsp->fake_file_handle) {
6065 * This is actually for the QUOTA_FAKE_FILE --metze
6068 /* We know this name is ok, it's already passed the checks. */
6070 } else if(fsp->fh->fd == -1) {
6072 * This is actually a QFILEINFO on a directory
6073 * handle (returned from an NT SMB). NT5.0 seems
6074 * to do this call. JRA.
6077 if (INFO_LEVEL_IS_UNIX(info_level)) {
6078 /* Always do lstat for UNIX calls. */
6079 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6080 DEBUG(3,("call_trans2qfilepathinfo: "
6081 "SMB_VFS_LSTAT of %s failed "
6083 smb_fname_str_dbg(smb_fname),
6086 map_nt_error_from_unix(errno));
6089 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6090 DEBUG(3,("call_trans2qfilepathinfo: "
6091 "SMB_VFS_STAT of %s failed (%s)\n",
6092 smb_fname_str_dbg(smb_fname),
6095 map_nt_error_from_unix(errno));
6099 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6100 fileid = vfs_file_id_from_sbuf(
6101 conn, &smb_fname->st);
6102 get_file_infos(fileid, fsp->name_hash,
6108 * Original code - this is an open file.
6110 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6111 DEBUG(3, ("fstat of %s failed (%s)\n",
6112 fsp_fnum_dbg(fsp), strerror(errno)));
6114 map_nt_error_from_unix(errno));
6117 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6118 fileid = vfs_file_id_from_sbuf(
6119 conn, &smb_fname->st);
6120 get_file_infos(fileid, fsp->name_hash,
6129 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6132 if (total_params < 7) {
6133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6137 info_level = SVAL(params,0);
6139 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6141 if (INFO_LEVEL_IS_UNIX(info_level)) {
6142 if (!lp_unix_extensions()) {
6143 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6146 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6147 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6148 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6149 req->posix_pathnames) {
6150 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6154 if (req->posix_pathnames) {
6155 srvstr_get_path_posix(req,
6164 srvstr_get_path(req,
6173 if (!NT_STATUS_IS_OK(status)) {
6174 reply_nterror(req, status);
6178 status = filename_convert(req,
6184 if (!NT_STATUS_IS_OK(status)) {
6185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6186 reply_botherror(req,
6187 NT_STATUS_PATH_NOT_COVERED,
6188 ERRSRV, ERRbadpath);
6191 reply_nterror(req, status);
6195 /* If this is a stream, check if there is a delete_pending. */
6196 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6197 && is_ntfs_stream_smb_fname(smb_fname)) {
6198 struct smb_filename *smb_fname_base;
6200 /* Create an smb_filename with stream_name == NULL. */
6201 smb_fname_base = synthetic_smb_fname(
6203 smb_fname->base_name,
6208 if (smb_fname_base == NULL) {
6209 reply_nterror(req, NT_STATUS_NO_MEMORY);
6213 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6214 /* Always do lstat for UNIX calls. */
6215 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6216 DEBUG(3,("call_trans2qfilepathinfo: "
6217 "SMB_VFS_LSTAT of %s failed "
6219 smb_fname_str_dbg(smb_fname_base),
6221 TALLOC_FREE(smb_fname_base);
6223 map_nt_error_from_unix(errno));
6227 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6228 DEBUG(3,("call_trans2qfilepathinfo: "
6229 "fileinfo of %s failed "
6231 smb_fname_str_dbg(smb_fname_base),
6233 TALLOC_FREE(smb_fname_base);
6235 map_nt_error_from_unix(errno));
6240 status = file_name_hash(conn,
6241 smb_fname_str_dbg(smb_fname_base),
6243 if (!NT_STATUS_IS_OK(status)) {
6244 TALLOC_FREE(smb_fname_base);
6245 reply_nterror(req, status);
6249 fileid = vfs_file_id_from_sbuf(conn,
6250 &smb_fname_base->st);
6251 TALLOC_FREE(smb_fname_base);
6252 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6253 if (delete_pending) {
6254 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6259 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6260 /* Always do lstat for UNIX calls. */
6261 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6262 DEBUG(3,("call_trans2qfilepathinfo: "
6263 "SMB_VFS_LSTAT of %s failed (%s)\n",
6264 smb_fname_str_dbg(smb_fname),
6267 map_nt_error_from_unix(errno));
6272 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6273 DEBUG(3,("call_trans2qfilepathinfo: "
6274 "SMB_VFS_STAT of %s failed (%s)\n",
6275 smb_fname_str_dbg(smb_fname),
6278 map_nt_error_from_unix(errno));
6283 status = file_name_hash(conn,
6284 smb_fname_str_dbg(smb_fname),
6286 if (!NT_STATUS_IS_OK(status)) {
6287 reply_nterror(req, status);
6291 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6292 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6293 get_file_infos(fileid, name_hash, &delete_pending,
6297 if (delete_pending) {
6298 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6303 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6304 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6306 info_level,tran_call,total_data));
6308 /* Pull out any data sent here before we realloc. */
6309 switch (info_level) {
6310 case SMB_INFO_QUERY_EAS_FROM_LIST:
6312 /* Pull any EA list from the data portion. */
6315 if (total_data < 4) {
6317 req, NT_STATUS_INVALID_PARAMETER);
6320 ea_size = IVAL(pdata,0);
6322 if (total_data > 0 && ea_size != total_data) {
6323 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6324 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6326 req, NT_STATUS_INVALID_PARAMETER);
6330 if (!lp_ea_support(SNUM(conn))) {
6331 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6335 /* Pull out the list of names. */
6336 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6339 req, NT_STATUS_INVALID_PARAMETER);
6345 case SMB_QUERY_POSIX_LOCK:
6347 if (fsp == NULL || fsp->fh->fd == -1) {
6348 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6352 if (total_data != POSIX_LOCK_DATA_SIZE) {
6354 req, NT_STATUS_INVALID_PARAMETER);
6358 /* Copy the lock range data. */
6359 lock_data = (char *)talloc_memdup(
6360 req, pdata, total_data);
6362 reply_nterror(req, NT_STATUS_NO_MEMORY);
6365 lock_data_count = total_data;
6371 *pparams = (char *)SMB_REALLOC(*pparams,2);
6372 if (*pparams == NULL) {
6373 reply_nterror(req, NT_STATUS_NO_MEMORY);
6380 * draft-leach-cifs-v1-spec-02.txt
6381 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6384 * The requested information is placed in the Data portion of the
6385 * transaction response. For the information levels greater than 0x100,
6386 * the transaction response has 1 parameter word which should be
6387 * ignored by the client.
6389 * However Windows only follows this rule for the IS_NAME_VALID call.
6391 switch (info_level) {
6392 case SMB_INFO_IS_NAME_VALID:
6397 if ((info_level & 0xFF00) == 0xFF00) {
6399 * We use levels that start with 0xFF00
6400 * internally to represent SMB2 specific levels
6402 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6406 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6408 delete_pending, write_time_ts,
6410 lock_data_count, lock_data,
6411 req->flags2, max_data_bytes,
6413 ppdata, &data_size);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 if (open_was_deferred(req->xconn, req->mid)) {
6416 /* We have re-scheduled this call. */
6419 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6420 bool ok = defer_smb1_sharing_violation(req);
6425 reply_nterror(req, status);
6428 if (fixed_portion > max_data_bytes) {
6429 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6433 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6439 /****************************************************************************
6440 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6442 ****************************************************************************/
6444 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6445 connection_struct *conn,
6446 struct smb_request *req,
6447 bool overwrite_if_exists,
6448 const struct smb_filename *smb_fname_old,
6449 struct smb_filename *smb_fname_new)
6451 NTSTATUS status = NT_STATUS_OK;
6455 /* source must already exist. */
6456 if (!VALID_STAT(smb_fname_old->st)) {
6457 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6460 if (VALID_STAT(smb_fname_new->st)) {
6461 if (overwrite_if_exists) {
6462 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6463 return NT_STATUS_FILE_IS_A_DIRECTORY;
6465 status = unlink_internals(conn,
6467 FILE_ATTRIBUTE_NORMAL,
6469 if (!NT_STATUS_IS_OK(status)) {
6473 /* Disallow if newname already exists. */
6474 return NT_STATUS_OBJECT_NAME_COLLISION;
6478 /* No links from a directory. */
6479 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6480 return NT_STATUS_FILE_IS_A_DIRECTORY;
6483 /* Setting a hardlink to/from a stream isn't currently supported. */
6484 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6486 DBG_DEBUG("Old name has streams\n");
6487 return NT_STATUS_INVALID_PARAMETER;
6489 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6491 DBG_DEBUG("New name has streams\n");
6492 return NT_STATUS_INVALID_PARAMETER;
6495 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6496 smb_fname_old->base_name, smb_fname_new->base_name));
6498 ret = SMB_VFS_LINKAT(conn,
6506 status = map_nt_error_from_unix(errno);
6507 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6508 nt_errstr(status), smb_fname_old->base_name,
6509 smb_fname_new->base_name));
6514 /****************************************************************************
6515 Deal with setting the time from any of the setfilepathinfo functions.
6516 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6517 calling this function.
6518 ****************************************************************************/
6520 NTSTATUS smb_set_file_time(connection_struct *conn,
6522 const struct smb_filename *smb_fname,
6523 struct smb_file_time *ft,
6524 bool setting_write_time)
6526 struct smb_filename smb_fname_base;
6527 struct timeval_buf tbuf[4];
6529 FILE_NOTIFY_CHANGE_LAST_ACCESS
6530 |FILE_NOTIFY_CHANGE_LAST_WRITE
6531 |FILE_NOTIFY_CHANGE_CREATION;
6533 if (!VALID_STAT(smb_fname->st)) {
6534 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6537 /* get some defaults (no modifications) if any info is zero or -1. */
6538 if (is_omit_timespec(&ft->create_time)) {
6539 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6542 if (is_omit_timespec(&ft->atime)) {
6543 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6546 if (is_omit_timespec(&ft->mtime)) {
6547 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6550 if (!setting_write_time) {
6551 /* ft->mtime comes from change time, not write time. */
6552 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6555 /* Ensure the resolution is the correct for
6556 * what we can store on this filesystem. */
6558 round_timespec(conn->ts_res, &ft->create_time);
6559 round_timespec(conn->ts_res, &ft->ctime);
6560 round_timespec(conn->ts_res, &ft->atime);
6561 round_timespec(conn->ts_res, &ft->mtime);
6563 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6564 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6565 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6566 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6567 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6568 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6569 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6570 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6572 if (setting_write_time) {
6574 * This was a Windows setfileinfo on an open file.
6575 * NT does this a lot. We also need to
6576 * set the time here, as it can be read by
6577 * FindFirst/FindNext and with the patch for bug #2045
6578 * in smbd/fileio.c it ensures that this timestamp is
6579 * kept sticky even after a write. We save the request
6580 * away and will set it on file close and after a write. JRA.
6583 DBG_DEBUG("setting pending modtime to %s\n",
6584 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6587 if (fsp->base_fsp) {
6588 set_sticky_write_time_fsp(fsp->base_fsp,
6591 set_sticky_write_time_fsp(fsp, ft->mtime);
6594 set_sticky_write_time_path(
6595 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6600 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6602 /* Always call ntimes on the base, even if a stream was passed in. */
6603 smb_fname_base = *smb_fname;
6604 smb_fname_base.stream_name = NULL;
6606 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6607 return map_nt_error_from_unix(errno);
6610 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6611 smb_fname->base_name);
6612 return NT_STATUS_OK;
6615 /****************************************************************************
6616 Deal with setting the dosmode from any of the setfilepathinfo functions.
6617 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6618 done before calling this function.
6619 ****************************************************************************/
6621 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6622 const struct smb_filename *smb_fname,
6625 struct smb_filename *smb_fname_base;
6628 if (!VALID_STAT(smb_fname->st)) {
6629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6632 /* Always operate on the base_name, even if a stream was passed in. */
6633 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6634 smb_fname->base_name,
6639 if (smb_fname_base == NULL) {
6640 return NT_STATUS_NO_MEMORY;
6644 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6645 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6647 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6651 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6653 /* check the mode isn't different, before changing it */
6654 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6655 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6656 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6657 (unsigned int)dosmode));
6659 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6661 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6663 smb_fname_str_dbg(smb_fname_base),
6665 status = map_nt_error_from_unix(errno);
6669 status = NT_STATUS_OK;
6671 TALLOC_FREE(smb_fname_base);
6675 /****************************************************************************
6676 Deal with setting the size from any of the setfilepathinfo functions.
6677 ****************************************************************************/
6679 static NTSTATUS smb_set_file_size(connection_struct *conn,
6680 struct smb_request *req,
6682 const struct smb_filename *smb_fname,
6683 const SMB_STRUCT_STAT *psbuf,
6685 bool fail_after_createfile)
6687 NTSTATUS status = NT_STATUS_OK;
6688 struct smb_filename *smb_fname_tmp = NULL;
6689 files_struct *new_fsp = NULL;
6691 if (!VALID_STAT(*psbuf)) {
6692 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6695 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6697 get_file_size_stat(psbuf));
6699 if (size == get_file_size_stat(psbuf)) {
6701 return NT_STATUS_OK;
6703 if (!fsp->fsp_flags.modified) {
6704 return NT_STATUS_OK;
6706 trigger_write_time_update_immediate(fsp);
6707 return NT_STATUS_OK;
6710 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6711 smb_fname_str_dbg(smb_fname), (double)size));
6713 if (fsp && fsp->fh->fd != -1) {
6714 /* Handle based call. */
6715 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6716 return NT_STATUS_ACCESS_DENIED;
6719 if (vfs_set_filelen(fsp, size) == -1) {
6720 return map_nt_error_from_unix(errno);
6722 trigger_write_time_update_immediate(fsp);
6723 return NT_STATUS_OK;
6726 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6727 if (smb_fname_tmp == NULL) {
6728 return NT_STATUS_NO_MEMORY;
6731 smb_fname_tmp->st = *psbuf;
6733 status = SMB_VFS_CREATE_FILE(
6736 smb_fname_tmp, /* fname */
6737 FILE_WRITE_DATA, /* access_mask */
6738 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6740 FILE_OPEN, /* create_disposition*/
6741 0, /* create_options */
6742 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6743 0, /* oplock_request */
6745 0, /* allocation_size */
6746 0, /* private_flags */
6749 &new_fsp, /* result */
6751 NULL, NULL); /* create context */
6753 TALLOC_FREE(smb_fname_tmp);
6755 if (!NT_STATUS_IS_OK(status)) {
6756 /* NB. We check for open_was_deferred in the caller. */
6760 /* See RAW-SFILEINFO-END-OF-FILE */
6761 if (fail_after_createfile) {
6762 close_file(req, new_fsp,NORMAL_CLOSE);
6763 return NT_STATUS_INVALID_LEVEL;
6766 if (vfs_set_filelen(new_fsp, size) == -1) {
6767 status = map_nt_error_from_unix(errno);
6768 close_file(req, new_fsp,NORMAL_CLOSE);
6772 trigger_write_time_update_immediate(new_fsp);
6773 close_file(req, new_fsp,NORMAL_CLOSE);
6774 return NT_STATUS_OK;
6777 /****************************************************************************
6778 Deal with SMB_INFO_SET_EA.
6779 ****************************************************************************/
6781 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6785 const struct smb_filename *smb_fname)
6787 struct ea_list *ea_list = NULL;
6788 TALLOC_CTX *ctx = NULL;
6789 NTSTATUS status = NT_STATUS_OK;
6791 if (total_data < 10) {
6793 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6794 length. They seem to have no effect. Bug #3212. JRA */
6796 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6797 /* We're done. We only get EA info in this call. */
6798 return NT_STATUS_OK;
6801 return NT_STATUS_INVALID_PARAMETER;
6804 if (IVAL(pdata,0) > total_data) {
6805 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6806 IVAL(pdata,0), (unsigned int)total_data));
6807 return NT_STATUS_INVALID_PARAMETER;
6811 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6813 return NT_STATUS_INVALID_PARAMETER;
6816 status = set_ea(conn, fsp, smb_fname, ea_list);
6821 /****************************************************************************
6822 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6823 ****************************************************************************/
6825 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6830 struct ea_list *ea_list = NULL;
6834 return NT_STATUS_INVALID_HANDLE;
6837 if (!lp_ea_support(SNUM(conn))) {
6838 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6839 "EA's not supported.\n",
6840 (unsigned int)total_data));
6841 return NT_STATUS_EAS_NOT_SUPPORTED;
6844 if (total_data < 10) {
6845 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6847 (unsigned int)total_data));
6848 return NT_STATUS_INVALID_PARAMETER;
6851 ea_list = read_nttrans_ea_list(talloc_tos(),
6856 return NT_STATUS_INVALID_PARAMETER;
6859 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6861 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6862 smb_fname_str_dbg(fsp->fsp_name),
6863 nt_errstr(status) ));
6869 /****************************************************************************
6870 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6871 ****************************************************************************/
6873 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6877 struct smb_filename *smb_fname)
6879 NTSTATUS status = NT_STATUS_OK;
6880 bool delete_on_close;
6881 uint32_t dosmode = 0;
6883 if (total_data < 1) {
6884 return NT_STATUS_INVALID_PARAMETER;
6888 return NT_STATUS_INVALID_HANDLE;
6891 delete_on_close = (CVAL(pdata,0) ? True : False);
6892 dosmode = dos_mode(conn, smb_fname);
6894 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6895 "delete_on_close = %u\n",
6896 smb_fname_str_dbg(smb_fname),
6897 (unsigned int)dosmode,
6898 (unsigned int)delete_on_close ));
6900 if (delete_on_close) {
6901 status = can_set_delete_on_close(fsp, dosmode);
6902 if (!NT_STATUS_IS_OK(status)) {
6907 /* The set is across all open files on this dev/inode pair. */
6908 if (!set_delete_on_close(fsp, delete_on_close,
6909 conn->session_info->security_token,
6910 conn->session_info->unix_token)) {
6911 return NT_STATUS_ACCESS_DENIED;
6913 return NT_STATUS_OK;
6916 /****************************************************************************
6917 Deal with SMB_FILE_POSITION_INFORMATION.
6918 ****************************************************************************/
6920 static NTSTATUS smb_file_position_information(connection_struct *conn,
6925 uint64_t position_information;
6927 if (total_data < 8) {
6928 return NT_STATUS_INVALID_PARAMETER;
6932 /* Ignore on pathname based set. */
6933 return NT_STATUS_OK;
6936 position_information = (uint64_t)IVAL(pdata,0);
6937 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6939 DEBUG(10,("smb_file_position_information: Set file position "
6940 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6941 (double)position_information));
6942 fsp->fh->position_information = position_information;
6943 return NT_STATUS_OK;
6946 /****************************************************************************
6947 Deal with SMB_FILE_MODE_INFORMATION.
6948 ****************************************************************************/
6950 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6956 if (total_data < 4) {
6957 return NT_STATUS_INVALID_PARAMETER;
6959 mode = IVAL(pdata,0);
6960 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6961 return NT_STATUS_INVALID_PARAMETER;
6963 return NT_STATUS_OK;
6966 /****************************************************************************
6967 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6968 ****************************************************************************/
6970 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6971 struct smb_request *req,
6974 const struct smb_filename *new_smb_fname)
6976 char *link_target = NULL;
6977 struct smb_filename target_fname;
6978 TALLOC_CTX *ctx = talloc_tos();
6982 /* Set a symbolic link. */
6983 /* Don't allow this if follow links is false. */
6985 if (total_data == 0) {
6986 return NT_STATUS_INVALID_PARAMETER;
6989 if (!lp_follow_symlinks(SNUM(conn))) {
6990 return NT_STATUS_ACCESS_DENIED;
6993 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6994 total_data, STR_TERMINATE);
6997 return NT_STATUS_INVALID_PARAMETER;
7000 target_fname = (struct smb_filename) {
7001 .base_name = link_target,
7004 /* Removes @GMT tokens if any */
7005 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7006 if (!NT_STATUS_IS_OK(status)) {
7010 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7011 new_smb_fname->base_name, link_target ));
7013 ret = SMB_VFS_SYMLINKAT(conn,
7018 return map_nt_error_from_unix(errno);
7021 return NT_STATUS_OK;
7024 /****************************************************************************
7025 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7026 ****************************************************************************/
7028 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7029 struct smb_request *req,
7030 const char *pdata, int total_data,
7031 struct smb_filename *smb_fname_new)
7033 char *oldname = NULL;
7034 struct smb_filename *smb_fname_old = NULL;
7035 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7036 TALLOC_CTX *ctx = talloc_tos();
7037 NTSTATUS status = NT_STATUS_OK;
7039 /* Set a hard link. */
7040 if (total_data == 0) {
7041 return NT_STATUS_INVALID_PARAMETER;
7044 if (req->posix_pathnames) {
7045 srvstr_get_path_posix(ctx,
7054 srvstr_get_path(ctx,
7063 if (!NT_STATUS_IS_OK(status)) {
7067 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7068 smb_fname_str_dbg(smb_fname_new), oldname));
7070 status = filename_convert(ctx,
7076 if (!NT_STATUS_IS_OK(status)) {
7080 return hardlink_internals(ctx, conn, req, false,
7081 smb_fname_old, smb_fname_new);
7084 /****************************************************************************
7085 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7086 ****************************************************************************/
7088 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7089 struct smb_request *req,
7093 struct smb_filename *smb_fname_src)
7097 char *newname = NULL;
7098 struct smb_filename *smb_fname_dst = NULL;
7099 const char *dst_original_lcomp = NULL;
7100 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7101 NTSTATUS status = NT_STATUS_OK;
7102 TALLOC_CTX *ctx = talloc_tos();
7105 return NT_STATUS_INVALID_HANDLE;
7108 if (total_data < 20) {
7109 return NT_STATUS_INVALID_PARAMETER;
7112 overwrite = (CVAL(pdata,0) ? True : False);
7113 len = IVAL(pdata,16);
7115 if (len > (total_data - 20) || (len == 0)) {
7116 return NT_STATUS_INVALID_PARAMETER;
7119 if (req->posix_pathnames) {
7120 srvstr_get_path_posix(ctx,
7129 srvstr_get_path(ctx,
7138 if (!NT_STATUS_IS_OK(status)) {
7142 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7145 status = filename_convert(ctx,
7151 if (!NT_STATUS_IS_OK(status)) {
7155 if (fsp->base_fsp) {
7156 /* newname must be a stream name. */
7157 if (newname[0] != ':') {
7158 return NT_STATUS_NOT_SUPPORTED;
7161 /* Create an smb_fname to call rename_internals_fsp() with. */
7162 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7163 fsp->base_fsp->fsp_name->base_name,
7166 fsp->base_fsp->fsp_name->twrp,
7167 fsp->base_fsp->fsp_name->flags);
7168 if (smb_fname_dst == NULL) {
7169 status = NT_STATUS_NO_MEMORY;
7175 * Set the original last component, since
7176 * rename_internals_fsp() requires it.
7178 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7182 if (dst_original_lcomp == NULL) {
7183 status = NT_STATUS_NO_MEMORY;
7187 DEBUG(10,("smb2_file_rename_information: "
7188 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7189 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7190 smb_fname_str_dbg(smb_fname_dst)));
7191 status = rename_internals_fsp(conn,
7195 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7199 TALLOC_FREE(smb_fname_dst);
7203 static NTSTATUS smb_file_link_information(connection_struct *conn,
7204 struct smb_request *req,
7208 struct smb_filename *smb_fname_src)
7212 char *newname = NULL;
7213 struct smb_filename *smb_fname_dst = NULL;
7214 NTSTATUS status = NT_STATUS_OK;
7215 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7216 TALLOC_CTX *ctx = talloc_tos();
7219 return NT_STATUS_INVALID_HANDLE;
7222 if (total_data < 20) {
7223 return NT_STATUS_INVALID_PARAMETER;
7226 overwrite = (CVAL(pdata,0) ? true : false);
7227 len = IVAL(pdata,16);
7229 if (len > (total_data - 20) || (len == 0)) {
7230 return NT_STATUS_INVALID_PARAMETER;
7233 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7234 srvstr_get_path_posix(ctx,
7242 ucf_flags |= UCF_POSIX_PATHNAMES;
7244 srvstr_get_path(ctx,
7253 if (!NT_STATUS_IS_OK(status)) {
7257 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7260 status = filename_convert(ctx,
7266 if (!NT_STATUS_IS_OK(status)) {
7270 if (fsp->base_fsp) {
7271 /* No stream names. */
7272 return NT_STATUS_NOT_SUPPORTED;
7275 DEBUG(10,("smb_file_link_information: "
7276 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7277 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7278 smb_fname_str_dbg(smb_fname_dst)));
7279 status = hardlink_internals(ctx,
7286 TALLOC_FREE(smb_fname_dst);
7290 /****************************************************************************
7291 Deal with SMB_FILE_RENAME_INFORMATION.
7292 ****************************************************************************/
7294 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7295 struct smb_request *req,
7299 struct smb_filename *smb_fname_src)
7304 char *newname = NULL;
7305 struct smb_filename *smb_fname_dst = NULL;
7306 const char *dst_original_lcomp = NULL;
7307 NTSTATUS status = NT_STATUS_OK;
7309 TALLOC_CTX *ctx = talloc_tos();
7311 if (total_data < 13) {
7312 return NT_STATUS_INVALID_PARAMETER;
7315 overwrite = (CVAL(pdata,0) ? True : False);
7316 root_fid = IVAL(pdata,4);
7317 len = IVAL(pdata,8);
7319 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7320 return NT_STATUS_INVALID_PARAMETER;
7323 if (req->posix_pathnames) {
7324 srvstr_get_path_posix(ctx,
7333 srvstr_get_path(ctx,
7342 if (!NT_STATUS_IS_OK(status)) {
7346 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7349 /* Check the new name has no '/' characters. */
7350 if (strchr_m(newname, '/')) {
7351 return NT_STATUS_NOT_SUPPORTED;
7354 if (fsp && fsp->base_fsp) {
7355 /* newname must be a stream name. */
7356 if (newname[0] != ':') {
7357 return NT_STATUS_NOT_SUPPORTED;
7360 /* Create an smb_fname to call rename_internals_fsp() with. */
7361 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7362 fsp->base_fsp->fsp_name->base_name,
7365 fsp->base_fsp->fsp_name->twrp,
7366 fsp->base_fsp->fsp_name->flags);
7367 if (smb_fname_dst == NULL) {
7368 status = NT_STATUS_NO_MEMORY;
7373 * Get the original last component, since
7374 * rename_internals_fsp() requires it.
7376 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7380 if (dst_original_lcomp == NULL) {
7381 status = NT_STATUS_NO_MEMORY;
7387 * Build up an smb_fname_dst based on the filename passed in.
7388 * We basically just strip off the last component, and put on
7389 * the newname instead.
7391 char *base_name = NULL;
7392 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP|
7393 ucf_flags_from_smb_request(req);
7395 /* newname must *not* be a stream name. */
7396 if (newname[0] == ':') {
7397 return NT_STATUS_NOT_SUPPORTED;
7401 * Strip off the last component (filename) of the path passed
7404 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7406 return NT_STATUS_NO_MEMORY;
7408 p = strrchr_m(base_name, '/');
7412 base_name = talloc_strdup(ctx, "");
7414 return NT_STATUS_NO_MEMORY;
7417 /* Append the new name. */
7418 base_name = talloc_asprintf_append(base_name,
7422 return NT_STATUS_NO_MEMORY;
7425 status = filename_convert(ctx,
7432 /* If an error we expect this to be
7433 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7435 if (!NT_STATUS_IS_OK(status)) {
7436 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7440 /* Create an smb_fname to call rename_internals_fsp() */
7441 smb_fname_dst = synthetic_smb_fname(ctx,
7445 smb_fname_src->twrp,
7446 smb_fname_src->flags);
7447 if (smb_fname_dst == NULL) {
7448 status = NT_STATUS_NO_MEMORY;
7452 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7456 if (dst_original_lcomp == NULL) {
7457 status = NT_STATUS_NO_MEMORY;
7463 DEBUG(10,("smb_file_rename_information: "
7464 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7465 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7466 smb_fname_str_dbg(smb_fname_dst)));
7467 status = rename_internals_fsp(conn,
7474 DEBUG(10,("smb_file_rename_information: "
7475 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7476 smb_fname_str_dbg(smb_fname_src),
7477 smb_fname_str_dbg(smb_fname_dst)));
7478 status = rename_internals(ctx,
7486 FILE_WRITE_ATTRIBUTES);
7489 TALLOC_FREE(smb_fname_dst);
7493 /****************************************************************************
7494 Deal with SMB_SET_POSIX_ACL.
7495 ****************************************************************************/
7497 #if defined(HAVE_POSIX_ACLS)
7498 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7499 struct smb_request *req,
7503 const struct smb_filename *smb_fname)
7505 uint16_t posix_acl_version;
7506 uint16_t num_file_acls;
7507 uint16_t num_def_acls;
7508 bool valid_file_acls = true;
7509 bool valid_def_acls = true;
7511 unsigned int size_needed;
7512 unsigned int total_data;
7513 bool close_fsp = false;
7515 if (total_data_in < 0) {
7516 status = NT_STATUS_INVALID_PARAMETER;
7520 total_data = total_data_in;
7522 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7523 status = NT_STATUS_INVALID_PARAMETER;
7526 posix_acl_version = SVAL(pdata,0);
7527 num_file_acls = SVAL(pdata,2);
7528 num_def_acls = SVAL(pdata,4);
7530 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7531 valid_file_acls = false;
7535 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7536 valid_def_acls = false;
7540 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7541 status = NT_STATUS_INVALID_PARAMETER;
7546 if (num_file_acls + num_def_acls < num_file_acls) {
7547 status = NT_STATUS_INVALID_PARAMETER;
7551 size_needed = num_file_acls + num_def_acls;
7554 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7555 * than UINT_MAX, so check by division.
7557 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7558 status = NT_STATUS_INVALID_PARAMETER;
7562 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7563 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7564 status = NT_STATUS_INVALID_PARAMETER;
7567 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7569 if (total_data < size_needed) {
7570 status = NT_STATUS_INVALID_PARAMETER;
7575 * Ensure we always operate on a file descriptor, not just
7579 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7581 SEC_STD_READ_CONTROL|
7582 FILE_READ_ATTRIBUTES|
7583 FILE_WRITE_ATTRIBUTES;
7585 status = get_posix_fsp(conn,
7591 if (!NT_STATUS_IS_OK(status)) {
7597 /* Here we know fsp != NULL */
7598 SMB_ASSERT(fsp != NULL);
7600 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7601 if (!NT_STATUS_IS_OK(status)) {
7605 /* If we have a default acl, this *must* be a directory. */
7606 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7607 DBG_INFO("Can't set default acls on "
7608 "non-directory %s\n",
7610 return NT_STATUS_INVALID_HANDLE;
7613 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7614 "num_def_acls = %"PRIu16"\n",
7619 /* Move pdata to the start of the file ACL entries. */
7620 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7622 if (valid_file_acls) {
7623 status = set_unix_posix_acl(conn,
7627 if (!NT_STATUS_IS_OK(status)) {
7632 /* Move pdata to the start of the default ACL entries. */
7633 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7635 if (valid_def_acls) {
7636 status = set_unix_posix_default_acl(conn,
7640 if (!NT_STATUS_IS_OK(status)) {
7645 status = NT_STATUS_OK;
7650 (void)close_file(req, fsp, NORMAL_CLOSE);
7657 /****************************************************************************
7658 Deal with SMB_SET_POSIX_LOCK.
7659 ****************************************************************************/
7661 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7663 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7664 struct smb_request *req,
7669 struct tevent_req *subreq = NULL;
7670 struct smbd_lock_element *lck = NULL;
7674 bool blocking_lock = False;
7675 enum brl_type lock_type;
7677 NTSTATUS status = NT_STATUS_OK;
7679 if (fsp == NULL || fsp->fh->fd == -1) {
7680 return NT_STATUS_INVALID_HANDLE;
7683 if (total_data != POSIX_LOCK_DATA_SIZE) {
7684 return NT_STATUS_INVALID_PARAMETER;
7687 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7688 case POSIX_LOCK_TYPE_READ:
7689 lock_type = READ_LOCK;
7691 case POSIX_LOCK_TYPE_WRITE:
7692 /* Return the right POSIX-mappable error code for files opened read-only. */
7693 if (!fsp->fsp_flags.can_write) {
7694 return NT_STATUS_INVALID_HANDLE;
7696 lock_type = WRITE_LOCK;
7698 case POSIX_LOCK_TYPE_UNLOCK:
7699 lock_type = UNLOCK_LOCK;
7702 return NT_STATUS_INVALID_PARAMETER;
7705 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7706 case POSIX_LOCK_FLAG_NOWAIT:
7707 blocking_lock = false;
7709 case POSIX_LOCK_FLAG_WAIT:
7710 blocking_lock = true;
7713 return NT_STATUS_INVALID_PARAMETER;
7716 if (!lp_blocking_locks(SNUM(conn))) {
7717 blocking_lock = False;
7720 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7721 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7722 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7723 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7724 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7726 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7727 "count = %"PRIu64", offset = %"PRIu64"\n",
7729 (unsigned int)lock_type,
7734 if (lock_type == UNLOCK_LOCK) {
7735 struct smbd_lock_element l = {
7736 .req_guid = smbd_request_guid(req, 0),
7738 .brltype = UNLOCK_LOCK,
7742 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7746 lck = talloc(req, struct smbd_lock_element);
7748 return NT_STATUS_NO_MEMORY;
7751 *lck = (struct smbd_lock_element) {
7752 .req_guid = smbd_request_guid(req, 0),
7754 .brltype = lock_type,
7759 subreq = smbd_smb1_do_locks_send(
7764 blocking_lock ? UINT32_MAX : 0,
7765 true, /* large_offset */
7769 if (subreq == NULL) {
7771 return NT_STATUS_NO_MEMORY;
7773 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7774 return NT_STATUS_EVENT_PENDING;
7777 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7779 struct smb_request *req = NULL;
7783 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7786 status = smbd_smb1_do_locks_recv(subreq);
7787 TALLOC_FREE(subreq);
7789 if (NT_STATUS_IS_OK(status)) {
7790 char params[2] = {0};
7791 /* Fake up max_data_bytes here - we know it fits. */
7792 send_trans2_replies(
7802 reply_nterror(req, status);
7805 (char *)req->outbuf,
7808 IS_CONN_ENCRYPTED(req->conn),
7811 exit_server_cleanly("smb_set_posix_lock_done: "
7812 "srv_send_smb failed.");
7820 /****************************************************************************
7821 Deal with SMB_SET_FILE_BASIC_INFO.
7822 ****************************************************************************/
7824 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7828 const struct smb_filename *smb_fname)
7830 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7831 struct smb_file_time ft;
7832 uint32_t dosmode = 0;
7833 NTSTATUS status = NT_STATUS_OK;
7835 init_smb_file_time(&ft);
7837 if (total_data < 36) {
7838 return NT_STATUS_INVALID_PARAMETER;
7842 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7844 status = check_access(conn,
7847 FILE_WRITE_ATTRIBUTES);
7849 if (!NT_STATUS_IS_OK(status)) {
7853 /* Set the attributes */
7854 dosmode = IVAL(pdata,32);
7855 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7856 if (!NT_STATUS_IS_OK(status)) {
7861 ft.create_time = pull_long_date_full_timespec(pdata);
7864 ft.atime = pull_long_date_full_timespec(pdata+8);
7867 ft.mtime = pull_long_date_full_timespec(pdata+16);
7870 ft.ctime = pull_long_date_full_timespec(pdata+24);
7872 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7873 smb_fname_str_dbg(smb_fname)));
7875 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7876 if (!NT_STATUS_IS_OK(status)) {
7880 if (fsp != NULL && fsp->fsp_flags.modified) {
7881 trigger_write_time_update_immediate(fsp);
7883 return NT_STATUS_OK;
7886 /****************************************************************************
7887 Deal with SMB_INFO_STANDARD.
7888 ****************************************************************************/
7890 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7894 const struct smb_filename *smb_fname)
7897 struct smb_file_time ft;
7899 init_smb_file_time(&ft);
7901 if (total_data < 12) {
7902 return NT_STATUS_INVALID_PARAMETER;
7906 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7908 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7910 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7912 DEBUG(10,("smb_set_info_standard: file %s\n",
7913 smb_fname_str_dbg(smb_fname)));
7916 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7918 status = check_access(conn,
7921 FILE_WRITE_ATTRIBUTES);
7923 if (!NT_STATUS_IS_OK(status)) {
7927 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7928 if (!NT_STATUS_IS_OK(status)) {
7932 if (fsp != NULL && fsp->fsp_flags.modified) {
7933 trigger_write_time_update_immediate(fsp);
7935 return NT_STATUS_OK;
7938 /****************************************************************************
7939 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7940 ****************************************************************************/
7942 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7943 struct smb_request *req,
7947 struct smb_filename *smb_fname)
7949 uint64_t allocation_size = 0;
7950 NTSTATUS status = NT_STATUS_OK;
7951 files_struct *new_fsp = NULL;
7953 if (!VALID_STAT(smb_fname->st)) {
7954 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7957 if (total_data < 8) {
7958 return NT_STATUS_INVALID_PARAMETER;
7961 allocation_size = (uint64_t)IVAL(pdata,0);
7962 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7963 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7964 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7965 (double)allocation_size));
7967 if (allocation_size) {
7968 allocation_size = smb_roundup(conn, allocation_size);
7971 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7972 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7973 (double)allocation_size));
7975 if (fsp && fsp->fh->fd != -1) {
7976 /* Open file handle. */
7977 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7978 return NT_STATUS_ACCESS_DENIED;
7981 /* Only change if needed. */
7982 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7983 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7984 return map_nt_error_from_unix(errno);
7987 /* But always update the time. */
7989 * This is equivalent to a write. Ensure it's seen immediately
7990 * if there are no pending writes.
7992 trigger_write_time_update_immediate(fsp);
7993 return NT_STATUS_OK;
7996 /* Pathname or stat or directory file. */
7997 status = SMB_VFS_CREATE_FILE(
8000 smb_fname, /* fname */
8001 FILE_WRITE_DATA, /* access_mask */
8002 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8004 FILE_OPEN, /* create_disposition*/
8005 0, /* create_options */
8006 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8007 0, /* oplock_request */
8009 0, /* allocation_size */
8010 0, /* private_flags */
8013 &new_fsp, /* result */
8015 NULL, NULL); /* create context */
8017 if (!NT_STATUS_IS_OK(status)) {
8018 /* NB. We check for open_was_deferred in the caller. */
8022 /* Only change if needed. */
8023 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8024 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8025 status = map_nt_error_from_unix(errno);
8026 close_file(req, new_fsp, NORMAL_CLOSE);
8031 /* Changing the allocation size should set the last mod time. */
8033 * This is equivalent to a write. Ensure it's seen immediately
8034 * if there are no pending writes.
8036 trigger_write_time_update_immediate(new_fsp);
8037 close_file(req, new_fsp, NORMAL_CLOSE);
8038 return NT_STATUS_OK;
8041 /****************************************************************************
8042 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8043 ****************************************************************************/
8045 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8046 struct smb_request *req,
8050 const struct smb_filename *smb_fname,
8051 bool fail_after_createfile)
8055 if (total_data < 8) {
8056 return NT_STATUS_INVALID_PARAMETER;
8059 size = IVAL(pdata,0);
8060 size |= (((off_t)IVAL(pdata,4)) << 32);
8061 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8062 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8065 return smb_set_file_size(conn, req,
8070 fail_after_createfile);
8073 /****************************************************************************
8074 Allow a UNIX info mknod.
8075 ****************************************************************************/
8077 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8080 const struct smb_filename *smb_fname)
8082 uint32_t file_type = IVAL(pdata,56);
8083 #if defined(HAVE_MAKEDEV)
8084 uint32_t dev_major = IVAL(pdata,60);
8085 uint32_t dev_minor = IVAL(pdata,68);
8087 SMB_DEV_T dev = (SMB_DEV_T)0;
8088 uint32_t raw_unixmode = IVAL(pdata,84);
8093 if (total_data < 100) {
8094 return NT_STATUS_INVALID_PARAMETER;
8097 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8098 PERM_NEW_FILE, &unixmode);
8099 if (!NT_STATUS_IS_OK(status)) {
8103 #if defined(HAVE_MAKEDEV)
8104 dev = makedev(dev_major, dev_minor);
8107 switch (file_type) {
8108 /* We can't create other objects here. */
8109 case UNIX_TYPE_FILE:
8111 case UNIX_TYPE_SYMLINK:
8112 return NT_STATUS_ACCESS_DENIED;
8113 #if defined(S_IFIFO)
8114 case UNIX_TYPE_FIFO:
8115 unixmode |= S_IFIFO;
8118 #if defined(S_IFSOCK)
8119 case UNIX_TYPE_SOCKET:
8120 unixmode |= S_IFSOCK;
8123 #if defined(S_IFCHR)
8124 case UNIX_TYPE_CHARDEV:
8125 /* This is only allowed for root. */
8126 if (get_current_uid(conn) != sec_initial_uid()) {
8127 return NT_STATUS_ACCESS_DENIED;
8129 unixmode |= S_IFCHR;
8132 #if defined(S_IFBLK)
8133 case UNIX_TYPE_BLKDEV:
8134 if (get_current_uid(conn) != sec_initial_uid()) {
8135 return NT_STATUS_ACCESS_DENIED;
8137 unixmode |= S_IFBLK;
8141 return NT_STATUS_INVALID_PARAMETER;
8144 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8145 "%.0f mode 0%o for file %s\n", (double)dev,
8146 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8148 /* Ok - do the mknod. */
8149 ret = SMB_VFS_MKNODAT(conn,
8156 return map_nt_error_from_unix(errno);
8159 /* If any of the other "set" calls fail we
8160 * don't want to end up with a half-constructed mknod.
8163 if (lp_inherit_permissions(SNUM(conn))) {
8164 struct smb_filename *parent_fname = NULL;
8167 ok = parent_smb_fname(talloc_tos(),
8172 return NT_STATUS_NO_MEMORY;
8174 inherit_access_posix_acl(conn,
8178 TALLOC_FREE(parent_fname);
8181 return NT_STATUS_OK;
8184 /****************************************************************************
8185 Deal with SMB_SET_FILE_UNIX_BASIC.
8186 ****************************************************************************/
8188 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8189 struct smb_request *req,
8193 const struct smb_filename *smb_fname)
8195 struct smb_file_time ft;
8196 uint32_t raw_unixmode;
8199 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8200 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8201 NTSTATUS status = NT_STATUS_OK;
8202 enum perm_type ptype;
8203 files_struct *all_fsps = NULL;
8204 bool modify_mtime = true;
8206 SMB_STRUCT_STAT sbuf;
8208 init_smb_file_time(&ft);
8210 if (total_data < 100) {
8211 return NT_STATUS_INVALID_PARAMETER;
8214 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8215 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8216 size=IVAL(pdata,0); /* first 8 Bytes are size */
8217 size |= (((off_t)IVAL(pdata,4)) << 32);
8220 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8221 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8222 set_owner = (uid_t)IVAL(pdata,40);
8223 set_grp = (gid_t)IVAL(pdata,48);
8224 raw_unixmode = IVAL(pdata,84);
8226 if (VALID_STAT(smb_fname->st)) {
8227 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8228 ptype = PERM_EXISTING_DIR;
8230 ptype = PERM_EXISTING_FILE;
8233 ptype = PERM_NEW_FILE;
8236 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8238 if (!NT_STATUS_IS_OK(status)) {
8242 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8243 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8244 smb_fname_str_dbg(smb_fname), (double)size,
8245 (unsigned int)set_owner, (unsigned int)set_grp,
8246 (int)raw_unixmode));
8248 sbuf = smb_fname->st;
8250 if (!VALID_STAT(sbuf)) {
8252 * The only valid use of this is to create character and block
8253 * devices, and named pipes. This is deprecated (IMHO) and
8254 * a new info level should be used for mknod. JRA.
8257 return smb_unix_mknod(conn,
8264 /* Horrible backwards compatibility hack as an old server bug
8265 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8269 size = get_file_size_stat(&sbuf);
8274 * Deal with the UNIX specific mode set.
8277 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8280 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8281 "setting mode 0%o for file %s\n",
8282 (unsigned int)unixmode,
8283 smb_fname_str_dbg(smb_fname)));
8284 if (fsp && fsp->fh->fd != -1) {
8285 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8287 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8290 return map_nt_error_from_unix(errno);
8295 * Deal with the UNIX specific uid set.
8298 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8299 (sbuf.st_ex_uid != set_owner)) {
8302 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8303 "changing owner %u for path %s\n",
8304 (unsigned int)set_owner,
8305 smb_fname_str_dbg(smb_fname)));
8307 if (fsp && fsp->fh->fd != -1) {
8308 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8311 * UNIX extensions calls must always operate
8314 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8315 set_owner, (gid_t)-1);
8319 status = map_nt_error_from_unix(errno);
8325 * Deal with the UNIX specific gid set.
8328 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8329 (sbuf.st_ex_gid != set_grp)) {
8332 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8333 "changing group %u for file %s\n",
8334 (unsigned int)set_grp,
8335 smb_fname_str_dbg(smb_fname)));
8336 if (fsp && fsp->fh->fd != -1) {
8337 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8340 * UNIX extensions calls must always operate
8343 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8347 status = map_nt_error_from_unix(errno);
8352 /* Deal with any size changes. */
8354 if (S_ISREG(sbuf.st_ex_mode)) {
8355 status = smb_set_file_size(conn, req,
8361 if (!NT_STATUS_IS_OK(status)) {
8366 /* Deal with any time changes. */
8367 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8368 /* No change, don't cancel anything. */
8372 id = vfs_file_id_from_sbuf(conn, &sbuf);
8373 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8374 all_fsps = file_find_di_next(all_fsps)) {
8376 * We're setting the time explicitly for UNIX.
8377 * Cancel any pending changes over all handles.
8379 all_fsps->fsp_flags.update_write_time_on_close = false;
8380 TALLOC_FREE(all_fsps->update_write_time_event);
8384 * Override the "setting_write_time"
8385 * parameter here as it almost does what
8386 * we need. Just remember if we modified
8387 * mtime and send the notify ourselves.
8389 if (is_omit_timespec(&ft.mtime)) {
8390 modify_mtime = false;
8393 status = smb_set_file_time(conn,
8399 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8400 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8405 /****************************************************************************
8406 Deal with SMB_SET_FILE_UNIX_INFO2.
8407 ****************************************************************************/
8409 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8410 struct smb_request *req,
8414 const struct smb_filename *smb_fname)
8417 uint32_t smb_fflags;
8420 if (total_data < 116) {
8421 return NT_STATUS_INVALID_PARAMETER;
8424 /* Start by setting all the fields that are common between UNIX_BASIC
8427 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8429 if (!NT_STATUS_IS_OK(status)) {
8433 smb_fflags = IVAL(pdata, 108);
8434 smb_fmask = IVAL(pdata, 112);
8436 /* NB: We should only attempt to alter the file flags if the client
8437 * sends a non-zero mask.
8439 if (smb_fmask != 0) {
8440 int stat_fflags = 0;
8442 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8443 smb_fmask, &stat_fflags)) {
8444 /* Client asked to alter a flag we don't understand. */
8445 return NT_STATUS_INVALID_PARAMETER;
8448 if (fsp && fsp->fh->fd != -1) {
8449 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8450 return NT_STATUS_NOT_SUPPORTED;
8452 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8453 stat_fflags) != 0) {
8454 return map_nt_error_from_unix(errno);
8459 /* XXX: need to add support for changing the create_time here. You
8460 * can do this for paths on Darwin with setattrlist(2). The right way
8461 * to hook this up is probably by extending the VFS utimes interface.
8464 return NT_STATUS_OK;
8467 /****************************************************************************
8468 Create a directory with POSIX semantics.
8469 ****************************************************************************/
8471 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8472 struct smb_request *req,
8475 struct smb_filename *smb_fname,
8476 int *pdata_return_size)
8478 NTSTATUS status = NT_STATUS_OK;
8479 uint32_t raw_unixmode = 0;
8480 mode_t unixmode = (mode_t)0;
8481 files_struct *fsp = NULL;
8482 uint16_t info_level_return = 0;
8484 char *pdata = *ppdata;
8485 struct smb2_create_blobs *posx = NULL;
8487 if (total_data < 18) {
8488 return NT_STATUS_INVALID_PARAMETER;
8491 raw_unixmode = IVAL(pdata,8);
8492 /* Next 4 bytes are not yet defined. */
8494 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8495 PERM_NEW_DIR, &unixmode);
8496 if (!NT_STATUS_IS_OK(status)) {
8500 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8501 if (!NT_STATUS_IS_OK(status)) {
8502 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8507 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8508 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8510 status = SMB_VFS_CREATE_FILE(
8513 smb_fname, /* fname */
8514 FILE_READ_ATTRIBUTES, /* access_mask */
8515 FILE_SHARE_NONE, /* share_access */
8516 FILE_CREATE, /* create_disposition*/
8517 FILE_DIRECTORY_FILE, /* create_options */
8518 0, /* file_attributes */
8519 0, /* oplock_request */
8521 0, /* allocation_size */
8522 0, /* private_flags */
8527 posx, /* in_context_blobs */
8528 NULL); /* out_context_blobs */
8532 if (NT_STATUS_IS_OK(status)) {
8533 close_file(req, fsp, NORMAL_CLOSE);
8536 info_level_return = SVAL(pdata,16);
8538 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8539 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8540 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8541 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8543 *pdata_return_size = 12;
8546 /* Realloc the data size */
8547 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8548 if (*ppdata == NULL) {
8549 *pdata_return_size = 0;
8550 return NT_STATUS_NO_MEMORY;
8554 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8555 SSVAL(pdata,2,0); /* No fnum. */
8556 SIVAL(pdata,4,info); /* Was directory created. */
8558 switch (info_level_return) {
8559 case SMB_QUERY_FILE_UNIX_BASIC:
8560 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8561 SSVAL(pdata,10,0); /* Padding. */
8562 store_file_unix_basic(conn, pdata + 12, fsp,
8565 case SMB_QUERY_FILE_UNIX_INFO2:
8566 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8567 SSVAL(pdata,10,0); /* Padding. */
8568 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8572 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8573 SSVAL(pdata,10,0); /* Padding. */
8580 /****************************************************************************
8581 Open/Create a file with POSIX semantics.
8582 ****************************************************************************/
8584 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8585 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8587 static NTSTATUS smb_posix_open(connection_struct *conn,
8588 struct smb_request *req,
8591 struct smb_filename *smb_fname,
8592 int *pdata_return_size)
8594 bool extended_oplock_granted = False;
8595 char *pdata = *ppdata;
8597 uint32_t wire_open_mode = 0;
8598 uint32_t raw_unixmode = 0;
8599 uint32_t attributes = 0;
8600 uint32_t create_disp = 0;
8601 uint32_t access_mask = 0;
8602 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8603 NTSTATUS status = NT_STATUS_OK;
8604 mode_t unixmode = (mode_t)0;
8605 files_struct *fsp = NULL;
8606 int oplock_request = 0;
8608 uint16_t info_level_return = 0;
8609 struct smb2_create_blobs *posx = NULL;
8611 if (total_data < 18) {
8612 return NT_STATUS_INVALID_PARAMETER;
8615 flags = IVAL(pdata,0);
8616 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8617 if (oplock_request) {
8618 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8621 wire_open_mode = IVAL(pdata,4);
8623 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8624 return smb_posix_mkdir(conn, req,
8631 switch (wire_open_mode & SMB_ACCMODE) {
8633 access_mask = SMB_O_RDONLY_MAPPING;
8636 access_mask = SMB_O_WRONLY_MAPPING;
8639 access_mask = (SMB_O_RDONLY_MAPPING|
8640 SMB_O_WRONLY_MAPPING);
8643 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8644 (unsigned int)wire_open_mode ));
8645 return NT_STATUS_INVALID_PARAMETER;
8648 wire_open_mode &= ~SMB_ACCMODE;
8650 /* First take care of O_CREAT|O_EXCL interactions. */
8651 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8652 case (SMB_O_CREAT | SMB_O_EXCL):
8653 /* File exists fail. File not exist create. */
8654 create_disp = FILE_CREATE;
8657 /* File exists open. File not exist create. */
8658 create_disp = FILE_OPEN_IF;
8661 /* O_EXCL on its own without O_CREAT is undefined.
8662 We deliberately ignore it as some versions of
8663 Linux CIFSFS can send a bare O_EXCL on the
8664 wire which other filesystems in the kernel
8665 ignore. See bug 9519 for details. */
8670 /* File exists open. File not exist fail. */
8671 create_disp = FILE_OPEN;
8674 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8675 (unsigned int)wire_open_mode ));
8676 return NT_STATUS_INVALID_PARAMETER;
8679 /* Next factor in the effects of O_TRUNC. */
8680 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8682 if (wire_open_mode & SMB_O_TRUNC) {
8683 switch (create_disp) {
8685 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8686 /* Leave create_disp alone as
8687 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8689 /* File exists fail. File not exist create. */
8692 /* SMB_O_CREAT | SMB_O_TRUNC */
8693 /* File exists overwrite. File not exist create. */
8694 create_disp = FILE_OVERWRITE_IF;
8698 /* File exists overwrite. File not exist fail. */
8699 create_disp = FILE_OVERWRITE;
8702 /* Cannot get here. */
8703 smb_panic("smb_posix_open: logic error");
8704 return NT_STATUS_INVALID_PARAMETER;
8708 raw_unixmode = IVAL(pdata,8);
8709 /* Next 4 bytes are not yet defined. */
8711 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8712 (VALID_STAT(smb_fname->st) ?
8713 PERM_EXISTING_FILE : PERM_NEW_FILE),
8716 if (!NT_STATUS_IS_OK(status)) {
8720 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8721 if (!NT_STATUS_IS_OK(status)) {
8722 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8727 if (wire_open_mode & SMB_O_SYNC) {
8728 create_options |= FILE_WRITE_THROUGH;
8730 if (wire_open_mode & SMB_O_APPEND) {
8731 access_mask |= FILE_APPEND_DATA;
8733 if (wire_open_mode & SMB_O_DIRECT) {
8734 attributes |= FILE_FLAG_NO_BUFFERING;
8737 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8738 VALID_STAT_OF_DIR(smb_fname->st)) {
8739 if (access_mask != SMB_O_RDONLY_MAPPING) {
8740 return NT_STATUS_FILE_IS_A_DIRECTORY;
8742 create_options &= ~FILE_NON_DIRECTORY_FILE;
8743 create_options |= FILE_DIRECTORY_FILE;
8746 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8747 smb_fname_str_dbg(smb_fname),
8748 (unsigned int)wire_open_mode,
8749 (unsigned int)unixmode ));
8751 status = SMB_VFS_CREATE_FILE(
8754 smb_fname, /* fname */
8755 access_mask, /* access_mask */
8756 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8758 create_disp, /* create_disposition*/
8759 create_options, /* create_options */
8760 attributes, /* file_attributes */
8761 oplock_request, /* oplock_request */
8763 0, /* allocation_size */
8764 0, /* private_flags */
8769 posx, /* in_context_blobs */
8770 NULL); /* out_context_blobs */
8774 if (!NT_STATUS_IS_OK(status)) {
8778 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8779 extended_oplock_granted = True;
8782 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8783 extended_oplock_granted = True;
8786 info_level_return = SVAL(pdata,16);
8788 /* Allocate the correct return size. */
8790 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8791 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8792 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8793 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8795 *pdata_return_size = 12;
8798 /* Realloc the data size */
8799 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8800 if (*ppdata == NULL) {
8801 close_file(req, fsp, ERROR_CLOSE);
8802 *pdata_return_size = 0;
8803 return NT_STATUS_NO_MEMORY;
8807 if (extended_oplock_granted) {
8808 if (flags & REQUEST_BATCH_OPLOCK) {
8809 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8811 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8813 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8814 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8816 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8819 SSVAL(pdata,2,fsp->fnum);
8820 SIVAL(pdata,4,info); /* Was file created etc. */
8822 switch (info_level_return) {
8823 case SMB_QUERY_FILE_UNIX_BASIC:
8824 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8825 SSVAL(pdata,10,0); /* padding. */
8826 store_file_unix_basic(conn, pdata + 12, fsp,
8829 case SMB_QUERY_FILE_UNIX_INFO2:
8830 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8831 SSVAL(pdata,10,0); /* padding. */
8832 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8836 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8837 SSVAL(pdata,10,0); /* padding. */
8840 return NT_STATUS_OK;
8843 /****************************************************************************
8844 Delete a file with POSIX semantics.
8845 ****************************************************************************/
8847 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8848 struct smb_request *req,
8851 struct smb_filename *smb_fname)
8853 NTSTATUS status = NT_STATUS_OK;
8854 files_struct *fsp = NULL;
8858 int create_options = 0;
8859 struct share_mode_lock *lck = NULL;
8860 bool other_nonposix_opens;
8861 struct smb2_create_blobs *posx = NULL;
8863 if (total_data < 2) {
8864 return NT_STATUS_INVALID_PARAMETER;
8867 flags = SVAL(pdata,0);
8869 if (!VALID_STAT(smb_fname->st)) {
8870 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8873 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8874 !VALID_STAT_OF_DIR(smb_fname->st)) {
8875 return NT_STATUS_NOT_A_DIRECTORY;
8878 DEBUG(10,("smb_posix_unlink: %s %s\n",
8879 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8880 smb_fname_str_dbg(smb_fname)));
8882 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8883 create_options |= FILE_DIRECTORY_FILE;
8886 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8887 if (!NT_STATUS_IS_OK(status)) {
8888 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8893 status = SMB_VFS_CREATE_FILE(
8896 smb_fname, /* fname */
8897 DELETE_ACCESS, /* access_mask */
8898 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8900 FILE_OPEN, /* create_disposition*/
8901 create_options, /* create_options */
8902 0, /* file_attributes */
8903 0, /* oplock_request */
8905 0, /* allocation_size */
8906 0, /* private_flags */
8911 posx, /* in_context_blobs */
8912 NULL); /* out_context_blobs */
8916 if (!NT_STATUS_IS_OK(status)) {
8921 * Don't lie to client. If we can't really delete due to
8922 * non-POSIX opens return SHARING_VIOLATION.
8925 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8927 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8928 "lock for file %s\n", fsp_str_dbg(fsp)));
8929 close_file(req, fsp, NORMAL_CLOSE);
8930 return NT_STATUS_INVALID_PARAMETER;
8933 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8934 if (other_nonposix_opens) {
8935 /* Fail with sharing violation. */
8937 close_file(req, fsp, NORMAL_CLOSE);
8938 return NT_STATUS_SHARING_VIOLATION;
8942 * Set the delete on close.
8944 status = smb_set_file_disposition_info(conn,
8952 if (!NT_STATUS_IS_OK(status)) {
8953 close_file(req, fsp, NORMAL_CLOSE);
8956 return close_file(req, fsp, NORMAL_CLOSE);
8959 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8960 struct smb_request *req,
8961 TALLOC_CTX *mem_ctx,
8962 uint16_t info_level,
8964 struct smb_filename *smb_fname,
8965 char **ppdata, int total_data,
8968 char *pdata = *ppdata;
8969 NTSTATUS status = NT_STATUS_OK;
8970 int data_return_size = 0;
8974 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8975 return NT_STATUS_INVALID_LEVEL;
8978 if (!CAN_WRITE(conn)) {
8979 /* Allow POSIX opens. The open path will deny
8980 * any non-readonly opens. */
8981 if (info_level != SMB_POSIX_PATH_OPEN) {
8982 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8986 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8987 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8989 info_level, total_data));
8991 switch (info_level) {
8993 case SMB_INFO_STANDARD:
8995 status = smb_set_info_standard(conn,
9003 case SMB_INFO_SET_EA:
9005 status = smb_info_set_ea(conn,
9013 case SMB_SET_FILE_BASIC_INFO:
9014 case SMB_FILE_BASIC_INFORMATION:
9016 status = smb_set_file_basic_info(conn,
9024 case SMB_FILE_ALLOCATION_INFORMATION:
9025 case SMB_SET_FILE_ALLOCATION_INFO:
9027 status = smb_set_file_allocation_info(conn, req,
9035 case SMB_FILE_END_OF_FILE_INFORMATION:
9036 case SMB_SET_FILE_END_OF_FILE_INFO:
9039 * XP/Win7 both fail after the createfile with
9040 * SMB_SET_FILE_END_OF_FILE_INFO but not
9041 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9042 * The level is known here, so pass it down
9046 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9048 status = smb_set_file_end_of_file_info(conn, req,
9057 case SMB_FILE_DISPOSITION_INFORMATION:
9058 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9061 /* JRA - We used to just ignore this on a path ?
9062 * Shouldn't this be invalid level on a pathname
9065 if (tran_call != TRANSACT2_SETFILEINFO) {
9066 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9069 status = smb_set_file_disposition_info(conn,
9077 case SMB_FILE_POSITION_INFORMATION:
9079 status = smb_file_position_information(conn,
9086 case SMB_FILE_FULL_EA_INFORMATION:
9088 status = smb_set_file_full_ea_info(conn,
9095 /* From tridge Samba4 :
9096 * MODE_INFORMATION in setfileinfo (I have no
9097 * idea what "mode information" on a file is - it takes a value of 0,
9098 * 2, 4 or 6. What could it be?).
9101 case SMB_FILE_MODE_INFORMATION:
9103 status = smb_file_mode_information(conn,
9109 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9110 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9111 case SMB_FILE_SHORT_NAME_INFORMATION:
9112 return NT_STATUS_NOT_SUPPORTED;
9115 * CIFS UNIX extensions.
9118 case SMB_SET_FILE_UNIX_BASIC:
9120 status = smb_set_file_unix_basic(conn, req,
9128 case SMB_SET_FILE_UNIX_INFO2:
9130 status = smb_set_file_unix_info2(conn, req,
9138 case SMB_SET_FILE_UNIX_LINK:
9141 /* We must have a pathname for this. */
9142 return NT_STATUS_INVALID_LEVEL;
9144 status = smb_set_file_unix_link(conn, req, pdata,
9145 total_data, smb_fname);
9149 case SMB_SET_FILE_UNIX_HLINK:
9152 /* We must have a pathname for this. */
9153 return NT_STATUS_INVALID_LEVEL;
9155 status = smb_set_file_unix_hlink(conn, req,
9161 case SMB_FILE_RENAME_INFORMATION:
9163 status = smb_file_rename_information(conn, req,
9169 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9171 /* SMB2 rename information. */
9172 status = smb2_file_rename_information(conn, req,
9178 case SMB_FILE_LINK_INFORMATION:
9180 status = smb_file_link_information(conn, req,
9186 #if defined(HAVE_POSIX_ACLS)
9187 case SMB_SET_POSIX_ACL:
9189 status = smb_set_posix_acl(conn,
9199 case SMB_SET_POSIX_LOCK:
9202 return NT_STATUS_INVALID_LEVEL;
9204 status = smb_set_posix_lock(conn, req,
9205 pdata, total_data, fsp);
9209 case SMB_POSIX_PATH_OPEN:
9212 /* We must have a pathname for this. */
9213 return NT_STATUS_INVALID_LEVEL;
9216 status = smb_posix_open(conn, req,
9224 case SMB_POSIX_PATH_UNLINK:
9227 /* We must have a pathname for this. */
9228 return NT_STATUS_INVALID_LEVEL;
9231 status = smb_posix_unlink(conn, req,
9239 return NT_STATUS_INVALID_LEVEL;
9242 if (!NT_STATUS_IS_OK(status)) {
9246 *ret_data_size = data_return_size;
9247 return NT_STATUS_OK;
9250 /****************************************************************************
9251 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9252 ****************************************************************************/
9254 static void call_trans2setfilepathinfo(connection_struct *conn,
9255 struct smb_request *req,
9256 unsigned int tran_call,
9257 char **pparams, int total_params,
9258 char **ppdata, int total_data,
9259 unsigned int max_data_bytes)
9261 char *params = *pparams;
9262 char *pdata = *ppdata;
9263 uint16_t info_level;
9264 struct smb_filename *smb_fname = NULL;
9265 files_struct *fsp = NULL;
9266 NTSTATUS status = NT_STATUS_OK;
9267 int data_return_size = 0;
9270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9274 if (tran_call == TRANSACT2_SETFILEINFO) {
9275 if (total_params < 4) {
9276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9280 fsp = file_fsp(req, SVAL(params,0));
9281 /* Basic check for non-null fsp. */
9282 if (!check_fsp_open(conn, req, fsp)) {
9285 info_level = SVAL(params,2);
9287 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9288 if (smb_fname == NULL) {
9289 reply_nterror(req, NT_STATUS_NO_MEMORY);
9293 if(fsp->fh->fd == -1) {
9295 * This is actually a SETFILEINFO on a directory
9296 * handle (returned from an NT SMB). NT5.0 seems
9297 * to do this call. JRA.
9299 if (INFO_LEVEL_IS_UNIX(info_level)) {
9300 /* Always do lstat for UNIX calls. */
9301 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9302 DEBUG(3,("call_trans2setfilepathinfo: "
9303 "SMB_VFS_LSTAT of %s failed "
9305 smb_fname_str_dbg(smb_fname),
9307 reply_nterror(req, map_nt_error_from_unix(errno));
9311 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9312 DEBUG(3,("call_trans2setfilepathinfo: "
9313 "fileinfo of %s failed (%s)\n",
9314 smb_fname_str_dbg(smb_fname),
9316 reply_nterror(req, map_nt_error_from_unix(errno));
9320 } else if (fsp->print_file) {
9322 * Doing a DELETE_ON_CLOSE should cancel a print job.
9324 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9325 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9327 DEBUG(3,("call_trans2setfilepathinfo: "
9328 "Cancelling print job (%s)\n",
9332 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9338 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9343 * Original code - this is an open file.
9345 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9346 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9347 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9349 reply_nterror(req, map_nt_error_from_unix(errno));
9355 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9358 if (total_params < 7) {
9359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9363 info_level = SVAL(params,0);
9364 if (req->posix_pathnames) {
9365 srvstr_get_path_posix(req,
9374 srvstr_get_path(req,
9383 if (!NT_STATUS_IS_OK(status)) {
9384 reply_nterror(req, status);
9388 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9389 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9390 info_level == SMB_FILE_RENAME_INFORMATION ||
9391 info_level == SMB_POSIX_PATH_OPEN ||
9392 info_level == SMB_POSIX_PATH_UNLINK) {
9393 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9396 status = filename_convert(req, conn,
9401 if (!NT_STATUS_IS_OK(status)) {
9402 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9403 reply_botherror(req,
9404 NT_STATUS_PATH_NOT_COVERED,
9405 ERRSRV, ERRbadpath);
9408 reply_nterror(req, status);
9412 if (INFO_LEVEL_IS_UNIX(info_level)) {
9414 * For CIFS UNIX extensions the target name may not exist.
9417 /* Always do lstat for UNIX calls. */
9418 SMB_VFS_LSTAT(conn, smb_fname);
9420 } else if (!VALID_STAT(smb_fname->st) &&
9421 SMB_VFS_STAT(conn, smb_fname)) {
9422 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9424 smb_fname_str_dbg(smb_fname),
9426 reply_nterror(req, map_nt_error_from_unix(errno));
9431 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9432 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9434 info_level,total_data));
9436 /* Realloc the parameter size */
9437 *pparams = (char *)SMB_REALLOC(*pparams,2);
9438 if (*pparams == NULL) {
9439 reply_nterror(req, NT_STATUS_NO_MEMORY);
9446 status = smbd_do_setfilepathinfo(conn, req, req,
9452 if (!NT_STATUS_IS_OK(status)) {
9453 if (open_was_deferred(req->xconn, req->mid)) {
9454 /* We have re-scheduled this call. */
9457 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9458 bool ok = defer_smb1_sharing_violation(req);
9463 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9464 /* We have re-scheduled this call. */
9467 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9468 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9469 ERRSRV, ERRbadpath);
9472 if (info_level == SMB_POSIX_PATH_OPEN) {
9473 reply_openerror(req, status);
9478 * Invalid EA name needs to return 2 param bytes,
9479 * not a zero-length error packet.
9481 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9482 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9485 reply_nterror(req, status);
9490 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9496 /****************************************************************************
9497 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9498 ****************************************************************************/
9500 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9501 char **pparams, int total_params,
9502 char **ppdata, int total_data,
9503 unsigned int max_data_bytes)
9505 struct smb_filename *smb_dname = NULL;
9506 char *params = *pparams;
9507 char *pdata = *ppdata;
9508 char *directory = NULL;
9509 NTSTATUS status = NT_STATUS_OK;
9510 struct ea_list *ea_list = NULL;
9511 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9512 TALLOC_CTX *ctx = talloc_tos();
9514 if (!CAN_WRITE(conn)) {
9515 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9519 if (total_params < 5) {
9520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9524 if (req->posix_pathnames) {
9525 srvstr_get_path_posix(ctx,
9534 srvstr_get_path(ctx,
9543 if (!NT_STATUS_IS_OK(status)) {
9544 reply_nterror(req, status);
9548 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9550 status = filename_convert(ctx,
9557 if (!NT_STATUS_IS_OK(status)) {
9558 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9559 reply_botherror(req,
9560 NT_STATUS_PATH_NOT_COVERED,
9561 ERRSRV, ERRbadpath);
9564 reply_nterror(req, status);
9569 * OS/2 workplace shell seems to send SET_EA requests of "null"
9570 * length (4 bytes containing IVAL 4).
9571 * They seem to have no effect. Bug #3212. JRA.
9574 if (total_data && (total_data != 4)) {
9575 /* Any data in this call is an EA list. */
9576 if (total_data < 10) {
9577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9581 if (IVAL(pdata,0) > total_data) {
9582 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9583 IVAL(pdata,0), (unsigned int)total_data));
9584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9588 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9595 if (!lp_ea_support(SNUM(conn))) {
9596 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9600 /* If total_data == 4 Windows doesn't care what values
9601 * are placed in that field, it just ignores them.
9602 * The System i QNTC IBM SMB client puts bad values here,
9603 * so ignore them. */
9605 status = create_directory(conn, req, smb_dname);
9607 if (!NT_STATUS_IS_OK(status)) {
9608 reply_nterror(req, status);
9612 /* Try and set any given EA. */
9614 status = set_ea(conn, NULL, smb_dname, ea_list);
9615 if (!NT_STATUS_IS_OK(status)) {
9616 reply_nterror(req, status);
9621 /* Realloc the parameter and data sizes */
9622 *pparams = (char *)SMB_REALLOC(*pparams,2);
9623 if(*pparams == NULL) {
9624 reply_nterror(req, NT_STATUS_NO_MEMORY);
9631 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9634 TALLOC_FREE(smb_dname);
9638 /****************************************************************************
9639 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9640 We don't actually do this - we just send a null response.
9641 ****************************************************************************/
9643 static void call_trans2findnotifyfirst(connection_struct *conn,
9644 struct smb_request *req,
9645 char **pparams, int total_params,
9646 char **ppdata, int total_data,
9647 unsigned int max_data_bytes)
9649 char *params = *pparams;
9650 uint16_t info_level;
9652 if (total_params < 6) {
9653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9657 info_level = SVAL(params,4);
9658 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9660 switch (info_level) {
9665 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9669 /* Realloc the parameter and data sizes */
9670 *pparams = (char *)SMB_REALLOC(*pparams,6);
9671 if (*pparams == NULL) {
9672 reply_nterror(req, NT_STATUS_NO_MEMORY);
9677 SSVAL(params,0,fnf_handle);
9678 SSVAL(params,2,0); /* No changes */
9679 SSVAL(params,4,0); /* No EA errors */
9686 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9691 /****************************************************************************
9692 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9693 changes). Currently this does nothing.
9694 ****************************************************************************/
9696 static void call_trans2findnotifynext(connection_struct *conn,
9697 struct smb_request *req,
9698 char **pparams, int total_params,
9699 char **ppdata, int total_data,
9700 unsigned int max_data_bytes)
9702 char *params = *pparams;
9704 DEBUG(3,("call_trans2findnotifynext\n"));
9706 /* Realloc the parameter and data sizes */
9707 *pparams = (char *)SMB_REALLOC(*pparams,4);
9708 if (*pparams == NULL) {
9709 reply_nterror(req, NT_STATUS_NO_MEMORY);
9714 SSVAL(params,0,0); /* No changes */
9715 SSVAL(params,2,0); /* No EA errors */
9717 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9722 /****************************************************************************
9723 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9724 ****************************************************************************/
9726 static void call_trans2getdfsreferral(connection_struct *conn,
9727 struct smb_request *req,
9728 char **pparams, int total_params,
9729 char **ppdata, int total_data,
9730 unsigned int max_data_bytes)
9732 char *params = *pparams;
9733 char *pathname = NULL;
9735 int max_referral_level;
9736 NTSTATUS status = NT_STATUS_OK;
9737 TALLOC_CTX *ctx = talloc_tos();
9739 DEBUG(10,("call_trans2getdfsreferral\n"));
9741 if (total_params < 3) {
9742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9746 max_referral_level = SVAL(params,0);
9748 if(!lp_host_msdfs()) {
9749 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9753 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9754 total_params - 2, STR_TERMINATE);
9756 reply_nterror(req, NT_STATUS_NOT_FOUND);
9759 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9760 ppdata,&status)) < 0) {
9761 reply_nterror(req, status);
9765 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9766 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9767 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9772 #define LMCAT_SPL 0x53
9773 #define LMFUNC_GETJOBID 0x60
9775 /****************************************************************************
9776 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9777 ****************************************************************************/
9779 static void call_trans2ioctl(connection_struct *conn,
9780 struct smb_request *req,
9781 char **pparams, int total_params,
9782 char **ppdata, int total_data,
9783 unsigned int max_data_bytes)
9785 const struct loadparm_substitution *lp_sub =
9786 loadparm_s3_global_substitution();
9787 char *pdata = *ppdata;
9788 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9792 /* check for an invalid fid before proceeding */
9795 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9799 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9800 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9801 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9802 if (*ppdata == NULL) {
9803 reply_nterror(req, NT_STATUS_NO_MEMORY);
9808 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9809 CAN ACCEPT THIS IN UNICODE. JRA. */
9812 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9814 status = srvstr_push(pdata, req->flags2, pdata + 2,
9815 lp_netbios_name(), 15,
9816 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9817 if (!NT_STATUS_IS_OK(status)) {
9818 reply_nterror(req, status);
9821 status = srvstr_push(pdata, req->flags2, pdata+18,
9822 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9823 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9824 if (!NT_STATUS_IS_OK(status)) {
9825 reply_nterror(req, status);
9828 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9833 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9834 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9837 /****************************************************************************
9838 Reply to a SMBfindclose (stop trans2 directory search).
9839 ****************************************************************************/
9841 void reply_findclose(struct smb_request *req)
9844 struct smbd_server_connection *sconn = req->sconn;
9845 files_struct *fsp = NULL;
9847 START_PROFILE(SMBfindclose);
9850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9851 END_PROFILE(SMBfindclose);
9855 dptr_num = SVALS(req->vwv+0, 0);
9857 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9860 * OS/2 seems to use -1 to indicate "close all directories"
9861 * This has to mean on this specific connection struct.
9863 if (dptr_num == -1) {
9864 dptr_closecnum(req->conn);
9866 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9869 close_file(NULL, fsp, NORMAL_CLOSE);
9874 reply_outbuf(req, 0, 0);
9876 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9878 END_PROFILE(SMBfindclose);
9882 /****************************************************************************
9883 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9884 ****************************************************************************/
9886 void reply_findnclose(struct smb_request *req)
9890 START_PROFILE(SMBfindnclose);
9893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9894 END_PROFILE(SMBfindnclose);
9898 dptr_num = SVAL(req->vwv+0, 0);
9900 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9902 /* We never give out valid handles for a
9903 findnotifyfirst - so any dptr_num is ok here.
9906 reply_outbuf(req, 0, 0);
9908 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9910 END_PROFILE(SMBfindnclose);
9914 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9915 struct trans_state *state)
9917 if (get_Protocol() >= PROTOCOL_NT1) {
9918 req->flags2 |= 0x40; /* IS_LONG_NAME */
9919 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9922 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9923 if (state->call != TRANSACT2_QFSINFO &&
9924 state->call != TRANSACT2_SETFSINFO) {
9925 DEBUG(0,("handle_trans2: encryption required "
9927 (unsigned int)state->call));
9928 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9933 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9935 /* Now we must call the relevant TRANS2 function */
9936 switch(state->call) {
9937 case TRANSACT2_OPEN:
9939 START_PROFILE(Trans2_open);
9940 call_trans2open(conn, req,
9941 &state->param, state->total_param,
9942 &state->data, state->total_data,
9943 state->max_data_return);
9944 END_PROFILE(Trans2_open);
9948 case TRANSACT2_FINDFIRST:
9950 START_PROFILE(Trans2_findfirst);
9951 call_trans2findfirst(conn, req,
9952 &state->param, state->total_param,
9953 &state->data, state->total_data,
9954 state->max_data_return);
9955 END_PROFILE(Trans2_findfirst);
9959 case TRANSACT2_FINDNEXT:
9961 START_PROFILE(Trans2_findnext);
9962 call_trans2findnext(conn, req,
9963 &state->param, state->total_param,
9964 &state->data, state->total_data,
9965 state->max_data_return);
9966 END_PROFILE(Trans2_findnext);
9970 case TRANSACT2_QFSINFO:
9972 START_PROFILE(Trans2_qfsinfo);
9973 call_trans2qfsinfo(conn, req,
9974 &state->param, state->total_param,
9975 &state->data, state->total_data,
9976 state->max_data_return);
9977 END_PROFILE(Trans2_qfsinfo);
9981 case TRANSACT2_SETFSINFO:
9983 START_PROFILE(Trans2_setfsinfo);
9984 call_trans2setfsinfo(conn, req,
9985 &state->param, state->total_param,
9986 &state->data, state->total_data,
9987 state->max_data_return);
9988 END_PROFILE(Trans2_setfsinfo);
9992 case TRANSACT2_QPATHINFO:
9993 case TRANSACT2_QFILEINFO:
9995 START_PROFILE(Trans2_qpathinfo);
9996 call_trans2qfilepathinfo(conn, req, state->call,
9997 &state->param, state->total_param,
9998 &state->data, state->total_data,
9999 state->max_data_return);
10000 END_PROFILE(Trans2_qpathinfo);
10004 case TRANSACT2_SETPATHINFO:
10005 case TRANSACT2_SETFILEINFO:
10007 START_PROFILE(Trans2_setpathinfo);
10008 call_trans2setfilepathinfo(conn, req, state->call,
10009 &state->param, state->total_param,
10010 &state->data, state->total_data,
10011 state->max_data_return);
10012 END_PROFILE(Trans2_setpathinfo);
10016 case TRANSACT2_FINDNOTIFYFIRST:
10018 START_PROFILE(Trans2_findnotifyfirst);
10019 call_trans2findnotifyfirst(conn, req,
10020 &state->param, state->total_param,
10021 &state->data, state->total_data,
10022 state->max_data_return);
10023 END_PROFILE(Trans2_findnotifyfirst);
10027 case TRANSACT2_FINDNOTIFYNEXT:
10029 START_PROFILE(Trans2_findnotifynext);
10030 call_trans2findnotifynext(conn, req,
10031 &state->param, state->total_param,
10032 &state->data, state->total_data,
10033 state->max_data_return);
10034 END_PROFILE(Trans2_findnotifynext);
10038 case TRANSACT2_MKDIR:
10040 START_PROFILE(Trans2_mkdir);
10041 call_trans2mkdir(conn, req,
10042 &state->param, state->total_param,
10043 &state->data, state->total_data,
10044 state->max_data_return);
10045 END_PROFILE(Trans2_mkdir);
10049 case TRANSACT2_GET_DFS_REFERRAL:
10051 START_PROFILE(Trans2_get_dfs_referral);
10052 call_trans2getdfsreferral(conn, req,
10053 &state->param, state->total_param,
10054 &state->data, state->total_data,
10055 state->max_data_return);
10056 END_PROFILE(Trans2_get_dfs_referral);
10060 case TRANSACT2_IOCTL:
10062 START_PROFILE(Trans2_ioctl);
10063 call_trans2ioctl(conn, req,
10064 &state->param, state->total_param,
10065 &state->data, state->total_data,
10066 state->max_data_return);
10067 END_PROFILE(Trans2_ioctl);
10072 /* Error in request */
10073 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10074 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10078 /****************************************************************************
10079 Reply to a SMBtrans2.
10080 ****************************************************************************/
10082 void reply_trans2(struct smb_request *req)
10084 connection_struct *conn = req->conn;
10085 unsigned int dsoff;
10086 unsigned int dscnt;
10087 unsigned int psoff;
10088 unsigned int pscnt;
10089 unsigned int tran_call;
10090 struct trans_state *state;
10093 START_PROFILE(SMBtrans2);
10095 if (req->wct < 14) {
10096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10097 END_PROFILE(SMBtrans2);
10101 dsoff = SVAL(req->vwv+12, 0);
10102 dscnt = SVAL(req->vwv+11, 0);
10103 psoff = SVAL(req->vwv+10, 0);
10104 pscnt = SVAL(req->vwv+9, 0);
10105 tran_call = SVAL(req->vwv+14, 0);
10107 result = allow_new_trans(conn->pending_trans, req->mid);
10108 if (!NT_STATUS_IS_OK(result)) {
10109 DEBUG(2, ("Got invalid trans2 request: %s\n",
10110 nt_errstr(result)));
10111 reply_nterror(req, result);
10112 END_PROFILE(SMBtrans2);
10116 if (IS_IPC(conn)) {
10117 switch (tran_call) {
10118 /* List the allowed trans2 calls on IPC$ */
10119 case TRANSACT2_OPEN:
10120 case TRANSACT2_GET_DFS_REFERRAL:
10121 case TRANSACT2_QFILEINFO:
10122 case TRANSACT2_QFSINFO:
10123 case TRANSACT2_SETFSINFO:
10126 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10127 END_PROFILE(SMBtrans2);
10132 if ((state = talloc(conn, struct trans_state)) == NULL) {
10133 DEBUG(0, ("talloc failed\n"));
10134 reply_nterror(req, NT_STATUS_NO_MEMORY);
10135 END_PROFILE(SMBtrans2);
10139 state->cmd = SMBtrans2;
10141 state->mid = req->mid;
10142 state->vuid = req->vuid;
10143 state->setup_count = SVAL(req->vwv+13, 0);
10144 state->setup = NULL;
10145 state->total_param = SVAL(req->vwv+0, 0);
10146 state->param = NULL;
10147 state->total_data = SVAL(req->vwv+1, 0);
10148 state->data = NULL;
10149 state->max_param_return = SVAL(req->vwv+2, 0);
10150 state->max_data_return = SVAL(req->vwv+3, 0);
10151 state->max_setup_return = SVAL(req->vwv+4, 0);
10152 state->close_on_completion = BITSETW(req->vwv+5, 0);
10153 state->one_way = BITSETW(req->vwv+5, 1);
10155 state->call = tran_call;
10157 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10158 is so as a sanity check */
10159 if (state->setup_count != 1) {
10161 * Need to have rc=0 for ioctl to get job id for OS/2.
10162 * Network printing will fail if function is not successful.
10163 * Similar function in reply.c will be used if protocol
10164 * is LANMAN1.0 instead of LM1.2X002.
10165 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10166 * outbuf doesn't have to be set(only job id is used).
10168 if ( (state->setup_count == 4)
10169 && (tran_call == TRANSACT2_IOCTL)
10170 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10171 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10172 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10174 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10175 DEBUG(2,("Transaction is %d\n",tran_call));
10176 TALLOC_FREE(state);
10177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10178 END_PROFILE(SMBtrans2);
10183 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10186 if (state->total_data) {
10188 if (trans_oob(state->total_data, 0, dscnt)
10189 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10193 /* Can't use talloc here, the core routines do realloc on the
10194 * params and data. */
10195 state->data = (char *)SMB_MALLOC(state->total_data);
10196 if (state->data == NULL) {
10197 DEBUG(0,("reply_trans2: data malloc fail for %u "
10198 "bytes !\n", (unsigned int)state->total_data));
10199 TALLOC_FREE(state);
10200 reply_nterror(req, NT_STATUS_NO_MEMORY);
10201 END_PROFILE(SMBtrans2);
10205 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10208 if (state->total_param) {
10210 if (trans_oob(state->total_param, 0, pscnt)
10211 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10215 /* Can't use talloc here, the core routines do realloc on the
10216 * params and data. */
10217 state->param = (char *)SMB_MALLOC(state->total_param);
10218 if (state->param == NULL) {
10219 DEBUG(0,("reply_trans: param malloc fail for %u "
10220 "bytes !\n", (unsigned int)state->total_param));
10221 SAFE_FREE(state->data);
10222 TALLOC_FREE(state);
10223 reply_nterror(req, NT_STATUS_NO_MEMORY);
10224 END_PROFILE(SMBtrans2);
10228 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10231 state->received_data = dscnt;
10232 state->received_param = pscnt;
10234 if ((state->received_param == state->total_param) &&
10235 (state->received_data == state->total_data)) {
10237 handle_trans2(conn, req, state);
10239 SAFE_FREE(state->data);
10240 SAFE_FREE(state->param);
10241 TALLOC_FREE(state);
10242 END_PROFILE(SMBtrans2);
10246 DLIST_ADD(conn->pending_trans, state);
10248 /* We need to send an interim response then receive the rest
10249 of the parameter/data bytes */
10250 reply_outbuf(req, 0, 0);
10251 show_msg((char *)req->outbuf);
10252 END_PROFILE(SMBtrans2);
10257 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10258 SAFE_FREE(state->data);
10259 SAFE_FREE(state->param);
10260 TALLOC_FREE(state);
10261 END_PROFILE(SMBtrans2);
10262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10266 /****************************************************************************
10267 Reply to a SMBtranss2
10268 ****************************************************************************/
10270 void reply_transs2(struct smb_request *req)
10272 connection_struct *conn = req->conn;
10273 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10274 struct trans_state *state;
10276 START_PROFILE(SMBtranss2);
10278 show_msg((const char *)req->inbuf);
10280 /* Windows clients expect all replies to
10281 a transact secondary (SMBtranss2 0x33)
10282 to have a command code of transact
10283 (SMBtrans2 0x32). See bug #8989
10284 and also [MS-CIFS] section 2.2.4.47.2
10287 req->cmd = SMBtrans2;
10289 if (req->wct < 8) {
10290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10291 END_PROFILE(SMBtranss2);
10295 for (state = conn->pending_trans; state != NULL;
10296 state = state->next) {
10297 if (state->mid == req->mid) {
10302 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10304 END_PROFILE(SMBtranss2);
10308 /* Revise state->total_param and state->total_data in case they have
10309 changed downwards */
10311 if (SVAL(req->vwv+0, 0) < state->total_param)
10312 state->total_param = SVAL(req->vwv+0, 0);
10313 if (SVAL(req->vwv+1, 0) < state->total_data)
10314 state->total_data = SVAL(req->vwv+1, 0);
10316 pcnt = SVAL(req->vwv+2, 0);
10317 poff = SVAL(req->vwv+3, 0);
10318 pdisp = SVAL(req->vwv+4, 0);
10320 dcnt = SVAL(req->vwv+5, 0);
10321 doff = SVAL(req->vwv+6, 0);
10322 ddisp = SVAL(req->vwv+7, 0);
10324 state->received_param += pcnt;
10325 state->received_data += dcnt;
10327 if ((state->received_data > state->total_data) ||
10328 (state->received_param > state->total_param))
10332 if (trans_oob(state->total_param, pdisp, pcnt)
10333 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10336 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10340 if (trans_oob(state->total_data, ddisp, dcnt)
10341 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10344 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10347 if ((state->received_param < state->total_param) ||
10348 (state->received_data < state->total_data)) {
10349 END_PROFILE(SMBtranss2);
10353 handle_trans2(conn, req, state);
10355 DLIST_REMOVE(conn->pending_trans, state);
10356 SAFE_FREE(state->data);
10357 SAFE_FREE(state->param);
10358 TALLOC_FREE(state);
10360 END_PROFILE(SMBtranss2);
10365 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10366 DLIST_REMOVE(conn->pending_trans, state);
10367 SAFE_FREE(state->data);
10368 SAFE_FREE(state->param);
10369 TALLOC_FREE(state);
10370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10371 END_PROFILE(SMBtranss2);