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"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
44 #include "smb1_utils.h"
46 #define DIR_ENTRY_SAFETY_MARGIN 4096
48 static char *store_file_unix_basic(connection_struct *conn,
51 const SMB_STRUCT_STAT *psbuf);
53 static char *store_file_unix_basic_info2(connection_struct *conn,
56 const SMB_STRUCT_STAT *psbuf);
58 /****************************************************************************
59 Check if an open file handle or smb_fname is a symlink.
60 ****************************************************************************/
62 static NTSTATUS refuse_symlink(connection_struct *conn,
63 const files_struct *fsp,
64 const struct smb_filename *smb_fname)
67 const SMB_STRUCT_STAT *pst = NULL;
70 pst = &fsp->fsp_name->st;
75 if (!VALID_STAT(*pst)) {
76 int ret = vfs_stat_smb_basename(conn,
79 if (ret == -1 && errno != ENOENT) {
80 return map_nt_error_from_unix(errno);
81 } else if (ret == -1) {
82 /* it's not a symlink.. */
88 if (S_ISLNK(pst->st_ex_mode)) {
89 return NT_STATUS_ACCESS_DENIED;
94 NTSTATUS check_access_fsp(const struct files_struct *fsp,
97 if (!(fsp->access_mask & access_mask)) {
98 return NT_STATUS_ACCESS_DENIED;
103 #if defined(HAVE_POSIX_ACLS)
104 /****************************************************************************
105 Utility function to open a fsp for a POSIX handle operation.
106 ****************************************************************************/
108 static NTSTATUS get_posix_fsp(connection_struct *conn,
109 struct smb_request *req,
110 const struct smb_filename *smb_fname,
111 uint32_t access_mask,
112 files_struct **ret_fsp)
115 struct smb_filename *smb_fname_tmp = NULL;
116 uint32_t create_disposition = FILE_OPEN;
117 uint32_t share_access = FILE_SHARE_READ|
121 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
122 * but set reasonable defaults.
124 uint32_t file_attributes = 0664|FILE_FLAG_POSIX_SEMANTICS;
125 uint32_t oplock = NO_OPLOCK;
126 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
128 /* File or directory must exist. */
129 if (!VALID_STAT(smb_fname->st)) {
130 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
132 /* Cannot be a symlink. */
133 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
134 return NT_STATUS_ACCESS_DENIED;
136 /* Set options correctly for directory open. */
137 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
139 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
140 * directories, but set reasonable defaults.
142 file_attributes = 0775|FILE_FLAG_POSIX_SEMANTICS;
143 create_options = FILE_DIRECTORY_FILE;
146 /* Createfile uses a non-const smb_fname. */
147 smb_fname_tmp = cp_smb_filename(talloc_tos(),
149 if (smb_fname_tmp == NULL) {
150 return NT_STATUS_NO_MEMORY;
153 status = SMB_VFS_CREATE_FILE(
156 0, /* root_dir_fid */
157 smb_fname_tmp, /* fname */
158 access_mask, /* access_mask */
159 share_access, /* share_access */
160 create_disposition,/* create_disposition*/
161 create_options, /* create_options */
162 file_attributes,/* file_attributes */
163 oplock, /* oplock_request */
165 0, /* allocation_size */
166 0, /* private_flags */
169 ret_fsp, /* result */
171 NULL, /* in_context */
172 NULL); /* out_context */
174 TALLOC_FREE(smb_fname_tmp);
179 /********************************************************************
180 The canonical "check access" based on object handle or path function.
181 ********************************************************************/
183 static NTSTATUS check_access(connection_struct *conn,
185 const struct smb_filename *smb_fname,
186 uint32_t access_mask)
191 status = check_access_fsp(fsp, access_mask);
193 status = smbd_check_access_rights(conn, smb_fname,
200 /********************************************************************
201 Roundup a value to the nearest allocation roundup size boundary.
202 Only do this for Windows clients.
203 ********************************************************************/
205 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
207 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
209 /* Only roundup for Windows clients. */
210 enum remote_arch_types ra_type = get_remote_arch();
211 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
212 val = SMB_ROUNDUP(val,rval);
217 /****************************************************************************
218 Utility functions for dealing with extended attributes.
219 ****************************************************************************/
221 /****************************************************************************
222 Refuse to allow clients to overwrite our private xattrs.
223 ****************************************************************************/
225 bool samba_private_attr_name(const char *unix_ea_name)
227 static const char * const prohibited_ea_names[] = {
228 SAMBA_POSIX_INHERITANCE_EA_NAME,
229 SAMBA_XATTR_DOS_ATTRIB,
237 for (i = 0; prohibited_ea_names[i]; i++) {
238 if (strequal( prohibited_ea_names[i], unix_ea_name))
241 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
242 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
248 /****************************************************************************
249 Get one EA value. Fill in a struct ea_struct.
250 ****************************************************************************/
252 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
253 connection_struct *conn,
255 const struct smb_filename *smb_fname,
257 struct ea_struct *pea)
259 /* Get the value of this xattr. Max size is 64k. */
260 size_t attr_size = 256;
266 val = talloc_realloc(mem_ctx, val, char, attr_size);
268 return NT_STATUS_NO_MEMORY;
271 if (fsp && fsp->fh->fd != -1) {
272 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
274 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
275 ea_name, val, attr_size);
278 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
284 return map_nt_error_from_unix(errno);
287 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
288 dump_data(10, (uint8_t *)val, sizeret);
291 if (strnequal(ea_name, "user.", 5)) {
292 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
294 pea->name = talloc_strdup(mem_ctx, ea_name);
296 if (pea->name == NULL) {
298 return NT_STATUS_NO_MEMORY;
300 pea->value.data = (unsigned char *)val;
301 pea->value.length = (size_t)sizeret;
305 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
306 connection_struct *conn,
308 const struct smb_filename *smb_fname,
313 /* Get a list of all xattrs. Max namesize is 64k. */
314 size_t ea_namelist_size = 1024;
315 char *ea_namelist = smallbuf;
316 char *to_free = NULL;
321 ssize_t sizeret = -1;
329 status = refuse_symlink(conn, fsp, smb_fname);
330 if (!NT_STATUS_IS_OK(status)) {
332 * Just return no EA's on a symlink.
337 if (fsp && fsp->fh->fd != -1) {
338 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
341 sizeret = SMB_VFS_LISTXATTR(conn,
347 if ((sizeret == -1) && (errno == ERANGE)) {
348 ea_namelist_size = 65536;
349 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
350 if (ea_namelist == NULL) {
351 return NT_STATUS_NO_MEMORY;
353 to_free = ea_namelist;
355 if (fsp && fsp->fh->fd != -1) {
356 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
359 sizeret = SMB_VFS_LISTXATTR(conn,
367 status = map_nt_error_from_unix(errno);
368 TALLOC_FREE(to_free);
372 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
375 TALLOC_FREE(to_free);
380 * Ensure the result is 0-terminated
383 if (ea_namelist[sizeret-1] != '\0') {
384 TALLOC_FREE(to_free);
385 return NT_STATUS_INTERNAL_ERROR;
393 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
397 *pnum_names = num_names;
399 if (pnames == NULL) {
400 TALLOC_FREE(to_free);
404 names = talloc_array(mem_ctx, char *, num_names);
406 DEBUG(0, ("talloc failed\n"));
407 TALLOC_FREE(to_free);
408 return NT_STATUS_NO_MEMORY;
411 if (ea_namelist == smallbuf) {
412 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
413 if (ea_namelist == NULL) {
415 return NT_STATUS_NO_MEMORY;
418 talloc_steal(names, ea_namelist);
420 ea_namelist = talloc_realloc(names, ea_namelist, char,
422 if (ea_namelist == NULL) {
424 return NT_STATUS_NO_MEMORY;
430 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
431 names[num_names++] = p;
439 /****************************************************************************
440 Return a linked list of the total EA's. Plus the total size
441 ****************************************************************************/
443 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
444 connection_struct *conn,
446 const struct smb_filename *smb_fname,
447 size_t *pea_total_len,
448 struct ea_list **ea_list)
450 /* Get a list of all xattrs. Max namesize is 64k. */
453 struct ea_list *ea_list_head = NULL;
454 bool posix_pathnames = false;
460 if (!lp_ea_support(SNUM(conn))) {
466 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
468 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
471 status = get_ea_names_from_file(talloc_tos(),
478 if (!NT_STATUS_IS_OK(status)) {
482 if (num_names == 0) {
486 for (i=0; i<num_names; i++) {
487 struct ea_list *listp;
490 if (strnequal(names[i], "system.", 7)
491 || samba_private_attr_name(names[i]))
495 * Filter out any underlying POSIX EA names
496 * that a Windows client can't handle.
498 if (!posix_pathnames &&
499 is_invalid_windows_ea_name(names[i])) {
503 listp = talloc(mem_ctx, struct ea_list);
505 return NT_STATUS_NO_MEMORY;
508 status = get_ea_value(listp,
515 if (!NT_STATUS_IS_OK(status)) {
520 if (listp->ea.value.length == 0) {
522 * We can never return a zero length EA.
523 * Windows reports the EA's as corrupted.
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
532 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
534 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
535 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
536 (unsigned int)listp->ea.value.length));
538 DLIST_ADD_END(ea_list_head, listp);
542 /* Add on 4 for total length. */
543 if (*pea_total_len) {
547 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
548 (unsigned int)*pea_total_len));
550 *ea_list = ea_list_head;
554 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
555 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
560 if (!lp_ea_support(SNUM(conn))) {
564 if (is_ntfs_stream_smb_fname(smb_fname)) {
565 return NT_STATUS_INVALID_PARAMETER;
568 return get_ea_list_from_file_path(mem_ctx,
576 /****************************************************************************
577 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
579 ****************************************************************************/
581 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
582 connection_struct *conn, struct ea_list *ea_list)
584 unsigned int ret_data_size = 4;
587 SMB_ASSERT(total_data_size >= 4);
589 if (!lp_ea_support(SNUM(conn))) {
594 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
597 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
598 dos_namelen = strlen(dos_ea_name);
599 if (dos_namelen > 255 || dos_namelen == 0) {
602 if (ea_list->ea.value.length > 65535) {
605 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
609 /* We know we have room. */
610 SCVAL(p,0,ea_list->ea.flags);
611 SCVAL(p,1,dos_namelen);
612 SSVAL(p,2,ea_list->ea.value.length);
613 strlcpy(p+4, dos_ea_name, dos_namelen+1);
614 if (ea_list->ea.value.length > 0) {
615 memcpy(p + 4 + dos_namelen + 1,
616 ea_list->ea.value.data,
617 ea_list->ea.value.length);
620 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
621 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
624 ret_data_size = PTR_DIFF(p, pdata);
625 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
626 SIVAL(pdata,0,ret_data_size);
627 return ret_data_size;
630 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
632 unsigned int total_data_size,
633 unsigned int *ret_data_size,
634 connection_struct *conn,
635 struct ea_list *ea_list)
637 uint8_t *p = (uint8_t *)pdata;
638 uint8_t *last_start = NULL;
639 bool do_store_data = (pdata != NULL);
643 if (!lp_ea_support(SNUM(conn))) {
644 return NT_STATUS_NO_EAS_ON_FILE;
647 for (; ea_list; ea_list = ea_list->next) {
653 if (last_start != NULL && do_store_data) {
654 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
658 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
659 dos_namelen = strlen(dos_ea_name);
660 if (dos_namelen > 255 || dos_namelen == 0) {
661 return NT_STATUS_INTERNAL_ERROR;
663 if (ea_list->ea.value.length > 65535) {
664 return NT_STATUS_INTERNAL_ERROR;
667 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
670 pad = (4 - (this_size % 4)) % 4;
675 if (this_size > total_data_size) {
676 return NT_STATUS_INFO_LENGTH_MISMATCH;
679 /* We know we have room. */
680 SIVAL(p, 0x00, 0); /* next offset */
681 SCVAL(p, 0x04, ea_list->ea.flags);
682 SCVAL(p, 0x05, dos_namelen);
683 SSVAL(p, 0x06, ea_list->ea.value.length);
684 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
685 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
687 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
691 total_data_size -= this_size;
697 *ret_data_size = PTR_DIFF(p, pdata);
698 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
702 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
704 size_t total_ea_len = 0;
706 struct ea_list *ea_list = NULL;
708 if (!lp_ea_support(SNUM(conn))) {
711 mem_ctx = talloc_stackframe();
713 /* If this is a stream fsp, then we need to instead find the
714 * estimated ea len from the main file, not the stream
715 * (streams cannot have EAs), but the estimate isn't just 0 in
717 if (is_ntfs_stream_smb_fname(smb_fname)) {
720 (void)get_ea_list_from_file_path(mem_ctx,
726 if(conn->sconn->using_smb2) {
728 unsigned int ret_data_size;
730 * We're going to be using fill_ea_chained_buffer() to
731 * marshall EA's - this size is significantly larger
732 * than the SMB1 buffer. Re-calculate the size without
735 status = fill_ea_chained_buffer(mem_ctx,
741 if (!NT_STATUS_IS_OK(status)) {
744 total_ea_len = ret_data_size;
746 TALLOC_FREE(mem_ctx);
750 /****************************************************************************
751 Ensure the EA name is case insensitive by matching any existing EA name.
752 ****************************************************************************/
754 static void canonicalize_ea_name(connection_struct *conn,
756 const struct smb_filename *smb_fname,
757 fstring unix_ea_name)
760 TALLOC_CTX *mem_ctx = talloc_tos();
761 struct ea_list *ea_list;
762 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
768 if (!NT_STATUS_IS_OK(status)) {
772 for (; ea_list; ea_list = ea_list->next) {
773 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
774 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
775 &unix_ea_name[5], ea_list->ea.name));
776 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
782 /****************************************************************************
783 Set or delete an extended attribute.
784 ****************************************************************************/
786 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
787 const struct smb_filename *smb_fname, struct ea_list *ea_list)
790 bool posix_pathnames = false;
792 if (!lp_ea_support(SNUM(conn))) {
793 return NT_STATUS_EAS_NOT_SUPPORTED;
798 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
800 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
803 status = refuse_symlink(conn, fsp, smb_fname);
804 if (!NT_STATUS_IS_OK(status)) {
808 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
809 if (!NT_STATUS_IS_OK(status)) {
813 /* Setting EAs on streams isn't supported. */
814 if (is_ntfs_stream_smb_fname(smb_fname)) {
815 return NT_STATUS_INVALID_PARAMETER;
819 * Filter out invalid Windows EA names - before
820 * we set *any* of them.
823 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
824 return STATUS_INVALID_EA_NAME;
827 for (;ea_list; ea_list = ea_list->next) {
829 fstring unix_ea_name;
831 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
832 fstrcat(unix_ea_name, ea_list->ea.name);
834 canonicalize_ea_name(conn,
839 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
841 if (samba_private_attr_name(unix_ea_name)) {
842 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
843 return NT_STATUS_ACCESS_DENIED;
846 if (ea_list->ea.value.length == 0) {
847 /* Remove the attribute. */
848 if (fsp && (fsp->fh->fd != -1)) {
849 DEBUG(10,("set_ea: deleting ea name %s on "
850 "file %s by file descriptor.\n",
851 unix_ea_name, fsp_str_dbg(fsp)));
852 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
854 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
855 unix_ea_name, smb_fname->base_name));
856 ret = SMB_VFS_REMOVEXATTR(conn,
861 /* Removing a non existent attribute always succeeds. */
862 if (ret == -1 && errno == ENOATTR) {
863 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
869 if (fsp && (fsp->fh->fd != -1)) {
870 DEBUG(10,("set_ea: setting ea name %s on file "
871 "%s by file descriptor.\n",
872 unix_ea_name, fsp_str_dbg(fsp)));
873 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
874 ea_list->ea.value.data, ea_list->ea.value.length, 0);
876 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
877 unix_ea_name, smb_fname->base_name));
878 ret = SMB_VFS_SETXATTR(conn,
881 ea_list->ea.value.data,
882 ea_list->ea.value.length,
889 if (errno == ENOTSUP) {
890 return NT_STATUS_EAS_NOT_SUPPORTED;
893 return map_nt_error_from_unix(errno);
899 /****************************************************************************
900 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
901 ****************************************************************************/
903 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
905 struct ea_list *ea_list_head = NULL;
906 size_t converted_size, offset = 0;
908 while (offset + 2 < data_size) {
909 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
910 unsigned int namelen = CVAL(pdata,offset);
912 offset++; /* Go past the namelen byte. */
914 /* integer wrap paranioa. */
915 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
916 (offset > data_size) || (namelen > data_size) ||
917 (offset + namelen >= data_size)) {
920 /* Ensure the name is null terminated. */
921 if (pdata[offset + namelen] != '\0') {
924 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
926 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
927 "failed: %s", strerror(errno)));
933 offset += (namelen + 1); /* Go past the name + terminating zero. */
934 DLIST_ADD_END(ea_list_head, eal);
935 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
941 /****************************************************************************
942 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
943 ****************************************************************************/
945 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
947 struct ea_list *ea_list_head = NULL;
949 size_t bytes_used = 0;
951 while (offset < data_size) {
952 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
958 DLIST_ADD_END(ea_list_head, eal);
959 offset += bytes_used;
965 /****************************************************************************
966 Count the total EA size needed.
967 ****************************************************************************/
969 static size_t ea_list_size(struct ea_list *ealist)
972 struct ea_list *listp;
975 for (listp = ealist; listp; listp = listp->next) {
976 push_ascii_fstring(dos_ea_name, listp->ea.name);
977 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
979 /* Add on 4 for total length. */
987 /****************************************************************************
988 Return a union of EA's from a file list and a list of names.
989 The TALLOC context for the two lists *MUST* be identical as we steal
990 memory from one list to add to another. JRA.
991 ****************************************************************************/
993 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
995 struct ea_list *nlistp, *flistp;
997 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
998 for (flistp = file_list; flistp; flistp = flistp->next) {
999 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1005 /* Copy the data from this entry. */
1006 nlistp->ea.flags = flistp->ea.flags;
1007 nlistp->ea.value = flistp->ea.value;
1010 nlistp->ea.flags = 0;
1011 ZERO_STRUCT(nlistp->ea.value);
1015 *total_ea_len = ea_list_size(name_list);
1019 /****************************************************************************
1020 Send the required number of replies back.
1021 We assume all fields other than the data fields are
1022 set correctly for the type of call.
1023 HACK ! Always assumes smb_setup field is zero.
1024 ****************************************************************************/
1026 void send_trans2_replies(connection_struct *conn,
1027 struct smb_request *req,
1035 /* As we are using a protocol > LANMAN1 then the max_send
1036 variable must have been set in the sessetupX call.
1037 This takes precedence over the max_xmit field in the
1038 global struct. These different max_xmit variables should
1039 be merged as this is now too confusing */
1041 int data_to_send = datasize;
1042 int params_to_send = paramsize;
1044 const char *pp = params;
1045 const char *pd = pdata;
1046 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1047 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1048 int data_alignment_offset = 0;
1049 bool overflow = False;
1050 struct smbXsrv_connection *xconn = req->xconn;
1051 int max_send = xconn->smb1.sessions.max_send;
1053 /* Modify the data_to_send and datasize and set the error if
1054 we're trying to send more than max_data_bytes. We still send
1055 the part of the packet(s) that fit. Strange, but needed
1058 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1059 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1060 max_data_bytes, datasize ));
1061 datasize = data_to_send = max_data_bytes;
1065 /* If there genuinely are no parameters or data to send just send the empty packet */
1067 if(params_to_send == 0 && data_to_send == 0) {
1068 reply_outbuf(req, 10, 0);
1069 if (NT_STATUS_V(status)) {
1072 ntstatus_to_dos(status, &eclass, &ecode);
1073 error_packet_set((char *)req->outbuf,
1074 eclass, ecode, status,
1077 show_msg((char *)req->outbuf);
1078 if (!srv_send_smb(xconn,
1079 (char *)req->outbuf,
1080 true, req->seqnum+1,
1081 IS_CONN_ENCRYPTED(conn),
1083 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1085 TALLOC_FREE(req->outbuf);
1089 /* When sending params and data ensure that both are nicely aligned */
1090 /* Only do this alignment when there is also data to send - else
1091 can cause NT redirector problems. */
1093 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1094 data_alignment_offset = 4 - (params_to_send % 4);
1096 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1097 /* The alignment_offset is to align the param bytes on an even byte
1098 boundary. NT 4.0 Beta needs this to work correctly. */
1100 useable_space = max_send - (smb_size
1103 + data_alignment_offset);
1105 if (useable_space < 0) {
1106 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1107 "= %d!!!", useable_space));
1108 exit_server_cleanly("send_trans2_replies: Not enough space");
1111 while (params_to_send || data_to_send) {
1112 /* Calculate whether we will totally or partially fill this packet */
1114 total_sent_thistime = params_to_send + data_to_send;
1116 /* We can never send more than useable_space */
1118 * Note that 'useable_space' does not include the alignment offsets,
1119 * but we must include the alignment offsets in the calculation of
1120 * the length of the data we send over the wire, as the alignment offsets
1121 * are sent here. Fix from Marc_Jacobsen@hp.com.
1124 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1126 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1127 + data_alignment_offset);
1129 /* Set total params and data to be sent */
1130 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1131 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1133 /* Calculate how many parameters and data we can fit into
1134 * this packet. Parameters get precedence
1137 params_sent_thistime = MIN(params_to_send,useable_space);
1138 data_sent_thistime = useable_space - params_sent_thistime;
1139 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1141 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1143 /* smb_proff is the offset from the start of the SMB header to the
1144 parameter bytes, however the first 4 bytes of outbuf are
1145 the Netbios over TCP header. Thus use smb_base() to subtract
1146 them from the calculation */
1148 SSVAL(req->outbuf,smb_proff,
1149 ((smb_buf(req->outbuf)+alignment_offset)
1150 - smb_base(req->outbuf)));
1152 if(params_sent_thistime == 0)
1153 SSVAL(req->outbuf,smb_prdisp,0);
1155 /* Absolute displacement of param bytes sent in this packet */
1156 SSVAL(req->outbuf,smb_prdisp,pp - params);
1158 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1159 if(data_sent_thistime == 0) {
1160 SSVAL(req->outbuf,smb_droff,0);
1161 SSVAL(req->outbuf,smb_drdisp, 0);
1163 /* The offset of the data bytes is the offset of the
1164 parameter bytes plus the number of parameters being sent this time */
1165 SSVAL(req->outbuf, smb_droff,
1166 ((smb_buf(req->outbuf)+alignment_offset)
1167 - smb_base(req->outbuf))
1168 + params_sent_thistime + data_alignment_offset);
1169 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1172 /* Initialize the padding for alignment */
1174 if (alignment_offset != 0) {
1175 memset(smb_buf(req->outbuf), 0, alignment_offset);
1178 /* Copy the param bytes into the packet */
1180 if(params_sent_thistime) {
1181 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1182 params_sent_thistime);
1185 /* Copy in the data bytes */
1186 if(data_sent_thistime) {
1187 if (data_alignment_offset != 0) {
1188 memset((smb_buf(req->outbuf)+alignment_offset+
1189 params_sent_thistime), 0,
1190 data_alignment_offset);
1192 memcpy(smb_buf(req->outbuf)+alignment_offset
1193 +params_sent_thistime+data_alignment_offset,
1194 pd,data_sent_thistime);
1197 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1198 params_sent_thistime, data_sent_thistime, useable_space));
1199 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1200 params_to_send, data_to_send, paramsize, datasize));
1203 error_packet_set((char *)req->outbuf,
1204 ERRDOS,ERRbufferoverflow,
1205 STATUS_BUFFER_OVERFLOW,
1207 } else if (NT_STATUS_V(status)) {
1210 ntstatus_to_dos(status, &eclass, &ecode);
1211 error_packet_set((char *)req->outbuf,
1212 eclass, ecode, status,
1216 /* Send the packet */
1217 show_msg((char *)req->outbuf);
1218 if (!srv_send_smb(xconn,
1219 (char *)req->outbuf,
1220 true, req->seqnum+1,
1221 IS_CONN_ENCRYPTED(conn),
1223 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1225 TALLOC_FREE(req->outbuf);
1227 pp += params_sent_thistime;
1228 pd += data_sent_thistime;
1230 params_to_send -= params_sent_thistime;
1231 data_to_send -= data_sent_thistime;
1234 if(params_to_send < 0 || data_to_send < 0) {
1235 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1236 params_to_send, data_to_send));
1244 /****************************************************************************
1245 Reply to a TRANSACT2_OPEN.
1246 ****************************************************************************/
1248 static void call_trans2open(connection_struct *conn,
1249 struct smb_request *req,
1250 char **pparams, int total_params,
1251 char **ppdata, int total_data,
1252 unsigned int max_data_bytes)
1254 struct smb_filename *smb_fname = NULL;
1255 char *params = *pparams;
1256 char *pdata = *ppdata;
1259 bool oplock_request;
1261 bool return_additional_info;
1270 int fattr=0,mtime=0;
1271 SMB_INO_T inode = 0;
1274 struct ea_list *ea_list = NULL;
1277 uint32_t access_mask;
1278 uint32_t share_mode;
1279 uint32_t create_disposition;
1280 uint32_t create_options = 0;
1281 uint32_t private_flags = 0;
1282 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1283 TALLOC_CTX *ctx = talloc_tos();
1286 * Ensure we have enough parameters to perform the operation.
1289 if (total_params < 29) {
1290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1294 flags = SVAL(params, 0);
1295 deny_mode = SVAL(params, 2);
1296 open_attr = SVAL(params,6);
1297 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1298 if (oplock_request) {
1299 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1303 return_additional_info = BITSETW(params,0);
1304 open_sattr = SVAL(params, 4);
1305 open_time = make_unix_date3(params+8);
1307 open_ofun = SVAL(params,12);
1308 open_size = IVAL(params,14);
1309 pname = ¶ms[28];
1312 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1316 if (req->posix_pathnames) {
1317 srvstr_get_path_posix(ctx,
1326 srvstr_get_path(ctx,
1335 if (!NT_STATUS_IS_OK(status)) {
1336 reply_nterror(req, status);
1340 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1341 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1342 (unsigned int)open_ofun, open_size));
1344 status = filename_convert(ctx,
1351 if (!NT_STATUS_IS_OK(status)) {
1352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1353 reply_botherror(req,
1354 NT_STATUS_PATH_NOT_COVERED,
1355 ERRSRV, ERRbadpath);
1358 reply_nterror(req, status);
1362 if (open_ofun == 0) {
1363 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1367 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1369 &access_mask, &share_mode,
1370 &create_disposition,
1373 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1377 /* Any data in this call is an EA list. */
1378 if (total_data && (total_data != 4)) {
1379 if (total_data < 10) {
1380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1384 if (IVAL(pdata,0) > total_data) {
1385 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1386 IVAL(pdata,0), (unsigned int)total_data));
1387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1391 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1398 if (!lp_ea_support(SNUM(conn))) {
1399 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1403 if (!req->posix_pathnames &&
1404 ea_list_has_invalid_name(ea_list)) {
1406 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1407 if(*pparams == NULL ) {
1408 reply_nterror(req, NT_STATUS_NO_MEMORY);
1412 memset(params, '\0', param_len);
1413 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1414 params, param_len, NULL, 0, max_data_bytes);
1419 status = SMB_VFS_CREATE_FILE(
1422 0, /* root_dir_fid */
1423 smb_fname, /* fname */
1424 access_mask, /* access_mask */
1425 share_mode, /* share_access */
1426 create_disposition, /* create_disposition*/
1427 create_options, /* create_options */
1428 open_attr, /* file_attributes */
1429 oplock_request, /* oplock_request */
1431 open_size, /* allocation_size */
1434 ea_list, /* ea_list */
1436 &smb_action, /* psbuf */
1437 NULL, NULL); /* create context */
1439 if (!NT_STATUS_IS_OK(status)) {
1440 if (open_was_deferred(req->xconn, req->mid)) {
1441 /* We have re-scheduled this call. */
1445 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1446 reply_openerror(req, status);
1450 fsp = fcb_or_dos_open(
1457 bool ok = defer_smb1_sharing_violation(req);
1461 reply_openerror(req, status);
1465 smb_action = FILE_WAS_OPENED;
1468 size = get_file_size_stat(&smb_fname->st);
1469 fattr = dos_mode(conn, smb_fname);
1470 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1471 inode = smb_fname->st.st_ex_ino;
1472 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1473 close_file(req, fsp, ERROR_CLOSE);
1474 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1478 /* Realloc the size of parameters and data we will return */
1479 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1480 if(*pparams == NULL ) {
1481 reply_nterror(req, NT_STATUS_NO_MEMORY);
1486 SSVAL(params,0,fsp->fnum);
1487 SSVAL(params,2,fattr);
1488 srv_put_dos_date2(params,4, mtime);
1489 SIVAL(params,8, (uint32_t)size);
1490 SSVAL(params,12,deny_mode);
1491 SSVAL(params,14,0); /* open_type - file or directory. */
1492 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1494 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1495 smb_action |= EXTENDED_OPLOCK_GRANTED;
1498 SSVAL(params,18,smb_action);
1501 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1503 SIVAL(params,20,inode);
1504 SSVAL(params,24,0); /* Padding. */
1506 uint32_t ea_size = estimate_ea_size(conn, fsp,
1508 SIVAL(params, 26, ea_size);
1510 SIVAL(params, 26, 0);
1513 /* Send the required number of replies */
1514 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1516 TALLOC_FREE(smb_fname);
1519 /*********************************************************
1520 Routine to check if a given string matches exactly.
1521 as a special case a mask of "." does NOT match. That
1522 is required for correct wildcard semantics
1523 Case can be significant or not.
1524 **********************************************************/
1526 static bool exact_match(bool has_wild,
1527 bool case_sensitive,
1531 if (mask[0] == '.' && mask[1] == 0) {
1539 if (case_sensitive) {
1540 return strcmp(str,mask)==0;
1542 return strcasecmp_m(str,mask) == 0;
1546 /****************************************************************************
1547 Return the filetype for UNIX extensions.
1548 ****************************************************************************/
1550 static uint32_t unix_filetype(mode_t mode)
1553 return UNIX_TYPE_FILE;
1554 else if(S_ISDIR(mode))
1555 return UNIX_TYPE_DIR;
1557 else if(S_ISLNK(mode))
1558 return UNIX_TYPE_SYMLINK;
1561 else if(S_ISCHR(mode))
1562 return UNIX_TYPE_CHARDEV;
1565 else if(S_ISBLK(mode))
1566 return UNIX_TYPE_BLKDEV;
1569 else if(S_ISFIFO(mode))
1570 return UNIX_TYPE_FIFO;
1573 else if(S_ISSOCK(mode))
1574 return UNIX_TYPE_SOCKET;
1577 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1578 return UNIX_TYPE_UNKNOWN;
1581 /****************************************************************************
1582 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1583 ****************************************************************************/
1585 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1587 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1588 const SMB_STRUCT_STAT *psbuf,
1590 enum perm_type ptype,
1595 if (perms == SMB_MODE_NO_CHANGE) {
1596 if (!VALID_STAT(*psbuf)) {
1597 return NT_STATUS_INVALID_PARAMETER;
1599 *ret_perms = psbuf->st_ex_mode;
1600 return NT_STATUS_OK;
1604 ret = wire_perms_to_unix(perms);
1606 if (ptype == PERM_NEW_FILE) {
1608 * "create mask"/"force create mode" are
1609 * only applied to new files, not existing ones.
1611 ret &= lp_create_mask(SNUM(conn));
1612 /* Add in force bits */
1613 ret |= lp_force_create_mode(SNUM(conn));
1614 } else if (ptype == PERM_NEW_DIR) {
1616 * "directory mask"/"force directory mode" are
1617 * only applied to new directories, not existing ones.
1619 ret &= lp_directory_mask(SNUM(conn));
1620 /* Add in force bits */
1621 ret |= lp_force_directory_mode(SNUM(conn));
1625 return NT_STATUS_OK;
1628 /****************************************************************************
1629 Needed to show the msdfs symlinks as directories. Modifies psbuf
1630 to be a directory if it's a msdfs link.
1631 ****************************************************************************/
1633 static bool check_msdfs_link(connection_struct *conn,
1634 struct smb_filename *smb_fname)
1636 int saved_errno = errno;
1637 if(lp_host_msdfs() &&
1638 lp_msdfs_root(SNUM(conn)) &&
1639 is_msdfs_link(conn, smb_fname)) {
1641 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1643 smb_fname->base_name));
1644 smb_fname->st.st_ex_mode =
1645 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1646 errno = saved_errno;
1649 errno = saved_errno;
1654 /****************************************************************************
1655 Get a level dependent lanman2 dir entry.
1656 ****************************************************************************/
1658 struct smbd_dirptr_lanman2_state {
1659 connection_struct *conn;
1660 uint32_t info_level;
1661 bool check_mangled_names;
1663 bool got_exact_match;
1666 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1672 struct smbd_dirptr_lanman2_state *state =
1673 (struct smbd_dirptr_lanman2_state *)private_data;
1675 char mangled_name[13]; /* mangled 8.3 name. */
1679 /* Mangle fname if it's an illegal name. */
1680 if (mangle_must_mangle(dname, state->conn->params)) {
1682 * Slow path - ensure we can push the original name as UCS2. If
1683 * not, then just don't return this name.
1687 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1688 uint8_t *tmp = talloc_array(talloc_tos(),
1692 status = srvstr_push(NULL,
1693 FLAGS2_UNICODE_STRINGS,
1702 if (!NT_STATUS_IS_OK(status)) {
1706 ok = name_to_8_3(dname, mangled_name,
1707 true, state->conn->params);
1711 fname = mangled_name;
1716 got_match = exact_match(state->has_wild,
1717 state->conn->case_sensitive,
1719 state->got_exact_match = got_match;
1721 got_match = mask_match(fname, mask,
1722 state->conn->case_sensitive);
1725 if(!got_match && state->check_mangled_names &&
1726 !mangle_is_8_3(fname, false, state->conn->params)) {
1728 * It turns out that NT matches wildcards against
1729 * both long *and* short names. This may explain some
1730 * of the wildcard wierdness from old DOS clients
1731 * that some people have been seeing.... JRA.
1733 /* Force the mangling into 8.3. */
1734 ok = name_to_8_3(fname, mangled_name,
1735 false, state->conn->params);
1740 got_match = exact_match(state->has_wild,
1741 state->conn->case_sensitive,
1742 mangled_name, mask);
1743 state->got_exact_match = got_match;
1745 got_match = mask_match(mangled_name, mask,
1746 state->conn->case_sensitive);
1754 *_fname = talloc_strdup(ctx, fname);
1755 if (*_fname == NULL) {
1762 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1764 struct smb_filename *smb_fname,
1768 struct smbd_dirptr_lanman2_state *state =
1769 (struct smbd_dirptr_lanman2_state *)private_data;
1770 bool ms_dfs_link = false;
1773 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1774 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1775 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1776 "Couldn't lstat [%s] (%s)\n",
1777 smb_fname_str_dbg(smb_fname),
1781 } else if (!VALID_STAT(smb_fname->st) &&
1782 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1783 /* Needed to show the msdfs symlinks as
1786 ms_dfs_link = check_msdfs_link(state->conn,
1789 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1790 "Couldn't stat [%s] (%s)\n",
1791 smb_fname_str_dbg(smb_fname),
1798 mode = dos_mode_msdfs(state->conn, smb_fname);
1799 } else if (get_dosmode) {
1800 mode = dos_mode(state->conn, smb_fname);
1807 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1808 connection_struct *conn,
1810 uint32_t info_level,
1811 struct ea_list *name_list,
1812 bool check_mangled_names,
1813 bool requires_resume_key,
1816 const struct smb_filename *smb_fname,
1817 int space_remaining,
1823 uint64_t *last_entry_off)
1825 char *p, *q, *pdata = *ppdata;
1827 uint64_t file_size = 0;
1828 uint64_t allocation_size = 0;
1829 uint64_t file_id = 0;
1831 struct timespec mdate_ts = {0};
1832 struct timespec adate_ts = {0};
1833 struct timespec cdate_ts = {0};
1834 struct timespec create_date_ts = {0};
1835 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1837 char *last_entry_ptr;
1842 struct readdir_attr_data *readdir_attr_data = NULL;
1844 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1845 file_size = get_file_size_stat(&smb_fname->st);
1847 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1849 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1856 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1858 mdate_ts = smb_fname->st.st_ex_mtime;
1859 adate_ts = smb_fname->st.st_ex_atime;
1860 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1861 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1863 if (lp_dos_filetime_resolution(SNUM(conn))) {
1864 dos_filetime_timespec(&create_date_ts);
1865 dos_filetime_timespec(&mdate_ts);
1866 dos_filetime_timespec(&adate_ts);
1867 dos_filetime_timespec(&cdate_ts);
1870 create_date = convert_timespec_to_time_t(create_date_ts);
1871 mdate = convert_timespec_to_time_t(mdate_ts);
1872 adate = convert_timespec_to_time_t(adate_ts);
1874 /* align the record */
1875 SMB_ASSERT(align >= 1);
1877 off = (int)PTR_DIFF(pdata, base_data);
1878 pad = (off + (align-1)) & ~(align-1);
1881 if (pad && pad > space_remaining) {
1882 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1883 "for padding (wanted %u, had %d)\n",
1886 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1890 /* initialize padding to 0 */
1892 memset(pdata, 0, pad);
1894 space_remaining -= pad;
1896 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1906 switch (info_level) {
1907 case SMB_FIND_INFO_STANDARD:
1908 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1909 if(requires_resume_key) {
1913 srv_put_dos_date2(p,0,create_date);
1914 srv_put_dos_date2(p,4,adate);
1915 srv_put_dos_date2(p,8,mdate);
1916 SIVAL(p,12,(uint32_t)file_size);
1917 SIVAL(p,16,(uint32_t)allocation_size);
1921 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1922 p += ucs2_align(base_data, p, 0);
1924 status = srvstr_push(base_data, flags2, p,
1925 fname, PTR_DIFF(end_data, p),
1926 STR_TERMINATE, &len);
1927 if (!NT_STATUS_IS_OK(status)) {
1930 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1932 SCVAL(nameptr, -1, len - 2);
1934 SCVAL(nameptr, -1, 0);
1938 SCVAL(nameptr, -1, len - 1);
1940 SCVAL(nameptr, -1, 0);
1946 case SMB_FIND_EA_SIZE:
1947 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1948 if (requires_resume_key) {
1952 srv_put_dos_date2(p,0,create_date);
1953 srv_put_dos_date2(p,4,adate);
1954 srv_put_dos_date2(p,8,mdate);
1955 SIVAL(p,12,(uint32_t)file_size);
1956 SIVAL(p,16,(uint32_t)allocation_size);
1959 unsigned int ea_size = estimate_ea_size(conn, NULL,
1961 SIVAL(p,22,ea_size); /* Extended attributes */
1965 status = srvstr_push(base_data, flags2,
1966 p, fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE | STR_NOALIGN, &len);
1968 if (!NT_STATUS_IS_OK(status)) {
1971 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1984 SCVAL(nameptr,0,len);
1986 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1989 case SMB_FIND_EA_LIST:
1991 struct ea_list *file_list = NULL;
1994 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1996 return NT_STATUS_INVALID_PARAMETER;
1998 if (requires_resume_key) {
2002 srv_put_dos_date2(p,0,create_date);
2003 srv_put_dos_date2(p,4,adate);
2004 srv_put_dos_date2(p,8,mdate);
2005 SIVAL(p,12,(uint32_t)file_size);
2006 SIVAL(p,16,(uint32_t)allocation_size);
2008 p += 22; /* p now points to the EA area. */
2010 status = get_ea_list_from_file(ctx, conn, NULL,
2012 &ea_len, &file_list);
2013 if (!NT_STATUS_IS_OK(status)) {
2016 name_list = ea_list_union(name_list, file_list, &ea_len);
2018 /* We need to determine if this entry will fit in the space available. */
2019 /* Max string size is 255 bytes. */
2020 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2021 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2022 "(wanted %u, had %d)\n",
2023 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2025 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2028 /* Push the ea_data followed by the name. */
2029 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2031 status = srvstr_push(base_data, flags2,
2032 p + 1, fname, PTR_DIFF(end_data, p+1),
2033 STR_TERMINATE | STR_NOALIGN, &len);
2034 if (!NT_STATUS_IS_OK(status)) {
2037 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2050 SCVAL(nameptr,0,len);
2052 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2056 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2057 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2058 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2060 SIVAL(p,0,reskey); p += 4;
2061 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2062 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2063 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2064 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2065 SOFF_T(p,0,file_size); p += 8;
2066 SOFF_T(p,0,allocation_size); p += 8;
2067 SIVAL(p,0,mode); p += 4;
2068 q = p; p += 4; /* q is placeholder for name length. */
2069 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2070 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2072 unsigned int ea_size = estimate_ea_size(conn, NULL,
2074 SIVAL(p,0,ea_size); /* Extended attributes */
2077 /* Clear the short name buffer. This is
2078 * IMPORTANT as not doing so will trigger
2079 * a Win2k client bug. JRA.
2081 if (!was_8_3 && check_mangled_names) {
2082 char mangled_name[13]; /* mangled 8.3 name. */
2083 if (!name_to_8_3(fname,mangled_name,True,
2085 /* Error - mangle failed ! */
2086 memset(mangled_name,'\0',12);
2088 mangled_name[12] = 0;
2089 status = srvstr_push(base_data, flags2,
2090 p+2, mangled_name, 24,
2091 STR_UPPER|STR_UNICODE, &len);
2092 if (!NT_STATUS_IS_OK(status)) {
2096 memset(p + 2 + len,'\0',24 - len);
2103 status = srvstr_push(base_data, flags2, p,
2104 fname, PTR_DIFF(end_data, p),
2105 STR_TERMINATE_ASCII, &len);
2106 if (!NT_STATUS_IS_OK(status)) {
2112 len = PTR_DIFF(p, pdata);
2113 pad = (len + (align-1)) & ~(align-1);
2115 * offset to the next entry, the caller
2116 * will overwrite it for the last entry
2117 * that's why we always include the padding
2121 * set padding to zero
2124 memset(p, 0, pad - len);
2131 case SMB_FIND_FILE_DIRECTORY_INFO:
2132 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2134 SIVAL(p,0,reskey); p += 4;
2135 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2136 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2137 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2138 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2139 SOFF_T(p,0,file_size); p += 8;
2140 SOFF_T(p,0,allocation_size); p += 8;
2141 SIVAL(p,0,mode); p += 4;
2142 status = srvstr_push(base_data, flags2,
2143 p + 4, fname, PTR_DIFF(end_data, p+4),
2144 STR_TERMINATE_ASCII, &len);
2145 if (!NT_STATUS_IS_OK(status)) {
2151 len = PTR_DIFF(p, pdata);
2152 pad = (len + (align-1)) & ~(align-1);
2154 * offset to the next entry, the caller
2155 * will overwrite it for the last entry
2156 * that's why we always include the padding
2160 * set padding to zero
2163 memset(p, 0, pad - len);
2170 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2171 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2173 SIVAL(p,0,reskey); p += 4;
2174 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2175 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2176 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2177 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2178 SOFF_T(p,0,file_size); p += 8;
2179 SOFF_T(p,0,allocation_size); p += 8;
2180 SIVAL(p,0,mode); p += 4;
2181 q = p; p += 4; /* q is placeholder for name length. */
2182 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2183 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2185 unsigned int ea_size = estimate_ea_size(conn, NULL,
2187 SIVAL(p,0,ea_size); /* Extended attributes */
2190 status = srvstr_push(base_data, flags2, p,
2191 fname, PTR_DIFF(end_data, p),
2192 STR_TERMINATE_ASCII, &len);
2193 if (!NT_STATUS_IS_OK(status)) {
2199 len = PTR_DIFF(p, pdata);
2200 pad = (len + (align-1)) & ~(align-1);
2202 * offset to the next entry, the caller
2203 * will overwrite it for the last entry
2204 * that's why we always include the padding
2208 * set padding to zero
2211 memset(p, 0, pad - len);
2218 case SMB_FIND_FILE_NAMES_INFO:
2219 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2221 SIVAL(p,0,reskey); p += 4;
2223 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2224 acl on a dir (tridge) */
2225 status = srvstr_push(base_data, flags2, p,
2226 fname, PTR_DIFF(end_data, p),
2227 STR_TERMINATE_ASCII, &len);
2228 if (!NT_STATUS_IS_OK(status)) {
2234 len = PTR_DIFF(p, pdata);
2235 pad = (len + (align-1)) & ~(align-1);
2237 * offset to the next entry, the caller
2238 * will overwrite it for the last entry
2239 * that's why we always include the padding
2243 * set padding to zero
2246 memset(p, 0, pad - len);
2253 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2254 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2256 SIVAL(p,0,reskey); p += 4;
2257 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2258 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2259 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2260 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2261 SOFF_T(p,0,file_size); p += 8;
2262 SOFF_T(p,0,allocation_size); p += 8;
2263 SIVAL(p,0,mode); p += 4;
2264 q = p; p += 4; /* q is placeholder for name length. */
2265 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2266 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2268 unsigned int ea_size = estimate_ea_size(conn, NULL,
2270 SIVAL(p,0,ea_size); /* Extended attributes */
2273 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2274 SBVAL(p,0,file_id); p += 8;
2275 status = srvstr_push(base_data, flags2, p,
2276 fname, PTR_DIFF(end_data, p),
2277 STR_TERMINATE_ASCII, &len);
2278 if (!NT_STATUS_IS_OK(status)) {
2284 len = PTR_DIFF(p, pdata);
2285 pad = (len + (align-1)) & ~(align-1);
2287 * offset to the next entry, the caller
2288 * will overwrite it for the last entry
2289 * that's why we always include the padding
2293 * set padding to zero
2296 memset(p, 0, pad - len);
2303 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2304 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2305 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2307 SIVAL(p,0,reskey); p += 4;
2308 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2309 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2310 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2311 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2312 SOFF_T(p,0,file_size); p += 8;
2313 SOFF_T(p,0,allocation_size); p += 8;
2314 SIVAL(p,0,mode); p += 4;
2315 q = p; p += 4; /* q is placeholder for name length */
2316 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2317 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2318 } else if (readdir_attr_data &&
2319 readdir_attr_data->type == RDATTR_AAPL) {
2321 * OS X specific SMB2 extension negotiated via
2322 * AAPL create context: return max_access in
2325 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2327 unsigned int ea_size = estimate_ea_size(conn, NULL,
2329 SIVAL(p,0,ea_size); /* Extended attributes */
2333 if (readdir_attr_data &&
2334 readdir_attr_data->type == RDATTR_AAPL) {
2336 * OS X specific SMB2 extension negotiated via
2337 * AAPL create context: return resource fork
2338 * length and compressed FinderInfo in
2341 * According to documentation short_name_len
2342 * should be 0, but on the wire behaviour
2343 * shows its set to 24 by clients.
2347 /* Resourefork length */
2348 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2350 /* Compressed FinderInfo */
2351 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2352 } else if (!was_8_3 && check_mangled_names) {
2353 char mangled_name[13]; /* mangled 8.3 name. */
2354 if (!name_to_8_3(fname,mangled_name,True,
2356 /* Error - mangle failed ! */
2357 memset(mangled_name,'\0',12);
2359 mangled_name[12] = 0;
2360 status = srvstr_push(base_data, flags2,
2361 p+2, mangled_name, 24,
2362 STR_UPPER|STR_UNICODE, &len);
2363 if (!NT_STATUS_IS_OK(status)) {
2368 memset(p + 2 + len,'\0',24 - len);
2372 /* Clear the short name buffer. This is
2373 * IMPORTANT as not doing so will trigger
2374 * a Win2k client bug. JRA.
2381 if (readdir_attr_data &&
2382 readdir_attr_data->type == RDATTR_AAPL) {
2384 * OS X specific SMB2 extension negotiated via
2385 * AAPL create context: return UNIX mode in
2388 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2389 SSVAL(p, 0, aapl_mode);
2395 SBVAL(p,0,file_id); p += 8;
2396 status = srvstr_push(base_data, flags2, p,
2397 fname, PTR_DIFF(end_data, p),
2398 STR_TERMINATE_ASCII, &len);
2399 if (!NT_STATUS_IS_OK(status)) {
2405 len = PTR_DIFF(p, pdata);
2406 pad = (len + (align-1)) & ~(align-1);
2408 * offset to the next entry, the caller
2409 * will overwrite it for the last entry
2410 * that's why we always include the padding
2414 * set padding to zero
2417 memset(p, 0, pad - len);
2424 /* CIFS UNIX Extension. */
2426 case SMB_FIND_FILE_UNIX:
2427 case SMB_FIND_FILE_UNIX_INFO2:
2429 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2431 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2433 if (info_level == SMB_FIND_FILE_UNIX) {
2434 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2435 p = store_file_unix_basic(conn, p,
2436 NULL, &smb_fname->st);
2437 status = srvstr_push(base_data, flags2, p,
2438 fname, PTR_DIFF(end_data, p),
2439 STR_TERMINATE, &len);
2440 if (!NT_STATUS_IS_OK(status)) {
2444 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2445 p = store_file_unix_basic_info2(conn, p,
2446 NULL, &smb_fname->st);
2449 status = srvstr_push(base_data, flags2, p, fname,
2450 PTR_DIFF(end_data, p), 0, &len);
2451 if (!NT_STATUS_IS_OK(status)) {
2454 SIVAL(nameptr, 0, len);
2459 len = PTR_DIFF(p, pdata);
2460 pad = (len + (align-1)) & ~(align-1);
2462 * offset to the next entry, the caller
2463 * will overwrite it for the last entry
2464 * that's why we always include the padding
2468 * set padding to zero
2471 memset(p, 0, pad - len);
2476 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2481 return NT_STATUS_INVALID_LEVEL;
2484 if (PTR_DIFF(p,pdata) > space_remaining) {
2485 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2486 "(wanted %u, had %d)\n",
2487 (unsigned int)PTR_DIFF(p,pdata),
2489 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2492 /* Setup the last entry pointer, as an offset from base_data */
2493 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2494 /* Advance the data pointer to the next slot */
2497 return NT_STATUS_OK;
2500 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2501 connection_struct *conn,
2502 struct dptr_struct *dirptr,
2504 const char *path_mask,
2507 int requires_resume_key,
2516 int space_remaining,
2517 struct smb_filename **_smb_fname,
2518 bool *got_exact_match,
2519 int *_last_entry_off,
2520 struct ea_list *name_list,
2521 struct file_id *file_id)
2524 const char *mask = NULL;
2525 long prev_dirpos = 0;
2528 struct smb_filename *smb_fname = NULL;
2529 struct smbd_dirptr_lanman2_state state;
2531 uint64_t last_entry_off = 0;
2533 enum mangled_names_options mangled_names;
2534 bool marshall_with_83_names;
2536 mangled_names = lp_mangled_names(conn->params);
2540 state.info_level = info_level;
2541 if (mangled_names != MANGLED_NAMES_NO) {
2542 state.check_mangled_names = true;
2544 state.has_wild = dptr_has_wild(dirptr);
2545 state.got_exact_match = false;
2547 *got_exact_match = false;
2549 p = strrchr_m(path_mask,'/');
2560 ok = smbd_dirptr_get_entry(ctx,
2567 smbd_dirptr_lanman2_match_fn,
2568 smbd_dirptr_lanman2_mode_fn,
2575 return NT_STATUS_END_OF_FILE;
2578 *got_exact_match = state.got_exact_match;
2580 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2582 status = smbd_marshall_dir_entry(ctx,
2587 marshall_with_83_names,
2588 requires_resume_key,
2599 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2600 DEBUG(1,("Conversion error: illegal character: %s\n",
2601 smb_fname_str_dbg(smb_fname)));
2604 if (file_id != NULL) {
2605 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2608 if (!NT_STATUS_IS_OK(status) &&
2609 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2611 TALLOC_FREE(smb_fname);
2616 if (_smb_fname != NULL) {
2617 struct smb_filename *name = NULL;
2619 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2621 TALLOC_FREE(smb_fname);
2623 return NT_STATUS_NO_MEMORY;
2628 TALLOC_FREE(smb_fname);
2631 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2632 dptr_SeekDir(dirptr, prev_dirpos);
2636 *_last_entry_off = last_entry_off;
2637 return NT_STATUS_OK;
2640 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2641 connection_struct *conn,
2642 struct dptr_struct *dirptr,
2644 const char *path_mask,
2647 bool requires_resume_key,
2653 int space_remaining,
2654 bool *got_exact_match,
2655 int *last_entry_off,
2656 struct ea_list *name_list)
2659 const bool do_pad = true;
2661 if (info_level >= 1 && info_level <= 3) {
2662 /* No alignment on earlier info levels. */
2666 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2667 path_mask, dirtype, info_level,
2668 requires_resume_key, dont_descend, ask_sharemode,
2669 true, align, do_pad,
2670 ppdata, base_data, end_data,
2674 last_entry_off, name_list, NULL);
2677 /****************************************************************************
2678 Reply to a TRANS2_FINDFIRST.
2679 ****************************************************************************/
2681 static void call_trans2findfirst(connection_struct *conn,
2682 struct smb_request *req,
2683 char **pparams, int total_params,
2684 char **ppdata, int total_data,
2685 unsigned int max_data_bytes)
2687 /* We must be careful here that we don't return more than the
2688 allowed number of data bytes. If this means returning fewer than
2689 maxentries then so be it. We assume that the redirector has
2690 enough room for the fixed number of parameter bytes it has
2692 struct smb_filename *smb_dname = NULL;
2693 char *params = *pparams;
2694 char *pdata = *ppdata;
2698 uint16_t findfirst_flags;
2699 bool close_after_first;
2701 bool requires_resume_key;
2703 char *directory = NULL;
2706 int last_entry_off=0;
2710 bool finished = False;
2711 bool dont_descend = False;
2712 bool out_of_space = False;
2713 int space_remaining;
2714 bool mask_contains_wcard = False;
2715 struct ea_list *ea_list = NULL;
2716 NTSTATUS ntstatus = NT_STATUS_OK;
2717 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2718 struct smbd_server_connection *sconn = req->sconn;
2719 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2720 ucf_flags_from_smb_request(req);
2721 bool backup_priv = false;
2722 bool as_root = false;
2723 files_struct *fsp = NULL;
2726 if (total_params < 13) {
2727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2731 dirtype = SVAL(params,0);
2732 maxentries = SVAL(params,2);
2733 findfirst_flags = SVAL(params,4);
2734 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2735 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2736 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2737 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2738 security_token_has_privilege(get_current_nttok(conn),
2741 info_level = SVAL(params,6);
2743 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2744 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2745 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2747 info_level, max_data_bytes));
2750 /* W2K3 seems to treat zero as 1. */
2754 switch (info_level) {
2755 case SMB_FIND_INFO_STANDARD:
2756 case SMB_FIND_EA_SIZE:
2757 case SMB_FIND_EA_LIST:
2758 case SMB_FIND_FILE_DIRECTORY_INFO:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2760 case SMB_FIND_FILE_NAMES_INFO:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2765 case SMB_FIND_FILE_UNIX:
2766 case SMB_FIND_FILE_UNIX_INFO2:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode = false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2773 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2776 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 if (req->posix_pathnames) {
2781 srvstr_get_path_wcard_posix(talloc_tos(),
2789 &mask_contains_wcard);
2791 srvstr_get_path_wcard(talloc_tos(),
2799 &mask_contains_wcard);
2801 if (!NT_STATUS_IS_OK(ntstatus)) {
2802 reply_nterror(req, ntstatus);
2809 ntstatus = filename_convert_with_privilege(talloc_tos(),
2814 &mask_contains_wcard,
2817 ntstatus = filename_convert(talloc_tos(), conn,
2821 &mask_contains_wcard,
2825 if (!NT_STATUS_IS_OK(ntstatus)) {
2826 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2827 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2828 ERRSRV, ERRbadpath);
2831 reply_nterror(req, ntstatus);
2835 mask = smb_dname->original_lcomp;
2837 directory = smb_dname->base_name;
2839 p = strrchr_m(directory,'/');
2841 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2842 if((directory[0] == '.') && (directory[1] == '\0')) {
2843 mask = talloc_strdup(talloc_tos(),"*");
2845 reply_nterror(req, NT_STATUS_NO_MEMORY);
2848 mask_contains_wcard = True;
2854 if (p == NULL || p == directory) {
2855 /* Ensure we don't have a directory name of "". */
2856 directory = talloc_strdup(talloc_tos(), ".");
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2861 /* Ensure smb_dname->base_name matches. */
2862 smb_dname->base_name = directory;
2865 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2867 if (info_level == SMB_FIND_EA_LIST) {
2870 if (total_data < 4) {
2871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2875 ea_size = IVAL(pdata,0);
2876 if (ea_size != total_data) {
2877 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2878 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2883 if (!lp_ea_support(SNUM(conn))) {
2884 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2888 /* Pull out the list of names. */
2889 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2896 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2901 *ppdata = (char *)SMB_REALLOC(
2902 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2903 if(*ppdata == NULL ) {
2904 reply_nterror(req, NT_STATUS_NO_MEMORY);
2908 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2910 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2913 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2914 /* Realloc the params space */
2915 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2916 if (*pparams == NULL) {
2917 reply_nterror(req, NT_STATUS_NO_MEMORY);
2923 * As we've cut off the last component from
2924 * smb_fname we need to re-stat smb_dname
2925 * so FILE_OPEN disposition knows the directory
2928 if (req->posix_pathnames) {
2929 ret = SMB_VFS_LSTAT(conn, smb_dname);
2931 ret = SMB_VFS_STAT(conn, smb_dname);
2935 ntstatus = map_nt_error_from_unix(errno);
2936 reply_nterror(req, ntstatus);
2941 * Open an fsp on this directory for the dptr.
2943 ntstatus = SMB_VFS_CREATE_FILE(
2946 0, /* root_dir_fid */
2947 smb_dname, /* dname */
2948 FILE_LIST_DIRECTORY, /* access_mask */
2950 FILE_SHARE_WRITE, /* share_access */
2951 FILE_OPEN, /* create_disposition*/
2952 FILE_DIRECTORY_FILE, /* create_options */
2953 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2954 NO_OPLOCK, /* oplock_request */
2956 0, /* allocation_size */
2957 0, /* private_flags */
2962 NULL, /* in_context */
2963 NULL);/* out_context */
2965 if (!NT_STATUS_IS_OK(ntstatus)) {
2966 DBG_ERR("failed to open directory %s\n",
2967 smb_fname_str_dbg(smb_dname));
2968 reply_nterror(req, ntstatus);
2972 /* Save the wildcard match and attribs we are using on this directory -
2973 needed as lanman2 assumes these are being saved between calls */
2975 ntstatus = dptr_create(conn,
2982 mask_contains_wcard,
2986 if (!NT_STATUS_IS_OK(ntstatus)) {
2988 * Use NULL here for the first parameter (req)
2989 * as this is not a client visible handle so
2990 * can'tbe part of an SMB1 chain.
2992 close_file(NULL, fsp, NORMAL_CLOSE);
2994 reply_nterror(req, ntstatus);
2999 /* Remember this in case we have
3000 to do a findnext. */
3001 dptr_set_priv(fsp->dptr);
3004 dptr_num = dptr_dnum(fsp->dptr);
3005 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3007 /* We don't need to check for VOL here as this is returned by
3008 a different TRANS2 call. */
3010 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3011 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
3012 if (in_list(directory,
3013 lp_dont_descend(talloc_tos(), SNUM(conn)),
3014 conn->case_sensitive)) {
3015 dont_descend = True;
3019 space_remaining = max_data_bytes;
3020 out_of_space = False;
3022 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3023 bool got_exact_match = False;
3025 /* this is a heuristic to avoid seeking the dirptr except when
3026 absolutely necessary. It allows for a filename of about 40 chars */
3027 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3028 out_of_space = True;
3031 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3035 mask,dirtype,info_level,
3036 requires_resume_key,dont_descend,
3041 &last_entry_off, ea_list);
3042 if (NT_STATUS_EQUAL(ntstatus,
3043 NT_STATUS_ILLEGAL_CHARACTER)) {
3045 * Bad character conversion on name. Ignore this
3050 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3051 out_of_space = true;
3053 finished = !NT_STATUS_IS_OK(ntstatus);
3057 if (!finished && !out_of_space)
3061 * As an optimisation if we know we aren't looking
3062 * for a wildcard name (ie. the name matches the wildcard exactly)
3063 * then we can finish on any (first) match.
3064 * This speeds up large directory searches. JRA.
3070 /* Ensure space_remaining never goes -ve. */
3071 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3072 space_remaining = 0;
3073 out_of_space = true;
3075 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3079 /* Check if we can close the dirptr */
3080 if(close_after_first || (finished && close_if_end)) {
3081 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3083 close_file(NULL, fsp, NORMAL_CLOSE);
3088 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3089 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3090 * the protocol level is less than NT1. Tested with smbclient. JRA.
3091 * This should fix the OS/2 client bug #2335.
3094 if(numentries == 0) {
3097 * We may have already closed the file in the
3098 * close_after_first or finished case above.
3101 close_file(NULL, fsp, NORMAL_CLOSE);
3104 if (get_Protocol() < PROTOCOL_NT1) {
3105 reply_force_doserror(req, ERRDOS, ERRnofiles);
3108 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3109 ERRDOS, ERRbadfile);
3114 /* At this point pdata points to numentries directory entries. */
3116 /* Set up the return parameter block */
3117 SSVAL(params,0,dptr_num);
3118 SSVAL(params,2,numentries);
3119 SSVAL(params,4,finished);
3120 SSVAL(params,6,0); /* Never an EA error */
3121 SSVAL(params,8,last_entry_off);
3123 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3126 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3127 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3129 reply_nterror(req, NT_STATUS_NO_MEMORY);
3133 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3134 smb_fn_name(req->cmd),
3135 mask, directory, dirtype, numentries ) );
3138 * Force a name mangle here to ensure that the
3139 * mask as an 8.3 name is top of the mangled cache.
3140 * The reasons for this are subtle. Don't remove
3141 * this code unless you know what you are doing
3142 * (see PR#13758). JRA.
3145 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3146 char mangled_name[13];
3147 name_to_8_3(mask, mangled_name, True, conn->params);
3155 TALLOC_FREE(smb_dname);
3159 /****************************************************************************
3160 Reply to a TRANS2_FINDNEXT.
3161 ****************************************************************************/
3163 static void call_trans2findnext(connection_struct *conn,
3164 struct smb_request *req,
3165 char **pparams, int total_params,
3166 char **ppdata, int total_data,
3167 unsigned int max_data_bytes)
3169 /* We must be careful here that we don't return more than the
3170 allowed number of data bytes. If this means returning fewer than
3171 maxentries then so be it. We assume that the redirector has
3172 enough room for the fixed number of parameter bytes it has
3174 char *params = *pparams;
3175 char *pdata = *ppdata;
3179 uint16_t info_level;
3180 uint32_t resume_key;
3181 uint16_t findnext_flags;
3182 bool close_after_request;
3184 bool requires_resume_key;
3186 bool mask_contains_wcard = False;
3187 char *resume_name = NULL;
3188 const char *mask = NULL;
3189 const char *directory = NULL;
3193 int i, last_entry_off=0;
3194 bool finished = False;
3195 bool dont_descend = False;
3196 bool out_of_space = False;
3197 int space_remaining;
3198 struct ea_list *ea_list = NULL;
3199 NTSTATUS ntstatus = NT_STATUS_OK;
3200 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3201 TALLOC_CTX *ctx = talloc_tos();
3202 struct smbd_server_connection *sconn = req->sconn;
3203 bool backup_priv = false;
3204 bool as_root = false;
3205 files_struct *fsp = NULL;
3207 if (total_params < 13) {
3208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3212 dptr_num = SVAL(params,0);
3213 maxentries = SVAL(params,2);
3214 info_level = SVAL(params,4);
3215 resume_key = IVAL(params,6);
3216 findnext_flags = SVAL(params,10);
3217 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3218 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3219 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3220 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3222 if (!continue_bit) {
3223 /* We only need resume_name if continue_bit is zero. */
3224 if (req->posix_pathnames) {
3225 srvstr_get_path_wcard_posix(ctx,
3233 &mask_contains_wcard);
3235 srvstr_get_path_wcard(ctx,
3243 &mask_contains_wcard);
3245 if (!NT_STATUS_IS_OK(ntstatus)) {
3246 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3247 complain (it thinks we're asking for the directory above the shared
3248 path or an invalid name). Catch this as the resume name is only compared, never used in
3249 a file access. JRA. */
3250 srvstr_pull_talloc(ctx, params, req->flags2,
3251 &resume_name, params+12,
3255 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3256 reply_nterror(req, ntstatus);
3262 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3263 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3264 resume_key = %d resume name = %s continue=%d level = %d\n",
3265 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3266 requires_resume_key, resume_key,
3267 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3270 /* W2K3 seems to treat zero as 1. */
3274 switch (info_level) {
3275 case SMB_FIND_INFO_STANDARD:
3276 case SMB_FIND_EA_SIZE:
3277 case SMB_FIND_EA_LIST:
3278 case SMB_FIND_FILE_DIRECTORY_INFO:
3279 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3280 case SMB_FIND_FILE_NAMES_INFO:
3281 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3282 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3283 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3285 case SMB_FIND_FILE_UNIX:
3286 case SMB_FIND_FILE_UNIX_INFO2:
3287 /* Always use filesystem for UNIX mtime query. */
3288 ask_sharemode = false;
3289 if (!lp_unix_extensions()) {
3290 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3295 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3299 if (info_level == SMB_FIND_EA_LIST) {
3302 if (total_data < 4) {
3303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3307 ea_size = IVAL(pdata,0);
3308 if (ea_size != total_data) {
3309 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3310 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3315 if (!lp_ea_support(SNUM(conn))) {
3316 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3320 /* Pull out the list of names. */
3321 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3328 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3333 *ppdata = (char *)SMB_REALLOC(
3334 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3335 if(*ppdata == NULL) {
3336 reply_nterror(req, NT_STATUS_NO_MEMORY);
3341 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3344 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3347 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3348 /* Realloc the params space */
3349 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3350 if(*pparams == NULL ) {
3351 reply_nterror(req, NT_STATUS_NO_MEMORY);
3357 /* Check that the dptr is valid */
3358 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3360 reply_nterror(req, STATUS_NO_MORE_FILES);
3364 directory = dptr_path(sconn, dptr_num);
3366 /* Get the wildcard mask from the dptr */
3367 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3368 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3369 reply_nterror(req, STATUS_NO_MORE_FILES);
3373 /* Get the attr mask from the dptr */
3374 dirtype = dptr_attr(sconn, dptr_num);
3376 backup_priv = dptr_get_priv(fsp->dptr);
3378 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3379 "backup_priv = %d\n",
3380 dptr_num, mask, dirtype,
3382 dptr_TellDir(fsp->dptr),
3385 /* We don't need to check for VOL here as this is returned by
3386 a different TRANS2 call. */
3388 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3389 directory,lp_dont_descend(ctx, SNUM(conn))));
3390 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3391 dont_descend = True;
3394 space_remaining = max_data_bytes;
3395 out_of_space = False;
3403 * Seek to the correct position. We no longer use the resume key but
3404 * depend on the last file name instead.
3407 if(!continue_bit && resume_name && *resume_name) {
3410 long current_pos = 0;
3412 * Remember, name_to_8_3 is called by
3413 * get_lanman2_dir_entry(), so the resume name
3414 * could be mangled. Ensure we check the unmangled name.
3417 if (mangle_is_mangled(resume_name, conn->params)) {
3418 char *new_resume_name = NULL;
3419 mangle_lookup_name_from_8_3(ctx,
3423 if (new_resume_name) {
3424 resume_name = new_resume_name;
3429 * Fix for NT redirector problem triggered by resume key indexes
3430 * changing between directory scans. We now return a resume key of 0
3431 * and instead look for the filename to continue from (also given
3432 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3433 * findfirst/findnext (as is usual) then the directory pointer
3434 * should already be at the correct place.
3437 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3438 } /* end if resume_name && !continue_bit */
3440 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3441 bool got_exact_match = False;
3443 /* this is a heuristic to avoid seeking the fsp->dptr except when
3444 absolutely necessary. It allows for a filename of about 40 chars */
3445 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3446 out_of_space = True;
3449 ntstatus = get_lanman2_dir_entry(ctx,
3453 mask,dirtype,info_level,
3454 requires_resume_key,dont_descend,
3459 &last_entry_off, ea_list);
3460 if (NT_STATUS_EQUAL(ntstatus,
3461 NT_STATUS_ILLEGAL_CHARACTER)) {
3463 * Bad character conversion on name. Ignore this
3468 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3469 out_of_space = true;
3471 finished = !NT_STATUS_IS_OK(ntstatus);
3475 if (!finished && !out_of_space)
3479 * As an optimisation if we know we aren't looking
3480 * for a wildcard name (ie. the name matches the wildcard exactly)
3481 * then we can finish on any (first) match.
3482 * This speeds up large directory searches. JRA.
3488 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3491 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3492 smb_fn_name(req->cmd),
3493 mask, directory, dirtype, numentries ) );
3495 /* Check if we can close the fsp->dptr */
3496 if(close_after_request || (finished && close_if_end)) {
3497 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3499 close_file(NULL, fsp, NORMAL_CLOSE);
3507 /* Set up the return parameter block */
3508 SSVAL(params,0,numentries);
3509 SSVAL(params,2,finished);
3510 SSVAL(params,4,0); /* Never an EA error */
3511 SSVAL(params,6,last_entry_off);
3513 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3519 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3521 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3525 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3527 SMB_ASSERT(extended_info != NULL);
3529 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3530 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3531 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3532 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3533 #ifdef SAMBA_VERSION_REVISION
3534 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3536 extended_info->samba_subversion = 0;
3537 #ifdef SAMBA_VERSION_RC_RELEASE
3538 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3540 #ifdef SAMBA_VERSION_PRE_RELEASE
3541 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3544 #ifdef SAMBA_VERSION_VENDOR_PATCH
3545 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3547 extended_info->samba_gitcommitdate = 0;
3548 #ifdef SAMBA_VERSION_COMMIT_TIME
3549 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3552 memset(extended_info->samba_version_string, 0,
3553 sizeof(extended_info->samba_version_string));
3555 snprintf (extended_info->samba_version_string,
3556 sizeof(extended_info->samba_version_string),
3557 "%s", samba_version_string());
3560 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3561 connection_struct *conn,
3562 TALLOC_CTX *mem_ctx,
3563 uint16_t info_level,
3565 unsigned int max_data_bytes,
3566 size_t *fixed_portion,
3567 struct smb_filename *fname,
3571 char *pdata, *end_data;
3574 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3575 int snum = SNUM(conn);
3576 const char *fstype = lp_fstype(SNUM(conn));
3577 const char *filename = NULL;
3578 const uint64_t bytes_per_sector = 512;
3579 uint32_t additional_flags = 0;
3580 struct smb_filename smb_fname;
3582 NTSTATUS status = NT_STATUS_OK;
3585 if (fname == NULL || fname->base_name == NULL) {
3588 filename = fname->base_name;
3592 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3593 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3594 "info level (0x%x) on IPC$.\n",
3595 (unsigned int)info_level));
3596 return NT_STATUS_ACCESS_DENIED;
3600 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3602 ZERO_STRUCT(smb_fname);
3603 smb_fname.base_name = discard_const_p(char, filename);
3605 if(info_level != SMB_FS_QUOTA_INFORMATION
3606 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3607 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3608 return map_nt_error_from_unix(errno);
3613 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3614 return NT_STATUS_INVALID_PARAMETER;
3617 *ppdata = (char *)SMB_REALLOC(
3618 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3619 if (*ppdata == NULL) {
3620 return NT_STATUS_NO_MEMORY;
3624 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3625 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3629 switch (info_level) {
3630 case SMB_INFO_ALLOCATION:
3632 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3634 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3636 if (df_ret == (uint64_t)-1) {
3637 return map_nt_error_from_unix(errno);
3640 block_size = lp_block_size(snum);
3641 if (bsize < block_size) {
3642 uint64_t factor = block_size/bsize;
3647 if (bsize > block_size) {
3648 uint64_t factor = bsize/block_size;
3653 sectors_per_unit = bsize/bytes_per_sector;
3655 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3656 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3657 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3660 * For large drives, return max values and not modulo.
3662 dsize = MIN(dsize, UINT32_MAX);
3663 dfree = MIN(dfree, UINT32_MAX);
3665 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3666 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3667 SIVAL(pdata,l1_cUnit,dsize);
3668 SIVAL(pdata,l1_cUnitAvail,dfree);
3669 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3673 case SMB_INFO_VOLUME:
3674 /* Return volume name */
3676 * Add volume serial number - hash of a combination of
3677 * the called hostname and the service name.
3679 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3681 * Win2k3 and previous mess this up by sending a name length
3682 * one byte short. I believe only older clients (OS/2 Win9x) use
3683 * this call so try fixing this by adding a terminating null to
3684 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3686 status = srvstr_push(
3688 pdata+l2_vol_szVolLabel, vname,
3689 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3690 STR_NOALIGN|STR_TERMINATE, &len);
3691 if (!NT_STATUS_IS_OK(status)) {
3694 SCVAL(pdata,l2_vol_cch,len);
3695 data_len = l2_vol_szVolLabel + len;
3696 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3697 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3698 (unsigned)len, vname));
3701 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3702 case SMB_FS_ATTRIBUTE_INFORMATION:
3704 additional_flags = 0;
3705 #if defined(HAVE_SYS_QUOTAS)
3706 additional_flags |= FILE_VOLUME_QUOTAS;
3709 if(lp_nt_acl_support(SNUM(conn))) {
3710 additional_flags |= FILE_PERSISTENT_ACLS;
3713 /* Capabilities are filled in at connection time through STATVFS call */
3714 additional_flags |= conn->fs_capabilities;
3715 additional_flags |= lp_parm_int(conn->params->service,
3716 "share", "fake_fscaps",
3719 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3720 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3721 additional_flags); /* FS ATTRIBUTES */
3723 SIVAL(pdata,4,255); /* Max filename component length */
3724 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3725 and will think we can't do long filenames */
3726 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3727 PTR_DIFF(end_data, pdata+12),
3729 if (!NT_STATUS_IS_OK(status)) {
3733 data_len = 12 + len;
3734 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3735 /* the client only requested a portion of the
3737 data_len = max_data_bytes;
3738 status = STATUS_BUFFER_OVERFLOW;
3740 *fixed_portion = 16;
3743 case SMB_QUERY_FS_LABEL_INFO:
3744 case SMB_FS_LABEL_INFORMATION:
3745 status = srvstr_push(pdata, flags2, pdata+4, vname,
3746 PTR_DIFF(end_data, pdata+4), 0, &len);
3747 if (!NT_STATUS_IS_OK(status)) {
3754 case SMB_QUERY_FS_VOLUME_INFO:
3755 case SMB_FS_VOLUME_INFORMATION:
3758 * Add volume serial number - hash of a combination of
3759 * the called hostname and the service name.
3761 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3762 (str_checksum(get_local_machine_name())<<16));
3764 /* Max label len is 32 characters. */
3765 status = srvstr_push(pdata, flags2, pdata+18, vname,
3766 PTR_DIFF(end_data, pdata+18),
3768 if (!NT_STATUS_IS_OK(status)) {
3771 SIVAL(pdata,12,len);
3774 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3775 (int)strlen(vname),vname,
3776 lp_servicename(talloc_tos(), snum)));
3777 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3778 /* the client only requested a portion of the
3780 data_len = max_data_bytes;
3781 status = STATUS_BUFFER_OVERFLOW;
3783 *fixed_portion = 24;
3786 case SMB_QUERY_FS_SIZE_INFO:
3787 case SMB_FS_SIZE_INFORMATION:
3789 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3791 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3793 if (df_ret == (uint64_t)-1) {
3794 return map_nt_error_from_unix(errno);
3796 block_size = lp_block_size(snum);
3797 if (bsize < block_size) {
3798 uint64_t factor = block_size/bsize;
3803 if (bsize > block_size) {
3804 uint64_t factor = bsize/block_size;
3809 sectors_per_unit = bsize/bytes_per_sector;
3810 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3811 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3812 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3813 SBIG_UINT(pdata,0,dsize);
3814 SBIG_UINT(pdata,8,dfree);
3815 SIVAL(pdata,16,sectors_per_unit);
3816 SIVAL(pdata,20,bytes_per_sector);
3817 *fixed_portion = 24;
3821 case SMB_FS_FULL_SIZE_INFORMATION:
3823 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3825 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3827 if (df_ret == (uint64_t)-1) {
3828 return map_nt_error_from_unix(errno);
3830 block_size = lp_block_size(snum);
3831 if (bsize < block_size) {
3832 uint64_t factor = block_size/bsize;
3837 if (bsize > block_size) {
3838 uint64_t factor = bsize/block_size;
3843 sectors_per_unit = bsize/bytes_per_sector;
3844 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3845 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3846 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3847 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3848 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3849 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3850 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3851 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3852 *fixed_portion = 32;
3856 case SMB_QUERY_FS_DEVICE_INFO:
3857 case SMB_FS_DEVICE_INFORMATION:
3859 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3861 if (!CAN_WRITE(conn)) {
3862 characteristics |= FILE_READ_ONLY_DEVICE;
3865 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3866 SIVAL(pdata,4,characteristics);
3871 #ifdef HAVE_SYS_QUOTAS
3872 case SMB_FS_QUOTA_INFORMATION:
3874 * what we have to send --metze:
3876 * Unknown1: 24 NULL bytes
3877 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3878 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3879 * Quota Flags: 2 byte :
3880 * Unknown3: 6 NULL bytes
3884 * details for Quota Flags:
3886 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3887 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3888 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3889 * 0x0001 Enable Quotas: enable quota for this fs
3893 /* we need to fake up a fsp here,
3894 * because its not send in this call
3897 SMB_NTQUOTA_STRUCT quotas;
3900 ZERO_STRUCT(quotas);
3903 fsp.fnum = FNUM_FIELD_INVALID;
3906 if (get_current_uid(conn) != 0) {
3907 DEBUG(0,("get_user_quota: access_denied "
3908 "service [%s] user [%s]\n",
3909 lp_servicename(talloc_tos(), SNUM(conn)),
3910 conn->session_info->unix_info->unix_name));
3911 return NT_STATUS_ACCESS_DENIED;
3914 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3916 if (!NT_STATUS_IS_OK(status)) {
3917 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3923 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3924 lp_servicename(talloc_tos(), SNUM(conn))));
3926 /* Unknown1 24 NULL bytes*/
3927 SBIG_UINT(pdata,0,(uint64_t)0);
3928 SBIG_UINT(pdata,8,(uint64_t)0);
3929 SBIG_UINT(pdata,16,(uint64_t)0);
3931 /* Default Soft Quota 8 bytes */
3932 SBIG_UINT(pdata,24,quotas.softlim);
3934 /* Default Hard Quota 8 bytes */
3935 SBIG_UINT(pdata,32,quotas.hardlim);
3937 /* Quota flag 2 bytes */
3938 SSVAL(pdata,40,quotas.qflags);
3940 /* Unknown3 6 NULL bytes */
3946 #endif /* HAVE_SYS_QUOTAS */
3947 case SMB_FS_OBJECTID_INFORMATION:
3949 unsigned char objid[16];
3950 struct smb_extended_info extended_info;
3951 memcpy(pdata,create_volume_objectid(conn, objid),16);
3952 samba_extended_info_version (&extended_info);
3953 SIVAL(pdata,16,extended_info.samba_magic);
3954 SIVAL(pdata,20,extended_info.samba_version);
3955 SIVAL(pdata,24,extended_info.samba_subversion);
3956 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3957 memcpy(pdata+36,extended_info.samba_version_string,28);
3962 case SMB_FS_SECTOR_SIZE_INFORMATION:
3966 * These values match a physical Windows Server 2012
3967 * share backed by NTFS atop spinning rust.
3969 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3970 /* logical_bytes_per_sector */
3971 SIVAL(pdata, 0, bytes_per_sector);
3972 /* phys_bytes_per_sector_atomic */
3973 SIVAL(pdata, 4, bytes_per_sector);
3974 /* phys_bytes_per_sector_perf */
3975 SIVAL(pdata, 8, bytes_per_sector);
3976 /* fs_effective_phys_bytes_per_sector_atomic */
3977 SIVAL(pdata, 12, bytes_per_sector);
3979 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3980 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3981 /* byte_off_sector_align */
3982 SIVAL(pdata, 20, 0);
3983 /* byte_off_partition_align */
3984 SIVAL(pdata, 24, 0);
3985 *fixed_portion = 28;
3991 * Query the version and capabilities of the CIFS UNIX extensions
3995 case SMB_QUERY_CIFS_UNIX_INFO:
3997 bool large_write = lp_min_receive_file_size() &&
3998 !srv_is_signing_active(xconn);
3999 bool large_read = !srv_is_signing_active(xconn);
4000 int encrypt_caps = 0;
4002 if (!lp_unix_extensions()) {
4003 return NT_STATUS_INVALID_LEVEL;
4006 switch (conn->encrypt_level) {
4007 case SMB_SIGNING_OFF:
4010 case SMB_SIGNING_DESIRED:
4011 case SMB_SIGNING_IF_REQUIRED:
4012 case SMB_SIGNING_DEFAULT:
4013 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4015 case SMB_SIGNING_REQUIRED:
4016 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4017 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4018 large_write = false;
4024 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4025 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4027 /* We have POSIX ACLs, pathname, encryption,
4028 * large read/write, and locking capability. */
4030 SBIG_UINT(pdata,4,((uint64_t)(
4031 CIFS_UNIX_POSIX_ACLS_CAP|
4032 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4033 CIFS_UNIX_FCNTL_LOCKS_CAP|
4034 CIFS_UNIX_EXTATTR_CAP|
4035 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4037 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4039 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4043 case SMB_QUERY_POSIX_FS_INFO:
4046 vfs_statvfs_struct svfs;
4048 if (!lp_unix_extensions()) {
4049 return NT_STATUS_INVALID_LEVEL;
4052 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4056 SIVAL(pdata,0,svfs.OptimalTransferSize);
4057 SIVAL(pdata,4,svfs.BlockSize);
4058 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4059 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4060 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4061 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4062 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4063 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4064 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4066 } else if (rc == EOPNOTSUPP) {
4067 return NT_STATUS_INVALID_LEVEL;
4068 #endif /* EOPNOTSUPP */
4070 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4071 return NT_STATUS_DOS(ERRSRV, ERRerror);
4076 case SMB_QUERY_POSIX_WHOAMI:
4082 if (!lp_unix_extensions()) {
4083 return NT_STATUS_INVALID_LEVEL;
4086 if (max_data_bytes < 40) {
4087 return NT_STATUS_BUFFER_TOO_SMALL;
4090 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4091 flags |= SMB_WHOAMI_GUEST;
4094 /* NOTE: 8 bytes for UID/GID, irrespective of native
4095 * platform size. This matches
4096 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4098 data_len = 4 /* flags */
4105 + 4 /* pad/reserved */
4106 + (conn->session_info->unix_token->ngroups * 8)
4108 + (conn->session_info->security_token->num_sids *
4112 SIVAL(pdata, 0, flags);
4113 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4115 (uint64_t)conn->session_info->unix_token->uid);
4116 SBIG_UINT(pdata, 16,
4117 (uint64_t)conn->session_info->unix_token->gid);
4120 if (data_len >= max_data_bytes) {
4121 /* Potential overflow, skip the GIDs and SIDs. */
4123 SIVAL(pdata, 24, 0); /* num_groups */
4124 SIVAL(pdata, 28, 0); /* num_sids */
4125 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4126 SIVAL(pdata, 36, 0); /* reserved */
4132 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4133 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4135 /* We walk the SID list twice, but this call is fairly
4136 * infrequent, and I don't expect that it's performance
4137 * sensitive -- jpeach
4139 for (i = 0, sid_bytes = 0;
4140 i < conn->session_info->security_token->num_sids; ++i) {
4141 sid_bytes += ndr_size_dom_sid(
4142 &conn->session_info->security_token->sids[i],
4146 /* SID list byte count */
4147 SIVAL(pdata, 32, sid_bytes);
4149 /* 4 bytes pad/reserved - must be zero */
4150 SIVAL(pdata, 36, 0);
4154 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4155 SBIG_UINT(pdata, data_len,
4156 (uint64_t)conn->session_info->unix_token->groups[i]);
4162 i < conn->session_info->security_token->num_sids; ++i) {
4163 int sid_len = ndr_size_dom_sid(
4164 &conn->session_info->security_token->sids[i],
4167 sid_linearize((uint8_t *)(pdata + data_len),
4169 &conn->session_info->security_token->sids[i]);
4170 data_len += sid_len;
4176 case SMB_MAC_QUERY_FS_INFO:
4178 * Thursby MAC extension... ONLY on NTFS filesystems
4179 * once we do streams then we don't need this
4181 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4183 SIVAL(pdata,84,0x100); /* Don't support mac... */
4189 return NT_STATUS_INVALID_LEVEL;
4192 *ret_data_len = data_len;
4196 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4197 struct smb_request *req,
4199 const DATA_BLOB *qdata)
4202 SMB_NTQUOTA_STRUCT quotas;
4204 ZERO_STRUCT(quotas);
4207 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4208 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4209 lp_servicename(talloc_tos(), SNUM(conn)),
4210 conn->session_info->unix_info->unix_name));
4211 return NT_STATUS_ACCESS_DENIED;
4214 if (!check_fsp_ntquota_handle(conn, req,
4216 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4217 return NT_STATUS_INVALID_HANDLE;
4220 /* note: normally there're 48 bytes,
4221 * but we didn't use the last 6 bytes for now
4224 if (qdata->length < 42) {
4225 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4226 (unsigned int)qdata->length));
4227 return NT_STATUS_INVALID_PARAMETER;
4230 /* unknown_1 24 NULL bytes in pdata*/
4232 /* the soft quotas 8 bytes (uint64_t)*/
4233 quotas.softlim = BVAL(qdata->data,24);
4235 /* the hard quotas 8 bytes (uint64_t)*/
4236 quotas.hardlim = BVAL(qdata->data,32);
4238 /* quota_flags 2 bytes **/
4239 quotas.qflags = SVAL(qdata->data,40);
4241 /* unknown_2 6 NULL bytes follow*/
4243 /* now set the quotas */
4244 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4245 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4246 lp_servicename(talloc_tos(), SNUM(conn))));
4247 status = map_nt_error_from_unix(errno);
4249 status = NT_STATUS_OK;
4254 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4255 struct smb_request *req,
4256 TALLOC_CTX *mem_ctx,
4257 uint16_t info_level,
4259 const DATA_BLOB *pdata)
4261 switch (info_level) {
4262 case SMB_FS_QUOTA_INFORMATION:
4264 return smb_set_fsquota(conn,
4273 return NT_STATUS_INVALID_LEVEL;
4276 /****************************************************************************
4277 Reply to a TRANS2_QFSINFO (query filesystem info).
4278 ****************************************************************************/
4280 static void call_trans2qfsinfo(connection_struct *conn,
4281 struct smb_request *req,
4282 char **pparams, int total_params,
4283 char **ppdata, int total_data,
4284 unsigned int max_data_bytes)
4286 char *params = *pparams;
4287 uint16_t info_level;
4289 size_t fixed_portion;
4292 if (total_params < 2) {
4293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4297 info_level = SVAL(params,0);
4299 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4300 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4301 DEBUG(0,("call_trans2qfsinfo: encryption required "
4302 "and info level 0x%x sent.\n",
4303 (unsigned int)info_level));
4304 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4309 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4311 status = smbd_do_qfsinfo(req->xconn, conn, req,
4318 if (!NT_STATUS_IS_OK(status)) {
4319 reply_nterror(req, status);
4323 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4326 DEBUG( 4, ( "%s info_level = %d\n",
4327 smb_fn_name(req->cmd), info_level) );
4332 /****************************************************************************
4333 Reply to a TRANS2_SETFSINFO (set filesystem info).
4334 ****************************************************************************/
4336 static void call_trans2setfsinfo(connection_struct *conn,
4337 struct smb_request *req,
4338 char **pparams, int total_params,
4339 char **ppdata, int total_data,
4340 unsigned int max_data_bytes)
4342 struct smbXsrv_connection *xconn = req->xconn;
4343 char *pdata = *ppdata;
4344 char *params = *pparams;
4345 uint16_t info_level;
4347 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4348 lp_servicename(talloc_tos(), SNUM(conn))));
4351 if (total_params < 4) {
4352 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4358 info_level = SVAL(params,2);
4361 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4362 info_level != SMB_SET_CIFS_UNIX_INFO) {
4363 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4364 "info level (0x%x) on IPC$.\n",
4365 (unsigned int)info_level));
4366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4371 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4372 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4373 DEBUG(0,("call_trans2setfsinfo: encryption required "
4374 "and info level 0x%x sent.\n",
4375 (unsigned int)info_level));
4376 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4381 switch(info_level) {
4382 case SMB_SET_CIFS_UNIX_INFO:
4383 if (!lp_unix_extensions()) {
4384 DEBUG(2,("call_trans2setfsinfo: "
4385 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4386 "unix extensions off\n"));
4388 NT_STATUS_INVALID_LEVEL);
4392 /* There should be 12 bytes of capabilities set. */
4393 if (total_data < 12) {
4396 NT_STATUS_INVALID_PARAMETER);
4399 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4400 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4401 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4402 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4403 /* Just print these values for now. */
4404 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4405 "major = %u, minor = %u cap_low = 0x%x, "
4407 (unsigned int)xconn->
4408 smb1.unix_info.client_major,
4409 (unsigned int)xconn->
4410 smb1.unix_info.client_minor,
4411 (unsigned int)xconn->
4412 smb1.unix_info.client_cap_low,
4413 (unsigned int)xconn->
4414 smb1.unix_info.client_cap_high));
4416 /* Here is where we must switch to posix pathname processing... */
4417 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4418 lp_set_posix_pathnames();
4419 mangle_change_to_posix();
4422 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4423 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4424 /* Client that knows how to do posix locks,
4425 * but not posix open/mkdir operations. Set a
4426 * default type for read/write checks. */
4428 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4433 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4436 size_t param_len = 0;
4437 size_t data_len = total_data;
4439 if (!lp_unix_extensions()) {
4442 NT_STATUS_INVALID_LEVEL);
4446 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4449 NT_STATUS_NOT_SUPPORTED);
4453 if (xconn->smb1.echo_handler.trusted_fde) {
4454 DEBUG( 2,("call_trans2setfsinfo: "
4455 "request transport encryption disabled"
4456 "with 'fork echo handler = yes'\n"));
4459 NT_STATUS_NOT_SUPPORTED);
4463 DEBUG( 4,("call_trans2setfsinfo: "
4464 "request transport encryption.\n"));
4466 status = srv_request_encryption_setup(conn,
4467 (unsigned char **)ppdata,
4469 (unsigned char **)pparams,
4472 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4473 !NT_STATUS_IS_OK(status)) {
4474 reply_nterror(req, status);
4478 send_trans2_replies(conn, req,
4486 if (NT_STATUS_IS_OK(status)) {
4487 /* Server-side transport
4488 * encryption is now *on*. */
4489 status = srv_encryption_start(conn);
4490 if (!NT_STATUS_IS_OK(status)) {
4491 char *reason = talloc_asprintf(talloc_tos(),
4492 "Failure in setting "
4493 "up encrypted transport: %s",
4495 exit_server_cleanly(reason);
4501 case SMB_FS_QUOTA_INFORMATION:
4505 .data = (uint8_t *)pdata,
4506 .length = total_data
4508 files_struct *fsp = NULL;
4509 fsp = file_fsp(req, SVAL(params,0));
4511 status = smb_set_fsquota(conn,
4515 if (!NT_STATUS_IS_OK(status)) {
4516 reply_nterror(req, status);
4522 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4524 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4530 * sending this reply works fine,
4531 * but I'm not sure it's the same
4532 * like windows do...
4535 reply_outbuf(req, 10, 0);
4538 #if defined(HAVE_POSIX_ACLS)
4539 /****************************************************************************
4540 Utility function to count the number of entries in a POSIX acl.
4541 ****************************************************************************/
4543 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4545 unsigned int ace_count = 0;
4546 int entry_id = SMB_ACL_FIRST_ENTRY;
4547 SMB_ACL_ENTRY_T entry;
4549 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4551 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4552 entry_id = SMB_ACL_NEXT_ENTRY;
4559 /****************************************************************************
4560 Utility function to marshall a POSIX acl into wire format.
4561 ****************************************************************************/
4563 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4565 int entry_id = SMB_ACL_FIRST_ENTRY;
4566 SMB_ACL_ENTRY_T entry;
4568 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4569 SMB_ACL_TAG_T tagtype;
4570 SMB_ACL_PERMSET_T permset;
4571 unsigned char perms = 0;
4572 unsigned int own_grp;
4575 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4576 entry_id = SMB_ACL_NEXT_ENTRY;
4579 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4580 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4584 if (sys_acl_get_permset(entry, &permset) == -1) {
4585 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4589 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4590 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4591 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4593 SCVAL(pdata,1,perms);
4596 case SMB_ACL_USER_OBJ:
4597 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4598 own_grp = (unsigned int)pst->st_ex_uid;
4599 SIVAL(pdata,2,own_grp);
4604 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4606 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4609 own_grp = (unsigned int)*puid;
4610 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4611 SIVAL(pdata,2,own_grp);
4615 case SMB_ACL_GROUP_OBJ:
4616 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4617 own_grp = (unsigned int)pst->st_ex_gid;
4618 SIVAL(pdata,2,own_grp);
4623 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4625 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4628 own_grp = (unsigned int)*pgid;
4629 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4630 SIVAL(pdata,2,own_grp);
4635 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4636 SIVAL(pdata,2,0xFFFFFFFF);
4637 SIVAL(pdata,6,0xFFFFFFFF);
4640 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4641 SIVAL(pdata,2,0xFFFFFFFF);
4642 SIVAL(pdata,6,0xFFFFFFFF);
4645 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4648 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4655 /****************************************************************************
4656 Store the FILE_UNIX_BASIC info.
4657 ****************************************************************************/
4659 static char *store_file_unix_basic(connection_struct *conn,
4662 const SMB_STRUCT_STAT *psbuf)
4666 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4667 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4669 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4672 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4675 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4676 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4677 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4680 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4684 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4688 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4691 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4692 devno = psbuf->st_ex_rdev;
4694 devno = psbuf->st_ex_dev;
4697 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4701 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4705 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4708 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4712 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4719 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4720 * the chflags(2) (or equivalent) flags.
4722 * XXX: this really should be behind the VFS interface. To do this, we would
4723 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4724 * Each VFS module could then implement its own mapping as appropriate for the
4725 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4727 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4731 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4735 { UF_IMMUTABLE, EXT_IMMUTABLE },
4739 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4743 { UF_HIDDEN, EXT_HIDDEN },
4746 /* Do not remove. We need to guarantee that this array has at least one
4747 * entry to build on HP-UX.
4753 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4754 uint32_t *smb_fflags, uint32_t *smb_fmask)
4758 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4759 *smb_fmask |= info2_flags_map[i].smb_fflag;
4760 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4761 *smb_fflags |= info2_flags_map[i].smb_fflag;
4766 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4767 const uint32_t smb_fflags,
4768 const uint32_t smb_fmask,
4771 uint32_t max_fmask = 0;
4774 *stat_fflags = psbuf->st_ex_flags;
4776 /* For each flags requested in smb_fmask, check the state of the
4777 * corresponding flag in smb_fflags and set or clear the matching
4781 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4782 max_fmask |= info2_flags_map[i].smb_fflag;
4783 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4784 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4785 *stat_fflags |= info2_flags_map[i].stat_fflag;
4787 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4792 /* If smb_fmask is asking to set any bits that are not supported by
4793 * our flag mappings, we should fail.
4795 if ((smb_fmask & max_fmask) != smb_fmask) {
4803 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4804 * of file flags and birth (create) time.
4806 static char *store_file_unix_basic_info2(connection_struct *conn,
4809 const SMB_STRUCT_STAT *psbuf)
4811 uint32_t file_flags = 0;
4812 uint32_t flags_mask = 0;
4814 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4816 /* Create (birth) time 64 bit */
4817 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4820 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4821 SIVAL(pdata, 0, file_flags); /* flags */
4822 SIVAL(pdata, 4, flags_mask); /* mask */
4828 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4829 const struct stream_struct *streams,
4831 unsigned int max_data_bytes,
4832 unsigned int *data_size)
4835 unsigned int ofs = 0;
4837 if (max_data_bytes < 32) {
4838 return NT_STATUS_INFO_LENGTH_MISMATCH;
4841 for (i = 0; i < num_streams; i++) {
4842 unsigned int next_offset;
4844 smb_ucs2_t *namebuf;
4846 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4847 streams[i].name, &namelen) ||
4850 return NT_STATUS_INVALID_PARAMETER;
4854 * name_buf is now null-terminated, we need to marshall as not
4861 * We cannot overflow ...
4863 if ((ofs + 24 + namelen) > max_data_bytes) {
4864 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4866 TALLOC_FREE(namebuf);
4867 return STATUS_BUFFER_OVERFLOW;
4870 SIVAL(data, ofs+4, namelen);
4871 SOFF_T(data, ofs+8, streams[i].size);
4872 SOFF_T(data, ofs+16, streams[i].alloc_size);
4873 memcpy(data+ofs+24, namebuf, namelen);
4874 TALLOC_FREE(namebuf);
4876 next_offset = ofs + 24 + namelen;
4878 if (i == num_streams-1) {
4879 SIVAL(data, ofs, 0);
4882 unsigned int align = ndr_align_size(next_offset, 8);
4884 if ((next_offset + align) > max_data_bytes) {
4885 DEBUG(10, ("refusing to overflow align "
4886 "reply at stream %u\n",
4888 TALLOC_FREE(namebuf);
4889 return STATUS_BUFFER_OVERFLOW;
4892 memset(data+next_offset, 0, align);
4893 next_offset += align;
4895 SIVAL(data, ofs, next_offset - ofs);
4902 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4906 return NT_STATUS_OK;
4909 #if defined(HAVE_POSIX_ACLS)
4910 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4911 struct smb_request *req,
4913 struct smb_filename *smb_fname,
4915 unsigned int data_size_in,
4916 unsigned int *pdata_size_out)
4918 SMB_ACL_T file_acl = NULL;
4919 SMB_ACL_T def_acl = NULL;
4920 uint16_t num_file_acls = 0;
4921 uint16_t num_def_acls = 0;
4922 unsigned int size_needed = 0;
4925 bool close_fsp = false;
4928 * Ensure we always operate on a file descriptor, not just
4932 uint32_t access_mask = SEC_STD_READ_CONTROL|
4933 FILE_READ_ATTRIBUTES|
4934 FILE_WRITE_ATTRIBUTES;
4936 status = get_posix_fsp(conn,
4942 if (!NT_STATUS_IS_OK(status)) {
4948 SMB_ASSERT(fsp != NULL);
4950 status = refuse_symlink(conn,
4953 if (!NT_STATUS_IS_OK(status)) {
4957 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4960 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4961 DBG_INFO("ACLs not implemented on "
4962 "filesystem containing %s\n",
4964 status = NT_STATUS_NOT_IMPLEMENTED;
4968 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4970 * We can only have default POSIX ACLs on
4973 if (!fsp->is_directory) {
4974 DBG_INFO("Non-directory open %s\n",
4976 status = NT_STATUS_INVALID_HANDLE;
4979 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4981 SMB_ACL_TYPE_DEFAULT,
4983 def_acl = free_empty_sys_acl(conn, def_acl);
4986 num_file_acls = count_acl_entries(conn, file_acl);
4987 num_def_acls = count_acl_entries(conn, def_acl);
4990 if (num_file_acls + num_def_acls < num_file_acls) {
4991 status = NT_STATUS_INVALID_PARAMETER;
4995 size_needed = num_file_acls + num_def_acls;
4998 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4999 * than UINT_MAX, so check by division.
5001 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5002 status = NT_STATUS_INVALID_PARAMETER;
5006 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5007 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5008 status = NT_STATUS_INVALID_PARAMETER;
5011 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5013 if ( data_size_in < size_needed) {
5014 DBG_INFO("data_size too small (%u) need %u\n",
5017 status = NT_STATUS_BUFFER_TOO_SMALL;
5021 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5022 SSVAL(pdata,2,num_file_acls);
5023 SSVAL(pdata,4,num_def_acls);
5024 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5026 ok = marshall_posix_acl(conn,
5031 status = NT_STATUS_INTERNAL_ERROR;
5034 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5036 ok = marshall_posix_acl(conn,
5041 status = NT_STATUS_INTERNAL_ERROR;
5045 *pdata_size_out = size_needed;
5046 status = NT_STATUS_OK;
5052 * Ensure the stat struct in smb_fname is up to
5053 * date. Structure copy.
5055 smb_fname->st = fsp->fsp_name->st;
5056 (void)close_file(req, fsp, NORMAL_CLOSE);
5060 TALLOC_FREE(file_acl);
5061 TALLOC_FREE(def_acl);
5066 /****************************************************************************
5067 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5068 ****************************************************************************/
5070 static void call_trans2qpipeinfo(connection_struct *conn,
5071 struct smb_request *req,
5072 unsigned int tran_call,
5073 char **pparams, int total_params,
5074 char **ppdata, int total_data,
5075 unsigned int max_data_bytes)
5077 char *params = *pparams;
5078 char *pdata = *ppdata;
5079 unsigned int data_size = 0;
5080 unsigned int param_size = 2;
5081 uint16_t info_level;
5085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 if (total_params < 4) {
5090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5094 fsp = file_fsp(req, SVAL(params,0));
5095 if (!fsp_is_np(fsp)) {
5096 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5100 info_level = SVAL(params,2);
5102 *pparams = (char *)SMB_REALLOC(*pparams,2);
5103 if (*pparams == NULL) {
5104 reply_nterror(req, NT_STATUS_NO_MEMORY);
5109 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5113 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5114 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5115 if (*ppdata == NULL ) {
5116 reply_nterror(req, NT_STATUS_NO_MEMORY);
5121 switch (info_level) {
5122 case SMB_FILE_STANDARD_INFORMATION:
5124 SOFF_T(pdata,0,4096LL);
5131 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5135 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5141 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5142 TALLOC_CTX *mem_ctx,
5143 struct smb_request *req,
5144 uint16_t info_level,
5146 struct smb_filename *smb_fname,
5147 bool delete_pending,
5148 struct timespec write_time_ts,
5149 struct ea_list *ea_list,
5150 int lock_data_count,
5153 unsigned int max_data_bytes,
5154 size_t *fixed_portion,
5156 unsigned int *pdata_size)
5158 char *pdata = *ppdata;
5159 char *dstart, *dend;
5160 unsigned int data_size;
5161 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5162 time_t create_time, mtime, atime, c_time;
5163 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5170 uint64_t file_size = 0;
5172 uint64_t allocation_size = 0;
5173 uint64_t file_id = 0;
5174 uint32_t access_mask = 0;
5177 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5178 return NT_STATUS_INVALID_LEVEL;
5181 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5182 smb_fname_str_dbg(smb_fname),
5184 info_level, max_data_bytes));
5186 mode = dos_mode(conn, smb_fname);
5187 nlink = psbuf->st_ex_nlink;
5189 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5193 if ((nlink > 0) && delete_pending) {
5197 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5198 return NT_STATUS_INVALID_PARAMETER;
5201 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5202 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5203 if (*ppdata == NULL) {
5204 return NT_STATUS_NO_MEMORY;
5208 dend = dstart + data_size - 1;
5210 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5211 update_stat_ex_mtime(psbuf, write_time_ts);
5214 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5215 mtime_ts = psbuf->st_ex_mtime;
5216 atime_ts = psbuf->st_ex_atime;
5217 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5219 if (lp_dos_filetime_resolution(SNUM(conn))) {
5220 dos_filetime_timespec(&create_time_ts);
5221 dos_filetime_timespec(&mtime_ts);
5222 dos_filetime_timespec(&atime_ts);
5223 dos_filetime_timespec(&ctime_ts);
5226 create_time = convert_timespec_to_time_t(create_time_ts);
5227 mtime = convert_timespec_to_time_t(mtime_ts);
5228 atime = convert_timespec_to_time_t(atime_ts);
5229 c_time = convert_timespec_to_time_t(ctime_ts);
5231 p = strrchr_m(smb_fname->base_name,'/');
5233 base_name = smb_fname->base_name;
5237 /* NT expects the name to be in an exact form of the *full*
5238 filename. See the trans2 torture test */
5239 if (ISDOT(base_name)) {
5240 dos_fname = talloc_strdup(mem_ctx, "\\");
5242 return NT_STATUS_NO_MEMORY;
5245 dos_fname = talloc_asprintf(mem_ctx,
5247 smb_fname->base_name);
5249 return NT_STATUS_NO_MEMORY;
5251 if (is_ntfs_stream_smb_fname(smb_fname)) {
5252 dos_fname = talloc_asprintf(dos_fname, "%s",
5253 smb_fname->stream_name);
5255 return NT_STATUS_NO_MEMORY;
5259 string_replace(dos_fname, '/', '\\');
5262 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5265 /* Do we have this path open ? */
5267 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5268 fsp1 = file_find_di_first(conn->sconn, fileid);
5269 if (fsp1 && fsp1->initial_allocation_size) {
5270 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5274 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5275 file_size = get_file_size_stat(psbuf);
5279 pos = fsp->fh->position_information;
5283 access_mask = fsp->access_mask;
5285 /* GENERIC_EXECUTE mapping from Windows */
5286 access_mask = 0x12019F;
5289 /* This should be an index number - looks like
5292 I think this causes us to fail the IFSKIT
5293 BasicFileInformationTest. -tpot */
5294 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5298 switch (info_level) {
5299 case SMB_INFO_STANDARD:
5300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5302 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5303 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5304 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5305 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5306 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5307 SSVAL(pdata,l1_attrFile,mode);
5310 case SMB_INFO_QUERY_EA_SIZE:
5312 unsigned int ea_size =
5313 estimate_ea_size(conn, fsp,
5315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5317 srv_put_dos_date2(pdata,0,create_time);
5318 srv_put_dos_date2(pdata,4,atime);
5319 srv_put_dos_date2(pdata,8,mtime); /* write time */
5320 SIVAL(pdata,12,(uint32_t)file_size);
5321 SIVAL(pdata,16,(uint32_t)allocation_size);
5322 SSVAL(pdata,20,mode);
5323 SIVAL(pdata,22,ea_size);
5327 case SMB_INFO_IS_NAME_VALID:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5330 /* os/2 needs this ? really ?*/
5331 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5333 /* This is only reached for qpathinfo */
5337 case SMB_INFO_QUERY_EAS_FROM_LIST:
5339 size_t total_ea_len = 0;
5340 struct ea_list *ea_file_list = NULL;
5341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5344 get_ea_list_from_file(mem_ctx, conn, fsp,
5346 &total_ea_len, &ea_file_list);
5347 if (!NT_STATUS_IS_OK(status)) {
5351 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5353 if (!ea_list || (total_ea_len > data_size)) {
5355 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5359 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5363 case SMB_INFO_QUERY_ALL_EAS:
5365 /* We have data_size bytes to put EA's into. */
5366 size_t total_ea_len = 0;
5367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5369 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5371 &total_ea_len, &ea_list);
5372 if (!NT_STATUS_IS_OK(status)) {
5376 if (!ea_list || (total_ea_len > data_size)) {
5378 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5382 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5386 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5388 /* This is FileFullEaInformation - 0xF which maps to
5389 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5391 /* We have data_size bytes to put EA's into. */
5392 size_t total_ea_len = 0;
5393 struct ea_list *ea_file_list = NULL;
5395 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5397 /*TODO: add filtering and index handling */
5400 get_ea_list_from_file(mem_ctx, conn, fsp,
5402 &total_ea_len, &ea_file_list);
5403 if (!NT_STATUS_IS_OK(status)) {
5406 if (!ea_file_list) {
5407 return NT_STATUS_NO_EAS_ON_FILE;
5410 status = fill_ea_chained_buffer(mem_ctx,
5414 conn, ea_file_list);
5415 if (!NT_STATUS_IS_OK(status)) {
5421 case SMB_FILE_BASIC_INFORMATION:
5422 case SMB_QUERY_FILE_BASIC_INFO:
5424 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5426 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5432 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5433 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5434 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5435 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5436 SIVAL(pdata,32,mode);
5438 DEBUG(5,("SMB_QFBI - "));
5439 DEBUG(5,("create: %s ", ctime(&create_time)));
5440 DEBUG(5,("access: %s ", ctime(&atime)));
5441 DEBUG(5,("write: %s ", ctime(&mtime)));
5442 DEBUG(5,("change: %s ", ctime(&c_time)));
5443 DEBUG(5,("mode: %x\n", mode));
5444 *fixed_portion = data_size;
5447 case SMB_FILE_STANDARD_INFORMATION:
5448 case SMB_QUERY_FILE_STANDARD_INFO:
5450 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5452 SOFF_T(pdata,0,allocation_size);
5453 SOFF_T(pdata,8,file_size);
5454 SIVAL(pdata,16,nlink);
5455 SCVAL(pdata,20,delete_pending?1:0);
5456 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5457 SSVAL(pdata,22,0); /* Padding. */
5458 *fixed_portion = 24;
5461 case SMB_FILE_EA_INFORMATION:
5462 case SMB_QUERY_FILE_EA_INFO:
5464 unsigned int ea_size =
5465 estimate_ea_size(conn, fsp, smb_fname);
5466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5469 SIVAL(pdata,0,ea_size);
5473 /* Get the 8.3 name - used if NT SMB was negotiated. */
5474 case SMB_QUERY_FILE_ALT_NAME_INFO:
5475 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5477 char mangled_name[13];
5478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5479 if (!name_to_8_3(base_name,mangled_name,
5480 True,conn->params)) {
5481 return NT_STATUS_NO_MEMORY;
5483 status = srvstr_push(dstart, flags2,
5484 pdata+4, mangled_name,
5485 PTR_DIFF(dend, pdata+4),
5487 if (!NT_STATUS_IS_OK(status)) {
5490 data_size = 4 + len;
5496 case SMB_QUERY_FILE_NAME_INFO:
5499 this must be *exactly* right for ACLs on mapped drives to work
5501 status = srvstr_push(dstart, flags2,
5503 PTR_DIFF(dend, pdata+4),
5505 if (!NT_STATUS_IS_OK(status)) {
5508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5509 data_size = 4 + len;
5514 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5516 char *nfname = NULL;
5518 if (!fsp->conn->sconn->using_smb2) {
5519 return NT_STATUS_INVALID_LEVEL;
5522 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5523 if (nfname == NULL) {
5524 return NT_STATUS_NO_MEMORY;
5527 if (ISDOT(nfname)) {
5530 string_replace(nfname, '/', '\\');
5532 if (smb_fname->stream_name != NULL) {
5533 const char *s = smb_fname->stream_name;
5534 const char *e = NULL;
5537 SMB_ASSERT(s[0] != '\0');
5540 * smb_fname->stream_name is in form
5541 * of ':StrEam:$DATA', but we should only
5542 * append ':StrEam' here.
5545 e = strchr(&s[1], ':');
5551 nfname = talloc_strndup_append(nfname, s, n);
5552 if (nfname == NULL) {
5553 return NT_STATUS_NO_MEMORY;
5557 status = srvstr_push(dstart, flags2,
5559 PTR_DIFF(dend, pdata+4),
5561 if (!NT_STATUS_IS_OK(status)) {
5564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5565 data_size = 4 + len;
5571 case SMB_FILE_ALLOCATION_INFORMATION:
5572 case SMB_QUERY_FILE_ALLOCATION_INFO:
5573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5575 SOFF_T(pdata,0,allocation_size);
5578 case SMB_FILE_END_OF_FILE_INFORMATION:
5579 case SMB_QUERY_FILE_END_OF_FILEINFO:
5580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5582 SOFF_T(pdata,0,file_size);
5585 case SMB_QUERY_FILE_ALL_INFO:
5586 case SMB_FILE_ALL_INFORMATION:
5588 unsigned int ea_size =
5589 estimate_ea_size(conn, fsp, smb_fname);
5590 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5591 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5592 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5593 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5594 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5595 SIVAL(pdata,32,mode);
5596 SIVAL(pdata,36,0); /* padding. */
5598 SOFF_T(pdata,0,allocation_size);
5599 SOFF_T(pdata,8,file_size);
5600 SIVAL(pdata,16,nlink);
5601 SCVAL(pdata,20,delete_pending);
5602 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5605 SIVAL(pdata,0,ea_size);
5606 pdata += 4; /* EA info */
5607 status = srvstr_push(dstart, flags2,
5609 PTR_DIFF(dend, pdata+4),
5611 if (!NT_STATUS_IS_OK(status)) {
5616 data_size = PTR_DIFF(pdata,(*ppdata));
5617 *fixed_portion = 10;
5621 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5623 unsigned int ea_size =
5624 estimate_ea_size(conn, fsp, smb_fname);
5625 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5626 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5627 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5628 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5629 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5630 SIVAL(pdata, 0x20, mode);
5631 SIVAL(pdata, 0x24, 0); /* padding. */
5632 SBVAL(pdata, 0x28, allocation_size);
5633 SBVAL(pdata, 0x30, file_size);
5634 SIVAL(pdata, 0x38, nlink);
5635 SCVAL(pdata, 0x3C, delete_pending);
5636 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5637 SSVAL(pdata, 0x3E, 0); /* padding */
5638 SBVAL(pdata, 0x40, file_id);
5639 SIVAL(pdata, 0x48, ea_size);
5640 SIVAL(pdata, 0x4C, access_mask);
5641 SBVAL(pdata, 0x50, pos);
5642 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5643 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5647 status = srvstr_push(dstart, flags2,
5649 PTR_DIFF(dend, pdata+4),
5651 if (!NT_STATUS_IS_OK(status)) {
5656 data_size = PTR_DIFF(pdata,(*ppdata));
5657 *fixed_portion = 104;
5660 case SMB_FILE_INTERNAL_INFORMATION:
5662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5663 SBVAL(pdata, 0, file_id);
5668 case SMB_FILE_ACCESS_INFORMATION:
5669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5670 SIVAL(pdata, 0, access_mask);
5675 case SMB_FILE_NAME_INFORMATION:
5676 /* Pathname with leading '\'. */
5679 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5681 SIVAL(pdata,0,byte_len);
5682 data_size = 4 + byte_len;
5686 case SMB_FILE_DISPOSITION_INFORMATION:
5687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5689 SCVAL(pdata,0,delete_pending);
5693 case SMB_FILE_POSITION_INFORMATION:
5694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5696 SOFF_T(pdata,0,pos);
5700 case SMB_FILE_MODE_INFORMATION:
5701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5702 SIVAL(pdata,0,mode);
5707 case SMB_FILE_ALIGNMENT_INFORMATION:
5708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5709 SIVAL(pdata,0,0); /* No alignment needed. */
5715 * NT4 server just returns "invalid query" to this - if we try
5716 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5719 /* The first statement above is false - verified using Thursby
5720 * client against NT4 -- gcolley.
5722 case SMB_QUERY_FILE_STREAM_INFO:
5723 case SMB_FILE_STREAM_INFORMATION: {
5724 unsigned int num_streams = 0;
5725 struct stream_struct *streams = NULL;
5727 DEBUG(10,("smbd_do_qfilepathinfo: "
5728 "SMB_FILE_STREAM_INFORMATION\n"));
5730 if (is_ntfs_stream_smb_fname(smb_fname)) {
5731 return NT_STATUS_INVALID_PARAMETER;
5734 status = vfs_streaminfo(conn,
5741 if (!NT_STATUS_IS_OK(status)) {
5742 DEBUG(10, ("could not get stream info: %s\n",
5743 nt_errstr(status)));
5747 status = marshall_stream_info(num_streams, streams,
5748 pdata, max_data_bytes,
5751 if (!NT_STATUS_IS_OK(status)) {
5752 DEBUG(10, ("marshall_stream_info failed: %s\n",
5753 nt_errstr(status)));
5754 TALLOC_FREE(streams);
5758 TALLOC_FREE(streams);
5760 *fixed_portion = 32;
5764 case SMB_QUERY_COMPRESSION_INFO:
5765 case SMB_FILE_COMPRESSION_INFORMATION:
5766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5767 SOFF_T(pdata,0,file_size);
5768 SIVAL(pdata,8,0); /* ??? */
5769 SIVAL(pdata,12,0); /* ??? */
5771 *fixed_portion = 16;
5774 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5775 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5776 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5777 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5778 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5779 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5780 SOFF_T(pdata,32,allocation_size);
5781 SOFF_T(pdata,40,file_size);
5782 SIVAL(pdata,48,mode);
5783 SIVAL(pdata,52,0); /* ??? */
5785 *fixed_portion = 56;
5788 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5790 SIVAL(pdata,0,mode);
5797 * CIFS UNIX Extensions.
5800 case SMB_QUERY_FILE_UNIX_BASIC:
5802 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5803 data_size = PTR_DIFF(pdata,(*ppdata));
5805 DEBUG(4,("smbd_do_qfilepathinfo: "
5806 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5807 dump_data(4, (uint8_t *)(*ppdata), data_size);
5811 case SMB_QUERY_FILE_UNIX_INFO2:
5813 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5814 data_size = PTR_DIFF(pdata,(*ppdata));
5818 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5820 for (i=0; i<100; i++)
5821 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5827 case SMB_QUERY_FILE_UNIX_LINK:
5830 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5833 return NT_STATUS_NO_MEMORY;
5836 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5838 if(!S_ISLNK(psbuf->st_ex_mode)) {
5839 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5842 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5844 link_len = SMB_VFS_READLINK(conn,
5847 if (link_len == -1) {
5848 return map_nt_error_from_unix(errno);
5850 buffer[link_len] = 0;
5851 status = srvstr_push(dstart, flags2,
5853 PTR_DIFF(dend, pdata),
5854 STR_TERMINATE, &len);
5855 if (!NT_STATUS_IS_OK(status)) {
5859 data_size = PTR_DIFF(pdata,(*ppdata));
5864 #if defined(HAVE_POSIX_ACLS)
5865 case SMB_QUERY_POSIX_ACL:
5867 status = smb_query_posix_acl(conn,
5874 if (!NT_STATUS_IS_OK(status)) {
5882 case SMB_QUERY_POSIX_LOCK:
5887 enum brl_type lock_type;
5889 /* We need an open file with a real fd for this. */
5890 if (!fsp || fsp->fh->fd == -1) {
5891 return NT_STATUS_INVALID_LEVEL;
5894 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5895 return NT_STATUS_INVALID_PARAMETER;
5898 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5899 case POSIX_LOCK_TYPE_READ:
5900 lock_type = READ_LOCK;
5902 case POSIX_LOCK_TYPE_WRITE:
5903 lock_type = WRITE_LOCK;
5905 case POSIX_LOCK_TYPE_UNLOCK:
5907 /* There's no point in asking for an unlock... */
5908 return NT_STATUS_INVALID_PARAMETER;
5911 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5912 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5913 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5915 status = query_lock(fsp,
5922 if (ERROR_WAS_LOCK_DENIED(status)) {
5923 /* Here we need to report who has it locked... */
5924 data_size = POSIX_LOCK_DATA_SIZE;
5926 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5927 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5928 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5929 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5930 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5932 } else if (NT_STATUS_IS_OK(status)) {
5933 /* For success we just return a copy of what we sent
5934 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5935 data_size = POSIX_LOCK_DATA_SIZE;
5936 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5945 return NT_STATUS_INVALID_LEVEL;
5948 *pdata_size = data_size;
5949 return NT_STATUS_OK;
5952 /****************************************************************************
5953 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5954 file name or file id).
5955 ****************************************************************************/
5957 static void call_trans2qfilepathinfo(connection_struct *conn,
5958 struct smb_request *req,
5959 unsigned int tran_call,
5960 char **pparams, int total_params,
5961 char **ppdata, int total_data,
5962 unsigned int max_data_bytes)
5964 char *params = *pparams;
5965 char *pdata = *ppdata;
5966 uint16_t info_level;
5967 unsigned int data_size = 0;
5968 unsigned int param_size = 2;
5969 struct smb_filename *smb_fname = NULL;
5970 bool delete_pending = False;
5971 struct timespec write_time_ts;
5972 files_struct *fsp = NULL;
5973 struct file_id fileid;
5974 struct ea_list *ea_list = NULL;
5975 int lock_data_count = 0;
5976 char *lock_data = NULL;
5977 size_t fixed_portion;
5978 NTSTATUS status = NT_STATUS_OK;
5981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5985 ZERO_STRUCT(write_time_ts);
5987 if (tran_call == TRANSACT2_QFILEINFO) {
5988 if (total_params < 4) {
5989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5994 call_trans2qpipeinfo(conn, req, tran_call,
5995 pparams, total_params,
6001 fsp = file_fsp(req, SVAL(params,0));
6002 info_level = SVAL(params,2);
6004 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6006 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6007 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6011 /* Initial check for valid fsp ptr. */
6012 if (!check_fsp_open(conn, req, fsp)) {
6016 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6017 if (smb_fname == NULL) {
6018 reply_nterror(req, NT_STATUS_NO_MEMORY);
6022 if(fsp->fake_file_handle) {
6024 * This is actually for the QUOTA_FAKE_FILE --metze
6027 /* We know this name is ok, it's already passed the checks. */
6029 } else if(fsp->fh->fd == -1) {
6031 * This is actually a QFILEINFO on a directory
6032 * handle (returned from an NT SMB). NT5.0 seems
6033 * to do this call. JRA.
6036 if (INFO_LEVEL_IS_UNIX(info_level)) {
6037 /* Always do lstat for UNIX calls. */
6038 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6039 DEBUG(3,("call_trans2qfilepathinfo: "
6040 "SMB_VFS_LSTAT of %s failed "
6042 smb_fname_str_dbg(smb_fname),
6045 map_nt_error_from_unix(errno));
6048 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6049 DEBUG(3,("call_trans2qfilepathinfo: "
6050 "SMB_VFS_STAT of %s failed (%s)\n",
6051 smb_fname_str_dbg(smb_fname),
6054 map_nt_error_from_unix(errno));
6058 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6059 fileid = vfs_file_id_from_sbuf(
6060 conn, &smb_fname->st);
6061 get_file_infos(fileid, fsp->name_hash,
6067 * Original code - this is an open file.
6069 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6070 DEBUG(3, ("fstat of %s failed (%s)\n",
6071 fsp_fnum_dbg(fsp), strerror(errno)));
6073 map_nt_error_from_unix(errno));
6076 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6077 fileid = vfs_file_id_from_sbuf(
6078 conn, &smb_fname->st);
6079 get_file_infos(fileid, fsp->name_hash,
6088 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6091 if (total_params < 7) {
6092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6096 info_level = SVAL(params,0);
6098 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6100 if (INFO_LEVEL_IS_UNIX(info_level)) {
6101 if (!lp_unix_extensions()) {
6102 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6105 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6106 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6107 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6108 req->posix_pathnames) {
6109 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6113 if (req->posix_pathnames) {
6114 srvstr_get_path_posix(req,
6123 srvstr_get_path(req,
6132 if (!NT_STATUS_IS_OK(status)) {
6133 reply_nterror(req, status);
6137 status = filename_convert(req,
6144 if (!NT_STATUS_IS_OK(status)) {
6145 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6146 reply_botherror(req,
6147 NT_STATUS_PATH_NOT_COVERED,
6148 ERRSRV, ERRbadpath);
6151 reply_nterror(req, status);
6155 /* If this is a stream, check if there is a delete_pending. */
6156 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6157 && is_ntfs_stream_smb_fname(smb_fname)) {
6158 struct smb_filename *smb_fname_base;
6160 /* Create an smb_filename with stream_name == NULL. */
6161 smb_fname_base = synthetic_smb_fname(
6163 smb_fname->base_name,
6167 if (smb_fname_base == NULL) {
6168 reply_nterror(req, NT_STATUS_NO_MEMORY);
6172 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6173 /* Always do lstat for UNIX calls. */
6174 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6175 DEBUG(3,("call_trans2qfilepathinfo: "
6176 "SMB_VFS_LSTAT of %s failed "
6178 smb_fname_str_dbg(smb_fname_base),
6180 TALLOC_FREE(smb_fname_base);
6182 map_nt_error_from_unix(errno));
6186 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6187 DEBUG(3,("call_trans2qfilepathinfo: "
6188 "fileinfo of %s failed "
6190 smb_fname_str_dbg(smb_fname_base),
6192 TALLOC_FREE(smb_fname_base);
6194 map_nt_error_from_unix(errno));
6199 status = file_name_hash(conn,
6200 smb_fname_str_dbg(smb_fname_base),
6202 if (!NT_STATUS_IS_OK(status)) {
6203 TALLOC_FREE(smb_fname_base);
6204 reply_nterror(req, status);
6208 fileid = vfs_file_id_from_sbuf(conn,
6209 &smb_fname_base->st);
6210 TALLOC_FREE(smb_fname_base);
6211 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6212 if (delete_pending) {
6213 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6218 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6219 /* Always do lstat for UNIX calls. */
6220 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6221 DEBUG(3,("call_trans2qfilepathinfo: "
6222 "SMB_VFS_LSTAT of %s failed (%s)\n",
6223 smb_fname_str_dbg(smb_fname),
6226 map_nt_error_from_unix(errno));
6231 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6232 DEBUG(3,("call_trans2qfilepathinfo: "
6233 "SMB_VFS_STAT of %s failed (%s)\n",
6234 smb_fname_str_dbg(smb_fname),
6237 map_nt_error_from_unix(errno));
6242 status = file_name_hash(conn,
6243 smb_fname_str_dbg(smb_fname),
6245 if (!NT_STATUS_IS_OK(status)) {
6246 reply_nterror(req, status);
6250 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6251 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6252 get_file_infos(fileid, name_hash, &delete_pending,
6256 if (delete_pending) {
6257 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6262 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6263 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6265 info_level,tran_call,total_data));
6267 /* Pull out any data sent here before we realloc. */
6268 switch (info_level) {
6269 case SMB_INFO_QUERY_EAS_FROM_LIST:
6271 /* Pull any EA list from the data portion. */
6274 if (total_data < 4) {
6276 req, NT_STATUS_INVALID_PARAMETER);
6279 ea_size = IVAL(pdata,0);
6281 if (total_data > 0 && ea_size != total_data) {
6282 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6283 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6285 req, NT_STATUS_INVALID_PARAMETER);
6289 if (!lp_ea_support(SNUM(conn))) {
6290 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6294 /* Pull out the list of names. */
6295 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6298 req, NT_STATUS_INVALID_PARAMETER);
6304 case SMB_QUERY_POSIX_LOCK:
6306 if (fsp == NULL || fsp->fh->fd == -1) {
6307 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6311 if (total_data != POSIX_LOCK_DATA_SIZE) {
6313 req, NT_STATUS_INVALID_PARAMETER);
6317 /* Copy the lock range data. */
6318 lock_data = (char *)talloc_memdup(
6319 req, pdata, total_data);
6321 reply_nterror(req, NT_STATUS_NO_MEMORY);
6324 lock_data_count = total_data;
6330 *pparams = (char *)SMB_REALLOC(*pparams,2);
6331 if (*pparams == NULL) {
6332 reply_nterror(req, NT_STATUS_NO_MEMORY);
6339 * draft-leach-cifs-v1-spec-02.txt
6340 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6343 * The requested information is placed in the Data portion of the
6344 * transaction response. For the information levels greater than 0x100,
6345 * the transaction response has 1 parameter word which should be
6346 * ignored by the client.
6348 * However Windows only follows this rule for the IS_NAME_VALID call.
6350 switch (info_level) {
6351 case SMB_INFO_IS_NAME_VALID:
6356 if ((info_level & 0xFF00) == 0xFF00) {
6358 * We use levels that start with 0xFF00
6359 * internally to represent SMB2 specific levels
6361 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6365 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6367 delete_pending, write_time_ts,
6369 lock_data_count, lock_data,
6370 req->flags2, max_data_bytes,
6372 ppdata, &data_size);
6373 if (!NT_STATUS_IS_OK(status)) {
6374 if (open_was_deferred(req->xconn, req->mid)) {
6375 /* We have re-scheduled this call. */
6378 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6379 bool ok = defer_smb1_sharing_violation(req);
6384 reply_nterror(req, status);
6387 if (fixed_portion > max_data_bytes) {
6388 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6392 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6398 /****************************************************************************
6399 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6401 ****************************************************************************/
6403 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6404 connection_struct *conn,
6405 struct smb_request *req,
6406 bool overwrite_if_exists,
6407 const struct smb_filename *smb_fname_old,
6408 struct smb_filename *smb_fname_new)
6410 NTSTATUS status = NT_STATUS_OK;
6414 /* source must already exist. */
6415 if (!VALID_STAT(smb_fname_old->st)) {
6416 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6419 if (VALID_STAT(smb_fname_new->st)) {
6420 if (overwrite_if_exists) {
6421 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6422 return NT_STATUS_FILE_IS_A_DIRECTORY;
6424 status = unlink_internals(conn,
6426 FILE_ATTRIBUTE_NORMAL,
6429 if (!NT_STATUS_IS_OK(status)) {
6433 /* Disallow if newname already exists. */
6434 return NT_STATUS_OBJECT_NAME_COLLISION;
6438 /* No links from a directory. */
6439 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6440 return NT_STATUS_FILE_IS_A_DIRECTORY;
6443 /* Setting a hardlink to/from a stream isn't currently supported. */
6444 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6446 DBG_DEBUG("Old name has streams\n");
6447 return NT_STATUS_INVALID_PARAMETER;
6449 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6451 DBG_DEBUG("New name has streams\n");
6452 return NT_STATUS_INVALID_PARAMETER;
6455 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6456 smb_fname_old->base_name, smb_fname_new->base_name));
6458 ret = SMB_VFS_LINKAT(conn,
6466 status = map_nt_error_from_unix(errno);
6467 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6468 nt_errstr(status), smb_fname_old->base_name,
6469 smb_fname_new->base_name));
6474 /****************************************************************************
6475 Deal with setting the time from any of the setfilepathinfo functions.
6476 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6477 calling this function.
6478 ****************************************************************************/
6480 NTSTATUS smb_set_file_time(connection_struct *conn,
6482 const struct smb_filename *smb_fname,
6483 struct smb_file_time *ft,
6484 bool setting_write_time)
6486 struct smb_filename smb_fname_base;
6488 FILE_NOTIFY_CHANGE_LAST_ACCESS
6489 |FILE_NOTIFY_CHANGE_LAST_WRITE
6490 |FILE_NOTIFY_CHANGE_CREATION;
6492 if (!VALID_STAT(smb_fname->st)) {
6493 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6496 /* get some defaults (no modifications) if any info is zero or -1. */
6497 if (null_timespec(ft->create_time)) {
6498 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6501 if (null_timespec(ft->atime)) {
6502 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6505 if (null_timespec(ft->mtime)) {
6506 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6509 if (!setting_write_time) {
6510 /* ft->mtime comes from change time, not write time. */
6511 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6514 /* Ensure the resolution is the correct for
6515 * what we can store on this filesystem. */
6517 round_timespec(conn->ts_res, &ft->create_time);
6518 round_timespec(conn->ts_res, &ft->ctime);
6519 round_timespec(conn->ts_res, &ft->atime);
6520 round_timespec(conn->ts_res, &ft->mtime);
6522 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6523 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6524 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6525 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6526 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6527 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6528 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6529 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6531 if (setting_write_time) {
6533 * This was a Windows setfileinfo on an open file.
6534 * NT does this a lot. We also need to
6535 * set the time here, as it can be read by
6536 * FindFirst/FindNext and with the patch for bug #2045
6537 * in smbd/fileio.c it ensures that this timestamp is
6538 * kept sticky even after a write. We save the request
6539 * away and will set it on file close and after a write. JRA.
6542 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6543 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6546 if (fsp->base_fsp) {
6547 set_sticky_write_time_fsp(fsp->base_fsp,
6550 set_sticky_write_time_fsp(fsp, ft->mtime);
6553 set_sticky_write_time_path(
6554 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6559 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6561 /* Always call ntimes on the base, even if a stream was passed in. */
6562 smb_fname_base = *smb_fname;
6563 smb_fname_base.stream_name = NULL;
6565 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6566 return map_nt_error_from_unix(errno);
6569 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6570 smb_fname->base_name);
6571 return NT_STATUS_OK;
6574 /****************************************************************************
6575 Deal with setting the dosmode from any of the setfilepathinfo functions.
6576 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6577 done before calling this function.
6578 ****************************************************************************/
6580 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6581 const struct smb_filename *smb_fname,
6584 struct smb_filename *smb_fname_base;
6587 if (!VALID_STAT(smb_fname->st)) {
6588 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6591 /* Always operate on the base_name, even if a stream was passed in. */
6592 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6593 smb_fname->base_name,
6597 if (smb_fname_base == NULL) {
6598 return NT_STATUS_NO_MEMORY;
6602 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6603 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6605 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6609 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6611 /* check the mode isn't different, before changing it */
6612 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6613 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6614 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6615 (unsigned int)dosmode));
6617 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6619 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6621 smb_fname_str_dbg(smb_fname_base),
6623 status = map_nt_error_from_unix(errno);
6627 status = NT_STATUS_OK;
6629 TALLOC_FREE(smb_fname_base);
6633 /****************************************************************************
6634 Deal with setting the size from any of the setfilepathinfo functions.
6635 ****************************************************************************/
6637 static NTSTATUS smb_set_file_size(connection_struct *conn,
6638 struct smb_request *req,
6640 const struct smb_filename *smb_fname,
6641 const SMB_STRUCT_STAT *psbuf,
6643 bool fail_after_createfile)
6645 NTSTATUS status = NT_STATUS_OK;
6646 struct smb_filename *smb_fname_tmp = NULL;
6647 files_struct *new_fsp = NULL;
6649 if (!VALID_STAT(*psbuf)) {
6650 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6653 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6655 get_file_size_stat(psbuf));
6657 if (size == get_file_size_stat(psbuf)) {
6658 return NT_STATUS_OK;
6661 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6662 smb_fname_str_dbg(smb_fname), (double)size));
6664 if (fsp && fsp->fh->fd != -1) {
6665 /* Handle based call. */
6666 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6667 return NT_STATUS_ACCESS_DENIED;
6670 if (vfs_set_filelen(fsp, size) == -1) {
6671 return map_nt_error_from_unix(errno);
6673 trigger_write_time_update_immediate(fsp);
6674 return NT_STATUS_OK;
6677 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6678 if (smb_fname_tmp == NULL) {
6679 return NT_STATUS_NO_MEMORY;
6682 smb_fname_tmp->st = *psbuf;
6684 status = SMB_VFS_CREATE_FILE(
6687 0, /* root_dir_fid */
6688 smb_fname_tmp, /* fname */
6689 FILE_WRITE_DATA, /* access_mask */
6690 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6692 FILE_OPEN, /* create_disposition*/
6693 0, /* create_options */
6694 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6695 0, /* oplock_request */
6697 0, /* allocation_size */
6698 0, /* private_flags */
6701 &new_fsp, /* result */
6703 NULL, NULL); /* create context */
6705 TALLOC_FREE(smb_fname_tmp);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 /* NB. We check for open_was_deferred in the caller. */
6712 /* See RAW-SFILEINFO-END-OF-FILE */
6713 if (fail_after_createfile) {
6714 close_file(req, new_fsp,NORMAL_CLOSE);
6715 return NT_STATUS_INVALID_LEVEL;
6718 if (vfs_set_filelen(new_fsp, size) == -1) {
6719 status = map_nt_error_from_unix(errno);
6720 close_file(req, new_fsp,NORMAL_CLOSE);
6724 trigger_write_time_update_immediate(new_fsp);
6725 close_file(req, new_fsp,NORMAL_CLOSE);
6726 return NT_STATUS_OK;
6729 /****************************************************************************
6730 Deal with SMB_INFO_SET_EA.
6731 ****************************************************************************/
6733 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6737 const struct smb_filename *smb_fname)
6739 struct ea_list *ea_list = NULL;
6740 TALLOC_CTX *ctx = NULL;
6741 NTSTATUS status = NT_STATUS_OK;
6743 if (total_data < 10) {
6745 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6746 length. They seem to have no effect. Bug #3212. JRA */
6748 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6749 /* We're done. We only get EA info in this call. */
6750 return NT_STATUS_OK;
6753 return NT_STATUS_INVALID_PARAMETER;
6756 if (IVAL(pdata,0) > total_data) {
6757 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6758 IVAL(pdata,0), (unsigned int)total_data));
6759 return NT_STATUS_INVALID_PARAMETER;
6763 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6765 return NT_STATUS_INVALID_PARAMETER;
6768 status = set_ea(conn, fsp, smb_fname, ea_list);
6773 /****************************************************************************
6774 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6775 ****************************************************************************/
6777 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6782 struct ea_list *ea_list = NULL;
6786 return NT_STATUS_INVALID_HANDLE;
6789 if (!lp_ea_support(SNUM(conn))) {
6790 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6791 "EA's not supported.\n",
6792 (unsigned int)total_data));
6793 return NT_STATUS_EAS_NOT_SUPPORTED;
6796 if (total_data < 10) {
6797 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6799 (unsigned int)total_data));
6800 return NT_STATUS_INVALID_PARAMETER;
6803 ea_list = read_nttrans_ea_list(talloc_tos(),
6808 return NT_STATUS_INVALID_PARAMETER;
6811 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6813 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6814 smb_fname_str_dbg(fsp->fsp_name),
6815 nt_errstr(status) ));
6821 /****************************************************************************
6822 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6823 ****************************************************************************/
6825 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6829 struct smb_filename *smb_fname)
6831 NTSTATUS status = NT_STATUS_OK;
6832 bool delete_on_close;
6833 uint32_t dosmode = 0;
6835 if (total_data < 1) {
6836 return NT_STATUS_INVALID_PARAMETER;
6840 return NT_STATUS_INVALID_HANDLE;
6843 delete_on_close = (CVAL(pdata,0) ? True : False);
6844 dosmode = dos_mode(conn, smb_fname);
6846 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6847 "delete_on_close = %u\n",
6848 smb_fname_str_dbg(smb_fname),
6849 (unsigned int)dosmode,
6850 (unsigned int)delete_on_close ));
6852 if (delete_on_close) {
6853 status = can_set_delete_on_close(fsp, dosmode);
6854 if (!NT_STATUS_IS_OK(status)) {
6859 /* The set is across all open files on this dev/inode pair. */
6860 if (!set_delete_on_close(fsp, delete_on_close,
6861 conn->session_info->security_token,
6862 conn->session_info->unix_token)) {
6863 return NT_STATUS_ACCESS_DENIED;
6865 return NT_STATUS_OK;
6868 /****************************************************************************
6869 Deal with SMB_FILE_POSITION_INFORMATION.
6870 ****************************************************************************/
6872 static NTSTATUS smb_file_position_information(connection_struct *conn,
6877 uint64_t position_information;
6879 if (total_data < 8) {
6880 return NT_STATUS_INVALID_PARAMETER;
6884 /* Ignore on pathname based set. */
6885 return NT_STATUS_OK;
6888 position_information = (uint64_t)IVAL(pdata,0);
6889 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6891 DEBUG(10,("smb_file_position_information: Set file position "
6892 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6893 (double)position_information));
6894 fsp->fh->position_information = position_information;
6895 return NT_STATUS_OK;
6898 /****************************************************************************
6899 Deal with SMB_FILE_MODE_INFORMATION.
6900 ****************************************************************************/
6902 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6908 if (total_data < 4) {
6909 return NT_STATUS_INVALID_PARAMETER;
6911 mode = IVAL(pdata,0);
6912 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6913 return NT_STATUS_INVALID_PARAMETER;
6915 return NT_STATUS_OK;
6918 /****************************************************************************
6919 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6920 ****************************************************************************/
6922 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6923 struct smb_request *req,
6926 const struct smb_filename *new_smb_fname)
6928 char *link_target = NULL;
6929 TALLOC_CTX *ctx = talloc_tos();
6931 /* Set a symbolic link. */
6932 /* Don't allow this if follow links is false. */
6934 if (total_data == 0) {
6935 return NT_STATUS_INVALID_PARAMETER;
6938 if (!lp_follow_symlinks(SNUM(conn))) {
6939 return NT_STATUS_ACCESS_DENIED;
6942 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6943 total_data, STR_TERMINATE);
6946 return NT_STATUS_INVALID_PARAMETER;
6949 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6950 new_smb_fname->base_name, link_target ));
6952 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6953 return map_nt_error_from_unix(errno);
6956 return NT_STATUS_OK;
6959 /****************************************************************************
6960 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6961 ****************************************************************************/
6963 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6964 struct smb_request *req,
6965 const char *pdata, int total_data,
6966 struct smb_filename *smb_fname_new)
6968 char *oldname = NULL;
6969 struct smb_filename *smb_fname_old = NULL;
6970 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6971 TALLOC_CTX *ctx = talloc_tos();
6972 NTSTATUS status = NT_STATUS_OK;
6974 /* Set a hard link. */
6975 if (total_data == 0) {
6976 return NT_STATUS_INVALID_PARAMETER;
6979 if (req->posix_pathnames) {
6980 srvstr_get_path_posix(ctx,
6989 srvstr_get_path(ctx,
6998 if (!NT_STATUS_IS_OK(status)) {
7002 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7003 smb_fname_str_dbg(smb_fname_new), oldname));
7005 status = filename_convert(ctx,
7012 if (!NT_STATUS_IS_OK(status)) {
7016 return hardlink_internals(ctx, conn, req, false,
7017 smb_fname_old, smb_fname_new);
7020 /****************************************************************************
7021 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7022 ****************************************************************************/
7024 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7025 struct smb_request *req,
7029 struct smb_filename *smb_fname_src)
7033 char *newname = NULL;
7034 struct smb_filename *smb_fname_dst = NULL;
7035 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7036 ucf_flags_from_smb_request(req);
7037 NTSTATUS status = NT_STATUS_OK;
7038 TALLOC_CTX *ctx = talloc_tos();
7041 return NT_STATUS_INVALID_HANDLE;
7044 if (total_data < 20) {
7045 return NT_STATUS_INVALID_PARAMETER;
7048 overwrite = (CVAL(pdata,0) ? True : False);
7049 len = IVAL(pdata,16);
7051 if (len > (total_data - 20) || (len == 0)) {
7052 return NT_STATUS_INVALID_PARAMETER;
7055 if (req->posix_pathnames) {
7056 srvstr_get_path_posix(ctx,
7065 srvstr_get_path(ctx,
7074 if (!NT_STATUS_IS_OK(status)) {
7078 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7081 status = filename_convert(ctx,
7088 if (!NT_STATUS_IS_OK(status)) {
7092 if (fsp->base_fsp) {
7093 /* newname must be a stream name. */
7094 if (newname[0] != ':') {
7095 return NT_STATUS_NOT_SUPPORTED;
7098 /* Create an smb_fname to call rename_internals_fsp() with. */
7099 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7100 fsp->base_fsp->fsp_name->base_name,
7103 fsp->base_fsp->fsp_name->flags);
7104 if (smb_fname_dst == NULL) {
7105 status = NT_STATUS_NO_MEMORY;
7110 * Set the original last component, since
7111 * rename_internals_fsp() requires it.
7113 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7115 if (smb_fname_dst->original_lcomp == NULL) {
7116 status = NT_STATUS_NO_MEMORY;
7122 DEBUG(10,("smb2_file_rename_information: "
7123 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7124 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7125 smb_fname_str_dbg(smb_fname_dst)));
7126 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7127 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7131 TALLOC_FREE(smb_fname_dst);
7135 static NTSTATUS smb_file_link_information(connection_struct *conn,
7136 struct smb_request *req,
7140 struct smb_filename *smb_fname_src)
7144 char *newname = NULL;
7145 struct smb_filename *smb_fname_dst = NULL;
7146 NTSTATUS status = NT_STATUS_OK;
7147 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7148 ucf_flags_from_smb_request(req);
7149 TALLOC_CTX *ctx = talloc_tos();
7152 return NT_STATUS_INVALID_HANDLE;
7155 if (total_data < 20) {
7156 return NT_STATUS_INVALID_PARAMETER;
7159 overwrite = (CVAL(pdata,0) ? true : false);
7160 len = IVAL(pdata,16);
7162 if (len > (total_data - 20) || (len == 0)) {
7163 return NT_STATUS_INVALID_PARAMETER;
7166 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7167 srvstr_get_path_posix(ctx,
7175 ucf_flags |= UCF_POSIX_PATHNAMES;
7177 srvstr_get_path(ctx,
7186 if (!NT_STATUS_IS_OK(status)) {
7190 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7193 status = filename_convert(ctx,
7200 if (!NT_STATUS_IS_OK(status)) {
7204 if (fsp->base_fsp) {
7205 /* No stream names. */
7206 return NT_STATUS_NOT_SUPPORTED;
7209 DEBUG(10,("smb_file_link_information: "
7210 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7211 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7212 smb_fname_str_dbg(smb_fname_dst)));
7213 status = hardlink_internals(ctx,
7220 TALLOC_FREE(smb_fname_dst);
7224 /****************************************************************************
7225 Deal with SMB_FILE_RENAME_INFORMATION.
7226 ****************************************************************************/
7228 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7229 struct smb_request *req,
7233 struct smb_filename *smb_fname_src)
7238 char *newname = NULL;
7239 struct smb_filename *smb_fname_dst = NULL;
7240 bool dest_has_wcard = False;
7241 NTSTATUS status = NT_STATUS_OK;
7243 TALLOC_CTX *ctx = talloc_tos();
7245 if (total_data < 13) {
7246 return NT_STATUS_INVALID_PARAMETER;
7249 overwrite = (CVAL(pdata,0) ? True : False);
7250 root_fid = IVAL(pdata,4);
7251 len = IVAL(pdata,8);
7253 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7254 return NT_STATUS_INVALID_PARAMETER;
7257 if (req->posix_pathnames) {
7258 srvstr_get_path_wcard_posix(ctx,
7268 srvstr_get_path_wcard(ctx,
7278 if (!NT_STATUS_IS_OK(status)) {
7282 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7285 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7286 status = resolve_dfspath_wcard(ctx, conn,
7288 UCF_COND_ALLOW_WCARD_LCOMP,
7289 !conn->sconn->using_smb2,
7292 if (!NT_STATUS_IS_OK(status)) {
7297 /* Check the new name has no '/' characters. */
7298 if (strchr_m(newname, '/')) {
7299 return NT_STATUS_NOT_SUPPORTED;
7302 if (fsp && fsp->base_fsp) {
7303 /* newname must be a stream name. */
7304 if (newname[0] != ':') {
7305 return NT_STATUS_NOT_SUPPORTED;
7308 /* Create an smb_fname to call rename_internals_fsp() with. */
7309 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7310 fsp->base_fsp->fsp_name->base_name,
7313 fsp->base_fsp->fsp_name->flags);
7314 if (smb_fname_dst == NULL) {
7315 status = NT_STATUS_NO_MEMORY;
7320 * Set the original last component, since
7321 * rename_internals_fsp() requires it.
7323 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7325 if (smb_fname_dst->original_lcomp == NULL) {
7326 status = NT_STATUS_NO_MEMORY;
7332 * Build up an smb_fname_dst based on the filename passed in.
7333 * We basically just strip off the last component, and put on
7334 * the newname instead.
7336 char *base_name = NULL;
7337 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7338 ucf_flags_from_smb_request(req);
7340 if (dest_has_wcard) {
7341 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7344 /* newname must *not* be a stream name. */
7345 if (newname[0] == ':') {
7346 return NT_STATUS_NOT_SUPPORTED;
7350 * Strip off the last component (filename) of the path passed
7353 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7355 return NT_STATUS_NO_MEMORY;
7357 p = strrchr_m(base_name, '/');
7361 base_name = talloc_strdup(ctx, "");
7363 return NT_STATUS_NO_MEMORY;
7366 /* Append the new name. */
7367 base_name = talloc_asprintf_append(base_name,
7371 return NT_STATUS_NO_MEMORY;
7374 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7377 /* If an error we expect this to be
7378 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7380 if (!NT_STATUS_IS_OK(status)) {
7381 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7385 /* Create an smb_fname to call rename_internals_fsp() */
7386 smb_fname_dst = synthetic_smb_fname(ctx,
7390 smb_fname_src->flags);
7391 if (smb_fname_dst == NULL) {
7392 status = NT_STATUS_NO_MEMORY;
7399 DEBUG(10,("smb_file_rename_information: "
7400 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7401 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7402 smb_fname_str_dbg(smb_fname_dst)));
7403 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7406 DEBUG(10,("smb_file_rename_information: "
7407 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7408 smb_fname_str_dbg(smb_fname_src),
7409 smb_fname_str_dbg(smb_fname_dst)));
7410 status = rename_internals(ctx, conn, req, smb_fname_src,
7411 smb_fname_dst, 0, overwrite, false,
7413 FILE_WRITE_ATTRIBUTES);
7416 TALLOC_FREE(smb_fname_dst);
7420 /****************************************************************************
7421 Deal with SMB_SET_POSIX_ACL.
7422 ****************************************************************************/
7424 #if defined(HAVE_POSIX_ACLS)
7425 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7426 struct smb_request *req,
7430 const struct smb_filename *smb_fname)
7432 uint16_t posix_acl_version;
7433 uint16_t num_file_acls;
7434 uint16_t num_def_acls;
7435 bool valid_file_acls = true;
7436 bool valid_def_acls = true;
7438 unsigned int size_needed;
7439 unsigned int total_data;
7440 bool close_fsp = false;
7442 if (total_data_in < 0) {
7443 status = NT_STATUS_INVALID_PARAMETER;
7447 total_data = total_data_in;
7449 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7450 status = NT_STATUS_INVALID_PARAMETER;
7453 posix_acl_version = SVAL(pdata,0);
7454 num_file_acls = SVAL(pdata,2);
7455 num_def_acls = SVAL(pdata,4);
7457 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7458 valid_file_acls = false;
7462 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7463 valid_def_acls = false;
7467 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7468 status = NT_STATUS_INVALID_PARAMETER;
7473 if (num_file_acls + num_def_acls < num_file_acls) {
7474 status = NT_STATUS_INVALID_PARAMETER;
7478 size_needed = num_file_acls + num_def_acls;
7481 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7482 * than UINT_MAX, so check by division.
7484 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7485 status = NT_STATUS_INVALID_PARAMETER;
7489 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7490 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7491 status = NT_STATUS_INVALID_PARAMETER;
7494 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7496 if (total_data < size_needed) {
7497 status = NT_STATUS_INVALID_PARAMETER;
7502 * Ensure we always operate on a file descriptor, not just
7506 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7508 SEC_STD_READ_CONTROL|
7509 FILE_READ_ATTRIBUTES|
7510 FILE_WRITE_ATTRIBUTES;
7512 status = get_posix_fsp(conn,
7518 if (!NT_STATUS_IS_OK(status)) {
7524 /* Here we know fsp != NULL */
7525 SMB_ASSERT(fsp != NULL);
7527 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7528 if (!NT_STATUS_IS_OK(status)) {
7532 /* If we have a default acl, this *must* be a directory. */
7533 if (valid_def_acls && !fsp->is_directory) {
7534 DBG_INFO("Can't set default acls on "
7535 "non-directory %s\n",
7537 return NT_STATUS_INVALID_HANDLE;
7540 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7541 "num_def_acls = %"PRIu16"\n",
7546 /* Move pdata to the start of the file ACL entries. */
7547 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7549 if (valid_file_acls) {
7550 status = set_unix_posix_acl(conn,
7554 if (!NT_STATUS_IS_OK(status)) {
7559 /* Move pdata to the start of the default ACL entries. */
7560 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7562 if (valid_def_acls) {
7563 status = set_unix_posix_default_acl(conn,
7567 if (!NT_STATUS_IS_OK(status)) {
7572 status = NT_STATUS_OK;
7577 (void)close_file(req, fsp, NORMAL_CLOSE);
7584 /****************************************************************************
7585 Deal with SMB_SET_POSIX_LOCK.
7586 ****************************************************************************/
7588 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7590 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7591 struct smb_request *req,
7596 struct tevent_req *subreq = NULL;
7597 struct smbd_lock_element *lck = NULL;
7601 bool blocking_lock = False;
7602 enum brl_type lock_type;
7604 NTSTATUS status = NT_STATUS_OK;
7606 if (fsp == NULL || fsp->fh->fd == -1) {
7607 return NT_STATUS_INVALID_HANDLE;
7610 if (total_data != POSIX_LOCK_DATA_SIZE) {
7611 return NT_STATUS_INVALID_PARAMETER;
7614 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7615 case POSIX_LOCK_TYPE_READ:
7616 lock_type = READ_LOCK;
7618 case POSIX_LOCK_TYPE_WRITE:
7619 /* Return the right POSIX-mappable error code for files opened read-only. */
7620 if (!fsp->can_write) {
7621 return NT_STATUS_INVALID_HANDLE;
7623 lock_type = WRITE_LOCK;
7625 case POSIX_LOCK_TYPE_UNLOCK:
7626 lock_type = UNLOCK_LOCK;
7629 return NT_STATUS_INVALID_PARAMETER;
7632 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7633 case POSIX_LOCK_FLAG_NOWAIT:
7634 blocking_lock = false;
7636 case POSIX_LOCK_FLAG_WAIT:
7637 blocking_lock = true;
7640 return NT_STATUS_INVALID_PARAMETER;
7643 if (!lp_blocking_locks(SNUM(conn))) {
7644 blocking_lock = False;
7647 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7648 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7649 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7650 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7651 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7653 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7654 "count = %"PRIu64", offset = %"PRIu64"\n",
7656 (unsigned int)lock_type,
7661 if (lock_type == UNLOCK_LOCK) {
7662 struct smbd_lock_element l = {
7664 .brltype = UNLOCK_LOCK,
7668 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7672 lck = talloc(req, struct smbd_lock_element);
7674 return NT_STATUS_NO_MEMORY;
7677 *lck = (struct smbd_lock_element) {
7679 .brltype = lock_type,
7684 subreq = smbd_smb1_do_locks_send(
7689 blocking_lock ? UINT32_MAX : 0,
7690 true, /* large_offset */
7694 if (subreq == NULL) {
7696 return NT_STATUS_NO_MEMORY;
7698 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7699 return NT_STATUS_EVENT_PENDING;
7702 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7704 struct smb_request *req = NULL;
7708 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7711 status = smbd_smb1_do_locks_recv(subreq);
7712 TALLOC_FREE(subreq);
7714 if (NT_STATUS_IS_OK(status)) {
7715 char params[2] = {0};
7716 /* Fake up max_data_bytes here - we know it fits. */
7717 send_trans2_replies(
7727 reply_nterror(req, status);
7730 (char *)req->outbuf,
7733 IS_CONN_ENCRYPTED(req->conn),
7736 exit_server_cleanly("smb_set_posix_lock_done: "
7737 "srv_send_smb failed.");
7745 /****************************************************************************
7746 Deal with SMB_SET_FILE_BASIC_INFO.
7747 ****************************************************************************/
7749 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7753 const struct smb_filename *smb_fname)
7755 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7756 struct smb_file_time ft;
7757 uint32_t dosmode = 0;
7758 NTSTATUS status = NT_STATUS_OK;
7762 if (total_data < 36) {
7763 return NT_STATUS_INVALID_PARAMETER;
7766 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7767 if (!NT_STATUS_IS_OK(status)) {
7771 /* Set the attributes */
7772 dosmode = IVAL(pdata,32);
7773 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7774 if (!NT_STATUS_IS_OK(status)) {
7779 ft.create_time = interpret_long_date(pdata);
7782 ft.atime = interpret_long_date(pdata+8);
7785 ft.mtime = interpret_long_date(pdata+16);
7788 ft.ctime = interpret_long_date(pdata+24);
7790 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7791 smb_fname_str_dbg(smb_fname)));
7793 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7797 /****************************************************************************
7798 Deal with SMB_INFO_STANDARD.
7799 ****************************************************************************/
7801 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7805 const struct smb_filename *smb_fname)
7808 struct smb_file_time ft;
7812 if (total_data < 12) {
7813 return NT_STATUS_INVALID_PARAMETER;
7817 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7819 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7821 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7823 DEBUG(10,("smb_set_info_standard: file %s\n",
7824 smb_fname_str_dbg(smb_fname)));
7826 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7827 if (!NT_STATUS_IS_OK(status)) {
7831 return smb_set_file_time(conn,
7838 /****************************************************************************
7839 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7840 ****************************************************************************/
7842 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7843 struct smb_request *req,
7847 struct smb_filename *smb_fname)
7849 uint64_t allocation_size = 0;
7850 NTSTATUS status = NT_STATUS_OK;
7851 files_struct *new_fsp = NULL;
7853 if (!VALID_STAT(smb_fname->st)) {
7854 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7857 if (total_data < 8) {
7858 return NT_STATUS_INVALID_PARAMETER;
7861 allocation_size = (uint64_t)IVAL(pdata,0);
7862 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7863 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7864 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7865 (double)allocation_size));
7867 if (allocation_size) {
7868 allocation_size = smb_roundup(conn, allocation_size);
7871 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7872 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7873 (double)allocation_size));
7875 if (fsp && fsp->fh->fd != -1) {
7876 /* Open file handle. */
7877 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7878 return NT_STATUS_ACCESS_DENIED;
7881 /* Only change if needed. */
7882 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7883 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7884 return map_nt_error_from_unix(errno);
7887 /* But always update the time. */
7889 * This is equivalent to a write. Ensure it's seen immediately
7890 * if there are no pending writes.
7892 trigger_write_time_update_immediate(fsp);
7893 return NT_STATUS_OK;
7896 /* Pathname or stat or directory file. */
7897 status = SMB_VFS_CREATE_FILE(
7900 0, /* root_dir_fid */
7901 smb_fname, /* fname */
7902 FILE_WRITE_DATA, /* access_mask */
7903 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7905 FILE_OPEN, /* create_disposition*/
7906 0, /* create_options */
7907 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7908 0, /* oplock_request */
7910 0, /* allocation_size */
7911 0, /* private_flags */
7914 &new_fsp, /* result */
7916 NULL, NULL); /* create context */
7918 if (!NT_STATUS_IS_OK(status)) {
7919 /* NB. We check for open_was_deferred in the caller. */
7923 /* Only change if needed. */
7924 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7925 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7926 status = map_nt_error_from_unix(errno);
7927 close_file(req, new_fsp, NORMAL_CLOSE);
7932 /* Changing the allocation size should set the last mod time. */
7934 * This is equivalent to a write. Ensure it's seen immediately
7935 * if there are no pending writes.
7937 trigger_write_time_update_immediate(new_fsp);
7938 close_file(req, new_fsp, NORMAL_CLOSE);
7939 return NT_STATUS_OK;
7942 /****************************************************************************
7943 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7944 ****************************************************************************/
7946 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7947 struct smb_request *req,
7951 const struct smb_filename *smb_fname,
7952 bool fail_after_createfile)
7956 if (total_data < 8) {
7957 return NT_STATUS_INVALID_PARAMETER;
7960 size = IVAL(pdata,0);
7961 size |= (((off_t)IVAL(pdata,4)) << 32);
7962 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7963 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7966 return smb_set_file_size(conn, req,
7971 fail_after_createfile);
7974 /****************************************************************************
7975 Allow a UNIX info mknod.
7976 ****************************************************************************/
7978 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7981 const struct smb_filename *smb_fname)
7983 uint32_t file_type = IVAL(pdata,56);
7984 #if defined(HAVE_MAKEDEV)
7985 uint32_t dev_major = IVAL(pdata,60);
7986 uint32_t dev_minor = IVAL(pdata,68);
7988 SMB_DEV_T dev = (SMB_DEV_T)0;
7989 uint32_t raw_unixmode = IVAL(pdata,84);
7994 if (total_data < 100) {
7995 return NT_STATUS_INVALID_PARAMETER;
7998 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7999 PERM_NEW_FILE, &unixmode);
8000 if (!NT_STATUS_IS_OK(status)) {
8004 #if defined(HAVE_MAKEDEV)
8005 dev = makedev(dev_major, dev_minor);
8008 switch (file_type) {
8009 #if defined(S_IFIFO)
8010 case UNIX_TYPE_FIFO:
8011 unixmode |= S_IFIFO;
8014 #if defined(S_IFSOCK)
8015 case UNIX_TYPE_SOCKET:
8016 unixmode |= S_IFSOCK;
8019 #if defined(S_IFCHR)
8020 case UNIX_TYPE_CHARDEV:
8021 unixmode |= S_IFCHR;
8024 #if defined(S_IFBLK)
8025 case UNIX_TYPE_BLKDEV:
8026 unixmode |= S_IFBLK;
8030 return NT_STATUS_INVALID_PARAMETER;
8033 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8034 "%.0f mode 0%o for file %s\n", (double)dev,
8035 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8037 /* Ok - do the mknod. */
8038 ret = SMB_VFS_MKNODAT(conn,
8045 return map_nt_error_from_unix(errno);
8048 /* If any of the other "set" calls fail we
8049 * don't want to end up with a half-constructed mknod.
8052 if (lp_inherit_permissions(SNUM(conn))) {
8054 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8056 return NT_STATUS_NO_MEMORY;
8058 inherit_access_posix_acl(conn, parent, smb_fname,
8060 TALLOC_FREE(parent);
8063 return NT_STATUS_OK;
8066 /****************************************************************************
8067 Deal with SMB_SET_FILE_UNIX_BASIC.
8068 ****************************************************************************/
8070 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8071 struct smb_request *req,
8075 const struct smb_filename *smb_fname)
8077 struct smb_file_time ft;
8078 uint32_t raw_unixmode;
8081 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8082 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8083 NTSTATUS status = NT_STATUS_OK;
8084 bool delete_on_fail = False;
8085 enum perm_type ptype;
8086 files_struct *all_fsps = NULL;
8087 bool modify_mtime = true;
8089 struct smb_filename *smb_fname_tmp = NULL;
8090 SMB_STRUCT_STAT sbuf;
8094 if (total_data < 100) {
8095 return NT_STATUS_INVALID_PARAMETER;
8098 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8099 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8100 size=IVAL(pdata,0); /* first 8 Bytes are size */
8101 size |= (((off_t)IVAL(pdata,4)) << 32);
8104 ft.atime = interpret_long_date(pdata+24); /* access_time */
8105 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8106 set_owner = (uid_t)IVAL(pdata,40);
8107 set_grp = (gid_t)IVAL(pdata,48);
8108 raw_unixmode = IVAL(pdata,84);
8110 if (VALID_STAT(smb_fname->st)) {
8111 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8112 ptype = PERM_EXISTING_DIR;
8114 ptype = PERM_EXISTING_FILE;
8117 ptype = PERM_NEW_FILE;
8120 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8122 if (!NT_STATUS_IS_OK(status)) {
8126 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8127 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8128 smb_fname_str_dbg(smb_fname), (double)size,
8129 (unsigned int)set_owner, (unsigned int)set_grp,
8130 (int)raw_unixmode));
8132 sbuf = smb_fname->st;
8134 if (!VALID_STAT(sbuf)) {
8136 * The only valid use of this is to create character and block
8137 * devices, and named pipes. This is deprecated (IMHO) and
8138 * a new info level should be used for mknod. JRA.
8141 status = smb_unix_mknod(conn,
8145 if (!NT_STATUS_IS_OK(status)) {
8149 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8150 if (smb_fname_tmp == NULL) {
8151 return NT_STATUS_NO_MEMORY;
8154 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8155 status = map_nt_error_from_unix(errno);
8156 TALLOC_FREE(smb_fname_tmp);
8157 SMB_VFS_UNLINK(conn, smb_fname);
8161 sbuf = smb_fname_tmp->st;
8162 smb_fname = smb_fname_tmp;
8164 /* Ensure we don't try and change anything else. */
8165 raw_unixmode = SMB_MODE_NO_CHANGE;
8166 size = get_file_size_stat(&sbuf);
8167 ft.atime = sbuf.st_ex_atime;
8168 ft.mtime = sbuf.st_ex_mtime;
8170 * We continue here as we might want to change the
8173 delete_on_fail = True;
8177 /* Horrible backwards compatibility hack as an old server bug
8178 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8182 size = get_file_size_stat(&sbuf);
8187 * Deal with the UNIX specific mode set.
8190 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8193 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8194 "setting mode 0%o for file %s\n",
8195 (unsigned int)unixmode,
8196 smb_fname_str_dbg(smb_fname)));
8197 if (fsp && fsp->fh->fd != -1) {
8198 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8200 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8203 return map_nt_error_from_unix(errno);
8208 * Deal with the UNIX specific uid set.
8211 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8212 (sbuf.st_ex_uid != set_owner)) {
8215 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8216 "changing owner %u for path %s\n",
8217 (unsigned int)set_owner,
8218 smb_fname_str_dbg(smb_fname)));
8220 if (fsp && fsp->fh->fd != -1) {
8221 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8224 * UNIX extensions calls must always operate
8227 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8228 set_owner, (gid_t)-1);
8232 status = map_nt_error_from_unix(errno);
8233 if (delete_on_fail) {
8234 SMB_VFS_UNLINK(conn, smb_fname);
8241 * Deal with the UNIX specific gid set.
8244 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8245 (sbuf.st_ex_gid != set_grp)) {
8248 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8249 "changing group %u for file %s\n",
8250 (unsigned int)set_grp,
8251 smb_fname_str_dbg(smb_fname)));
8252 if (fsp && fsp->fh->fd != -1) {
8253 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8256 * UNIX extensions calls must always operate
8259 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8263 status = map_nt_error_from_unix(errno);
8264 if (delete_on_fail) {
8265 SMB_VFS_UNLINK(conn, smb_fname);
8271 /* Deal with any size changes. */
8273 status = smb_set_file_size(conn, req,
8279 if (!NT_STATUS_IS_OK(status)) {
8283 /* Deal with any time changes. */
8284 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8285 /* No change, don't cancel anything. */
8289 id = vfs_file_id_from_sbuf(conn, &sbuf);
8290 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8291 all_fsps = file_find_di_next(all_fsps)) {
8293 * We're setting the time explicitly for UNIX.
8294 * Cancel any pending changes over all handles.
8296 all_fsps->update_write_time_on_close = false;
8297 TALLOC_FREE(all_fsps->update_write_time_event);
8301 * Override the "setting_write_time"
8302 * parameter here as it almost does what
8303 * we need. Just remember if we modified
8304 * mtime and send the notify ourselves.
8306 if (null_timespec(ft.mtime)) {
8307 modify_mtime = false;
8310 status = smb_set_file_time(conn,
8316 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8317 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8322 /****************************************************************************
8323 Deal with SMB_SET_FILE_UNIX_INFO2.
8324 ****************************************************************************/
8326 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8327 struct smb_request *req,
8331 const struct smb_filename *smb_fname)
8334 uint32_t smb_fflags;
8337 if (total_data < 116) {
8338 return NT_STATUS_INVALID_PARAMETER;
8341 /* Start by setting all the fields that are common between UNIX_BASIC
8344 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8346 if (!NT_STATUS_IS_OK(status)) {
8350 smb_fflags = IVAL(pdata, 108);
8351 smb_fmask = IVAL(pdata, 112);
8353 /* NB: We should only attempt to alter the file flags if the client
8354 * sends a non-zero mask.
8356 if (smb_fmask != 0) {
8357 int stat_fflags = 0;
8359 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8360 smb_fmask, &stat_fflags)) {
8361 /* Client asked to alter a flag we don't understand. */
8362 return NT_STATUS_INVALID_PARAMETER;
8365 if (fsp && fsp->fh->fd != -1) {
8366 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8367 return NT_STATUS_NOT_SUPPORTED;
8369 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8370 stat_fflags) != 0) {
8371 return map_nt_error_from_unix(errno);
8376 /* XXX: need to add support for changing the create_time here. You
8377 * can do this for paths on Darwin with setattrlist(2). The right way
8378 * to hook this up is probably by extending the VFS utimes interface.
8381 return NT_STATUS_OK;
8384 /****************************************************************************
8385 Create a directory with POSIX semantics.
8386 ****************************************************************************/
8388 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8389 struct smb_request *req,
8392 struct smb_filename *smb_fname,
8393 int *pdata_return_size)
8395 NTSTATUS status = NT_STATUS_OK;
8396 uint32_t raw_unixmode = 0;
8397 uint32_t mod_unixmode = 0;
8398 mode_t unixmode = (mode_t)0;
8399 files_struct *fsp = NULL;
8400 uint16_t info_level_return = 0;
8402 char *pdata = *ppdata;
8404 if (total_data < 18) {
8405 return NT_STATUS_INVALID_PARAMETER;
8408 raw_unixmode = IVAL(pdata,8);
8409 /* Next 4 bytes are not yet defined. */
8411 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8412 PERM_NEW_DIR, &unixmode);
8413 if (!NT_STATUS_IS_OK(status)) {
8417 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8419 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8420 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8422 status = SMB_VFS_CREATE_FILE(
8425 0, /* root_dir_fid */
8426 smb_fname, /* fname */
8427 FILE_READ_ATTRIBUTES, /* access_mask */
8428 FILE_SHARE_NONE, /* share_access */
8429 FILE_CREATE, /* create_disposition*/
8430 FILE_DIRECTORY_FILE, /* create_options */
8431 mod_unixmode, /* file_attributes */
8432 0, /* oplock_request */
8434 0, /* allocation_size */
8435 0, /* private_flags */
8440 NULL, NULL); /* create context */
8442 if (NT_STATUS_IS_OK(status)) {
8443 close_file(req, fsp, NORMAL_CLOSE);
8446 info_level_return = SVAL(pdata,16);
8448 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8449 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8450 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8451 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8453 *pdata_return_size = 12;
8456 /* Realloc the data size */
8457 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8458 if (*ppdata == NULL) {
8459 *pdata_return_size = 0;
8460 return NT_STATUS_NO_MEMORY;
8464 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8465 SSVAL(pdata,2,0); /* No fnum. */
8466 SIVAL(pdata,4,info); /* Was directory created. */
8468 switch (info_level_return) {
8469 case SMB_QUERY_FILE_UNIX_BASIC:
8470 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8471 SSVAL(pdata,10,0); /* Padding. */
8472 store_file_unix_basic(conn, pdata + 12, fsp,
8475 case SMB_QUERY_FILE_UNIX_INFO2:
8476 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8477 SSVAL(pdata,10,0); /* Padding. */
8478 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8482 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8483 SSVAL(pdata,10,0); /* Padding. */
8490 /****************************************************************************
8491 Open/Create a file with POSIX semantics.
8492 ****************************************************************************/
8494 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8495 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8497 static NTSTATUS smb_posix_open(connection_struct *conn,
8498 struct smb_request *req,
8501 struct smb_filename *smb_fname,
8502 int *pdata_return_size)
8504 bool extended_oplock_granted = False;
8505 char *pdata = *ppdata;
8507 uint32_t wire_open_mode = 0;
8508 uint32_t raw_unixmode = 0;
8509 uint32_t mod_unixmode = 0;
8510 uint32_t create_disp = 0;
8511 uint32_t access_mask = 0;
8512 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8513 NTSTATUS status = NT_STATUS_OK;
8514 mode_t unixmode = (mode_t)0;
8515 files_struct *fsp = NULL;
8516 int oplock_request = 0;
8518 uint16_t info_level_return = 0;
8520 if (total_data < 18) {
8521 return NT_STATUS_INVALID_PARAMETER;
8524 flags = IVAL(pdata,0);
8525 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8526 if (oplock_request) {
8527 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8530 wire_open_mode = IVAL(pdata,4);
8532 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8533 return smb_posix_mkdir(conn, req,
8540 switch (wire_open_mode & SMB_ACCMODE) {
8542 access_mask = SMB_O_RDONLY_MAPPING;
8545 access_mask = SMB_O_WRONLY_MAPPING;
8548 access_mask = (SMB_O_RDONLY_MAPPING|
8549 SMB_O_WRONLY_MAPPING);
8552 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8553 (unsigned int)wire_open_mode ));
8554 return NT_STATUS_INVALID_PARAMETER;
8557 wire_open_mode &= ~SMB_ACCMODE;
8559 /* First take care of O_CREAT|O_EXCL interactions. */
8560 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8561 case (SMB_O_CREAT | SMB_O_EXCL):
8562 /* File exists fail. File not exist create. */
8563 create_disp = FILE_CREATE;
8566 /* File exists open. File not exist create. */
8567 create_disp = FILE_OPEN_IF;
8570 /* O_EXCL on its own without O_CREAT is undefined.
8571 We deliberately ignore it as some versions of
8572 Linux CIFSFS can send a bare O_EXCL on the
8573 wire which other filesystems in the kernel
8574 ignore. See bug 9519 for details. */
8579 /* File exists open. File not exist fail. */
8580 create_disp = FILE_OPEN;
8583 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8584 (unsigned int)wire_open_mode ));
8585 return NT_STATUS_INVALID_PARAMETER;
8588 /* Next factor in the effects of O_TRUNC. */
8589 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8591 if (wire_open_mode & SMB_O_TRUNC) {
8592 switch (create_disp) {
8594 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8595 /* Leave create_disp alone as
8596 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8598 /* File exists fail. File not exist create. */
8601 /* SMB_O_CREAT | SMB_O_TRUNC */
8602 /* File exists overwrite. File not exist create. */
8603 create_disp = FILE_OVERWRITE_IF;
8607 /* File exists overwrite. File not exist fail. */
8608 create_disp = FILE_OVERWRITE;
8611 /* Cannot get here. */
8612 smb_panic("smb_posix_open: logic error");
8613 return NT_STATUS_INVALID_PARAMETER;
8617 raw_unixmode = IVAL(pdata,8);
8618 /* Next 4 bytes are not yet defined. */
8620 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8621 (VALID_STAT(smb_fname->st) ?
8622 PERM_EXISTING_FILE : PERM_NEW_FILE),
8625 if (!NT_STATUS_IS_OK(status)) {
8629 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8631 if (wire_open_mode & SMB_O_SYNC) {
8632 create_options |= FILE_WRITE_THROUGH;
8634 if (wire_open_mode & SMB_O_APPEND) {
8635 access_mask |= FILE_APPEND_DATA;
8637 if (wire_open_mode & SMB_O_DIRECT) {
8638 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8641 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8642 VALID_STAT_OF_DIR(smb_fname->st)) {
8643 if (access_mask != SMB_O_RDONLY_MAPPING) {
8644 return NT_STATUS_FILE_IS_A_DIRECTORY;
8646 create_options &= ~FILE_NON_DIRECTORY_FILE;
8647 create_options |= FILE_DIRECTORY_FILE;
8650 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8651 smb_fname_str_dbg(smb_fname),
8652 (unsigned int)wire_open_mode,
8653 (unsigned int)unixmode ));
8655 status = SMB_VFS_CREATE_FILE(
8658 0, /* root_dir_fid */
8659 smb_fname, /* fname */
8660 access_mask, /* access_mask */
8661 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8663 create_disp, /* create_disposition*/
8664 create_options, /* create_options */
8665 mod_unixmode, /* file_attributes */
8666 oplock_request, /* oplock_request */
8668 0, /* allocation_size */
8669 0, /* private_flags */
8674 NULL, NULL); /* create context */
8676 if (!NT_STATUS_IS_OK(status)) {
8680 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8681 extended_oplock_granted = True;
8684 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8685 extended_oplock_granted = True;
8688 info_level_return = SVAL(pdata,16);
8690 /* Allocate the correct return size. */
8692 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8693 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8694 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8695 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8697 *pdata_return_size = 12;
8700 /* Realloc the data size */
8701 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8702 if (*ppdata == NULL) {
8703 close_file(req, fsp, ERROR_CLOSE);
8704 *pdata_return_size = 0;
8705 return NT_STATUS_NO_MEMORY;
8709 if (extended_oplock_granted) {
8710 if (flags & REQUEST_BATCH_OPLOCK) {
8711 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8713 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8715 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8716 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8718 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8721 SSVAL(pdata,2,fsp->fnum);
8722 SIVAL(pdata,4,info); /* Was file created etc. */
8724 switch (info_level_return) {
8725 case SMB_QUERY_FILE_UNIX_BASIC:
8726 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8727 SSVAL(pdata,10,0); /* padding. */
8728 store_file_unix_basic(conn, pdata + 12, fsp,
8731 case SMB_QUERY_FILE_UNIX_INFO2:
8732 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8733 SSVAL(pdata,10,0); /* padding. */
8734 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8738 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8739 SSVAL(pdata,10,0); /* padding. */
8742 return NT_STATUS_OK;
8745 /****************************************************************************
8746 Delete a file with POSIX semantics.
8747 ****************************************************************************/
8749 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8750 struct smb_request *req,
8753 struct smb_filename *smb_fname)
8755 NTSTATUS status = NT_STATUS_OK;
8756 files_struct *fsp = NULL;
8760 int create_options = 0;
8761 struct share_mode_lock *lck = NULL;
8762 bool other_nonposix_opens;
8764 if (total_data < 2) {
8765 return NT_STATUS_INVALID_PARAMETER;
8768 flags = SVAL(pdata,0);
8770 if (!VALID_STAT(smb_fname->st)) {
8771 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8774 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8775 !VALID_STAT_OF_DIR(smb_fname->st)) {
8776 return NT_STATUS_NOT_A_DIRECTORY;
8779 DEBUG(10,("smb_posix_unlink: %s %s\n",
8780 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8781 smb_fname_str_dbg(smb_fname)));
8783 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8784 create_options |= FILE_DIRECTORY_FILE;
8787 status = SMB_VFS_CREATE_FILE(
8790 0, /* root_dir_fid */
8791 smb_fname, /* fname */
8792 DELETE_ACCESS, /* access_mask */
8793 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8795 FILE_OPEN, /* create_disposition*/
8796 create_options, /* create_options */
8797 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8798 0, /* oplock_request */
8800 0, /* allocation_size */
8801 0, /* private_flags */
8806 NULL, NULL); /* create context */
8808 if (!NT_STATUS_IS_OK(status)) {
8813 * Don't lie to client. If we can't really delete due to
8814 * non-POSIX opens return SHARING_VIOLATION.
8817 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8819 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8820 "lock for file %s\n", fsp_str_dbg(fsp)));
8821 close_file(req, fsp, NORMAL_CLOSE);
8822 return NT_STATUS_INVALID_PARAMETER;
8825 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8826 if (other_nonposix_opens) {
8827 /* Fail with sharing violation. */
8829 close_file(req, fsp, NORMAL_CLOSE);
8830 return NT_STATUS_SHARING_VIOLATION;
8834 * Set the delete on close.
8836 status = smb_set_file_disposition_info(conn,
8844 if (!NT_STATUS_IS_OK(status)) {
8845 close_file(req, fsp, NORMAL_CLOSE);
8848 return close_file(req, fsp, NORMAL_CLOSE);
8851 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8852 struct smb_request *req,
8853 TALLOC_CTX *mem_ctx,
8854 uint16_t info_level,
8856 struct smb_filename *smb_fname,
8857 char **ppdata, int total_data,
8860 char *pdata = *ppdata;
8861 NTSTATUS status = NT_STATUS_OK;
8862 int data_return_size = 0;
8866 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8867 return NT_STATUS_INVALID_LEVEL;
8870 if (!CAN_WRITE(conn)) {
8871 /* Allow POSIX opens. The open path will deny
8872 * any non-readonly opens. */
8873 if (info_level != SMB_POSIX_PATH_OPEN) {
8874 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8878 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8879 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8881 info_level, total_data));
8883 switch (info_level) {
8885 case SMB_INFO_STANDARD:
8887 status = smb_set_info_standard(conn,
8895 case SMB_INFO_SET_EA:
8897 status = smb_info_set_ea(conn,
8905 case SMB_SET_FILE_BASIC_INFO:
8906 case SMB_FILE_BASIC_INFORMATION:
8908 status = smb_set_file_basic_info(conn,
8916 case SMB_FILE_ALLOCATION_INFORMATION:
8917 case SMB_SET_FILE_ALLOCATION_INFO:
8919 status = smb_set_file_allocation_info(conn, req,
8927 case SMB_FILE_END_OF_FILE_INFORMATION:
8928 case SMB_SET_FILE_END_OF_FILE_INFO:
8931 * XP/Win7 both fail after the createfile with
8932 * SMB_SET_FILE_END_OF_FILE_INFO but not
8933 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8934 * The level is known here, so pass it down
8938 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8940 status = smb_set_file_end_of_file_info(conn, req,
8949 case SMB_FILE_DISPOSITION_INFORMATION:
8950 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8953 /* JRA - We used to just ignore this on a path ?
8954 * Shouldn't this be invalid level on a pathname
8957 if (tran_call != TRANSACT2_SETFILEINFO) {
8958 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8961 status = smb_set_file_disposition_info(conn,
8969 case SMB_FILE_POSITION_INFORMATION:
8971 status = smb_file_position_information(conn,
8978 case SMB_FILE_FULL_EA_INFORMATION:
8980 status = smb_set_file_full_ea_info(conn,
8987 /* From tridge Samba4 :
8988 * MODE_INFORMATION in setfileinfo (I have no
8989 * idea what "mode information" on a file is - it takes a value of 0,
8990 * 2, 4 or 6. What could it be?).
8993 case SMB_FILE_MODE_INFORMATION:
8995 status = smb_file_mode_information(conn,
9001 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9002 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9003 case SMB_FILE_SHORT_NAME_INFORMATION:
9004 return NT_STATUS_NOT_SUPPORTED;
9007 * CIFS UNIX extensions.
9010 case SMB_SET_FILE_UNIX_BASIC:
9012 status = smb_set_file_unix_basic(conn, req,
9020 case SMB_SET_FILE_UNIX_INFO2:
9022 status = smb_set_file_unix_info2(conn, req,
9030 case SMB_SET_FILE_UNIX_LINK:
9033 /* We must have a pathname for this. */
9034 return NT_STATUS_INVALID_LEVEL;
9036 status = smb_set_file_unix_link(conn, req, pdata,
9037 total_data, smb_fname);
9041 case SMB_SET_FILE_UNIX_HLINK:
9044 /* We must have a pathname for this. */
9045 return NT_STATUS_INVALID_LEVEL;
9047 status = smb_set_file_unix_hlink(conn, req,
9053 case SMB_FILE_RENAME_INFORMATION:
9055 status = smb_file_rename_information(conn, req,
9061 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9063 /* SMB2 rename information. */
9064 status = smb2_file_rename_information(conn, req,
9070 case SMB_FILE_LINK_INFORMATION:
9072 status = smb_file_link_information(conn, req,
9078 #if defined(HAVE_POSIX_ACLS)
9079 case SMB_SET_POSIX_ACL:
9081 status = smb_set_posix_acl(conn,
9091 case SMB_SET_POSIX_LOCK:
9094 return NT_STATUS_INVALID_LEVEL;
9096 status = smb_set_posix_lock(conn, req,
9097 pdata, total_data, fsp);
9101 case SMB_POSIX_PATH_OPEN:
9104 /* We must have a pathname for this. */
9105 return NT_STATUS_INVALID_LEVEL;
9108 status = smb_posix_open(conn, req,
9116 case SMB_POSIX_PATH_UNLINK:
9119 /* We must have a pathname for this. */
9120 return NT_STATUS_INVALID_LEVEL;
9123 status = smb_posix_unlink(conn, req,
9131 return NT_STATUS_INVALID_LEVEL;
9134 if (!NT_STATUS_IS_OK(status)) {
9138 *ret_data_size = data_return_size;
9139 return NT_STATUS_OK;
9142 /****************************************************************************
9143 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9144 ****************************************************************************/
9146 static void call_trans2setfilepathinfo(connection_struct *conn,
9147 struct smb_request *req,
9148 unsigned int tran_call,
9149 char **pparams, int total_params,
9150 char **ppdata, int total_data,
9151 unsigned int max_data_bytes)
9153 char *params = *pparams;
9154 char *pdata = *ppdata;
9155 uint16_t info_level;
9156 struct smb_filename *smb_fname = NULL;
9157 files_struct *fsp = NULL;
9158 NTSTATUS status = NT_STATUS_OK;
9159 int data_return_size = 0;
9162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9166 if (tran_call == TRANSACT2_SETFILEINFO) {
9167 if (total_params < 4) {
9168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9172 fsp = file_fsp(req, SVAL(params,0));
9173 /* Basic check for non-null fsp. */
9174 if (!check_fsp_open(conn, req, fsp)) {
9177 info_level = SVAL(params,2);
9179 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9180 if (smb_fname == NULL) {
9181 reply_nterror(req, NT_STATUS_NO_MEMORY);
9185 if(fsp->fh->fd == -1) {
9187 * This is actually a SETFILEINFO on a directory
9188 * handle (returned from an NT SMB). NT5.0 seems
9189 * to do this call. JRA.
9191 if (INFO_LEVEL_IS_UNIX(info_level)) {
9192 /* Always do lstat for UNIX calls. */
9193 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9194 DEBUG(3,("call_trans2setfilepathinfo: "
9195 "SMB_VFS_LSTAT of %s failed "
9197 smb_fname_str_dbg(smb_fname),
9199 reply_nterror(req, map_nt_error_from_unix(errno));
9203 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9204 DEBUG(3,("call_trans2setfilepathinfo: "
9205 "fileinfo of %s failed (%s)\n",
9206 smb_fname_str_dbg(smb_fname),
9208 reply_nterror(req, map_nt_error_from_unix(errno));
9212 } else if (fsp->print_file) {
9214 * Doing a DELETE_ON_CLOSE should cancel a print job.
9216 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9217 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9219 DEBUG(3,("call_trans2setfilepathinfo: "
9220 "Cancelling print job (%s)\n",
9224 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9230 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9235 * Original code - this is an open file.
9237 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9238 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9239 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9241 reply_nterror(req, map_nt_error_from_unix(errno));
9247 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9250 if (total_params < 7) {
9251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9255 info_level = SVAL(params,0);
9256 if (req->posix_pathnames) {
9257 srvstr_get_path_posix(req,
9266 srvstr_get_path(req,
9275 if (!NT_STATUS_IS_OK(status)) {
9276 reply_nterror(req, status);
9280 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9281 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9282 info_level == SMB_FILE_RENAME_INFORMATION ||
9283 info_level == SMB_POSIX_PATH_OPEN ||
9284 info_level == SMB_POSIX_PATH_UNLINK) {
9285 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9288 status = filename_convert(req, conn,
9294 if (!NT_STATUS_IS_OK(status)) {
9295 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9296 reply_botherror(req,
9297 NT_STATUS_PATH_NOT_COVERED,
9298 ERRSRV, ERRbadpath);
9301 reply_nterror(req, status);
9305 if (INFO_LEVEL_IS_UNIX(info_level)) {
9307 * For CIFS UNIX extensions the target name may not exist.
9310 /* Always do lstat for UNIX calls. */
9311 SMB_VFS_LSTAT(conn, smb_fname);
9313 } else if (!VALID_STAT(smb_fname->st) &&
9314 SMB_VFS_STAT(conn, smb_fname)) {
9315 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9317 smb_fname_str_dbg(smb_fname),
9319 reply_nterror(req, map_nt_error_from_unix(errno));
9324 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9325 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9327 info_level,total_data));
9329 /* Realloc the parameter size */
9330 *pparams = (char *)SMB_REALLOC(*pparams,2);
9331 if (*pparams == NULL) {
9332 reply_nterror(req, NT_STATUS_NO_MEMORY);
9339 status = smbd_do_setfilepathinfo(conn, req, req,
9345 if (!NT_STATUS_IS_OK(status)) {
9346 if (open_was_deferred(req->xconn, req->mid)) {
9347 /* We have re-scheduled this call. */
9350 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9351 bool ok = defer_smb1_sharing_violation(req);
9356 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9357 /* We have re-scheduled this call. */
9360 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9361 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9362 ERRSRV, ERRbadpath);
9365 if (info_level == SMB_POSIX_PATH_OPEN) {
9366 reply_openerror(req, status);
9371 * Invalid EA name needs to return 2 param bytes,
9372 * not a zero-length error packet.
9374 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9375 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9378 reply_nterror(req, status);
9383 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9389 /****************************************************************************
9390 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9391 ****************************************************************************/
9393 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9394 char **pparams, int total_params,
9395 char **ppdata, int total_data,
9396 unsigned int max_data_bytes)
9398 struct smb_filename *smb_dname = NULL;
9399 char *params = *pparams;
9400 char *pdata = *ppdata;
9401 char *directory = NULL;
9402 NTSTATUS status = NT_STATUS_OK;
9403 struct ea_list *ea_list = NULL;
9404 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9405 TALLOC_CTX *ctx = talloc_tos();
9407 if (!CAN_WRITE(conn)) {
9408 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9412 if (total_params < 5) {
9413 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9417 if (req->posix_pathnames) {
9418 srvstr_get_path_posix(ctx,
9427 srvstr_get_path(ctx,
9436 if (!NT_STATUS_IS_OK(status)) {
9437 reply_nterror(req, status);
9441 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9443 status = filename_convert(ctx,
9451 if (!NT_STATUS_IS_OK(status)) {
9452 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9453 reply_botherror(req,
9454 NT_STATUS_PATH_NOT_COVERED,
9455 ERRSRV, ERRbadpath);
9458 reply_nterror(req, status);
9463 * OS/2 workplace shell seems to send SET_EA requests of "null"
9464 * length (4 bytes containing IVAL 4).
9465 * They seem to have no effect. Bug #3212. JRA.
9468 if (total_data && (total_data != 4)) {
9469 /* Any data in this call is an EA list. */
9470 if (total_data < 10) {
9471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9475 if (IVAL(pdata,0) > total_data) {
9476 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9477 IVAL(pdata,0), (unsigned int)total_data));
9478 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9482 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9489 if (!lp_ea_support(SNUM(conn))) {
9490 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9494 /* If total_data == 4 Windows doesn't care what values
9495 * are placed in that field, it just ignores them.
9496 * The System i QNTC IBM SMB client puts bad values here,
9497 * so ignore them. */
9499 status = create_directory(conn, req, smb_dname);
9501 if (!NT_STATUS_IS_OK(status)) {
9502 reply_nterror(req, status);
9506 /* Try and set any given EA. */
9508 status = set_ea(conn, NULL, smb_dname, ea_list);
9509 if (!NT_STATUS_IS_OK(status)) {
9510 reply_nterror(req, status);
9515 /* Realloc the parameter and data sizes */
9516 *pparams = (char *)SMB_REALLOC(*pparams,2);
9517 if(*pparams == NULL) {
9518 reply_nterror(req, NT_STATUS_NO_MEMORY);
9525 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9528 TALLOC_FREE(smb_dname);
9532 /****************************************************************************
9533 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9534 We don't actually do this - we just send a null response.
9535 ****************************************************************************/
9537 static void call_trans2findnotifyfirst(connection_struct *conn,
9538 struct smb_request *req,
9539 char **pparams, int total_params,
9540 char **ppdata, int total_data,
9541 unsigned int max_data_bytes)
9543 char *params = *pparams;
9544 uint16_t info_level;
9546 if (total_params < 6) {
9547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9551 info_level = SVAL(params,4);
9552 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9554 switch (info_level) {
9559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9563 /* Realloc the parameter and data sizes */
9564 *pparams = (char *)SMB_REALLOC(*pparams,6);
9565 if (*pparams == NULL) {
9566 reply_nterror(req, NT_STATUS_NO_MEMORY);
9571 SSVAL(params,0,fnf_handle);
9572 SSVAL(params,2,0); /* No changes */
9573 SSVAL(params,4,0); /* No EA errors */
9580 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9585 /****************************************************************************
9586 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9587 changes). Currently this does nothing.
9588 ****************************************************************************/
9590 static void call_trans2findnotifynext(connection_struct *conn,
9591 struct smb_request *req,
9592 char **pparams, int total_params,
9593 char **ppdata, int total_data,
9594 unsigned int max_data_bytes)
9596 char *params = *pparams;
9598 DEBUG(3,("call_trans2findnotifynext\n"));
9600 /* Realloc the parameter and data sizes */
9601 *pparams = (char *)SMB_REALLOC(*pparams,4);
9602 if (*pparams == NULL) {
9603 reply_nterror(req, NT_STATUS_NO_MEMORY);
9608 SSVAL(params,0,0); /* No changes */
9609 SSVAL(params,2,0); /* No EA errors */
9611 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9616 /****************************************************************************
9617 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9618 ****************************************************************************/
9620 static void call_trans2getdfsreferral(connection_struct *conn,
9621 struct smb_request *req,
9622 char **pparams, int total_params,
9623 char **ppdata, int total_data,
9624 unsigned int max_data_bytes)
9626 char *params = *pparams;
9627 char *pathname = NULL;
9629 int max_referral_level;
9630 NTSTATUS status = NT_STATUS_OK;
9631 TALLOC_CTX *ctx = talloc_tos();
9633 DEBUG(10,("call_trans2getdfsreferral\n"));
9635 if (total_params < 3) {
9636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9640 max_referral_level = SVAL(params,0);
9642 if(!lp_host_msdfs()) {
9643 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9647 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9648 total_params - 2, STR_TERMINATE);
9650 reply_nterror(req, NT_STATUS_NOT_FOUND);
9653 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9654 ppdata,&status)) < 0) {
9655 reply_nterror(req, status);
9659 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9660 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9661 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9666 #define LMCAT_SPL 0x53
9667 #define LMFUNC_GETJOBID 0x60
9669 /****************************************************************************
9670 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9671 ****************************************************************************/
9673 static void call_trans2ioctl(connection_struct *conn,
9674 struct smb_request *req,
9675 char **pparams, int total_params,
9676 char **ppdata, int total_data,
9677 unsigned int max_data_bytes)
9679 char *pdata = *ppdata;
9680 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9684 /* check for an invalid fid before proceeding */
9687 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9691 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9692 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9693 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9694 if (*ppdata == NULL) {
9695 reply_nterror(req, NT_STATUS_NO_MEMORY);
9700 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9701 CAN ACCEPT THIS IN UNICODE. JRA. */
9704 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9706 status = srvstr_push(pdata, req->flags2, pdata + 2,
9707 lp_netbios_name(), 15,
9708 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9709 if (!NT_STATUS_IS_OK(status)) {
9710 reply_nterror(req, status);
9713 status = srvstr_push(pdata, req->flags2, pdata+18,
9714 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9715 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9716 if (!NT_STATUS_IS_OK(status)) {
9717 reply_nterror(req, status);
9720 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9725 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9726 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9729 /****************************************************************************
9730 Reply to a SMBfindclose (stop trans2 directory search).
9731 ****************************************************************************/
9733 void reply_findclose(struct smb_request *req)
9736 struct smbd_server_connection *sconn = req->sconn;
9737 files_struct *fsp = NULL;
9739 START_PROFILE(SMBfindclose);
9742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9743 END_PROFILE(SMBfindclose);
9747 dptr_num = SVALS(req->vwv+0, 0);
9749 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9752 * OS/2 seems to use -1 to indicate "close all directories"
9753 * This has to mean on this specific connection struct.
9755 if (dptr_num == -1) {
9756 dptr_closecnum(req->conn);
9758 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9761 close_file(NULL, fsp, NORMAL_CLOSE);
9766 reply_outbuf(req, 0, 0);
9768 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9770 END_PROFILE(SMBfindclose);
9774 /****************************************************************************
9775 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9776 ****************************************************************************/
9778 void reply_findnclose(struct smb_request *req)
9782 START_PROFILE(SMBfindnclose);
9785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9786 END_PROFILE(SMBfindnclose);
9790 dptr_num = SVAL(req->vwv+0, 0);
9792 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9794 /* We never give out valid handles for a
9795 findnotifyfirst - so any dptr_num is ok here.
9798 reply_outbuf(req, 0, 0);
9800 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9802 END_PROFILE(SMBfindnclose);
9806 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9807 struct trans_state *state)
9809 if (get_Protocol() >= PROTOCOL_NT1) {
9810 req->flags2 |= 0x40; /* IS_LONG_NAME */
9811 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9814 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9815 if (state->call != TRANSACT2_QFSINFO &&
9816 state->call != TRANSACT2_SETFSINFO) {
9817 DEBUG(0,("handle_trans2: encryption required "
9819 (unsigned int)state->call));
9820 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9825 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9827 /* Now we must call the relevant TRANS2 function */
9828 switch(state->call) {
9829 case TRANSACT2_OPEN:
9831 START_PROFILE(Trans2_open);
9832 call_trans2open(conn, req,
9833 &state->param, state->total_param,
9834 &state->data, state->total_data,
9835 state->max_data_return);
9836 END_PROFILE(Trans2_open);
9840 case TRANSACT2_FINDFIRST:
9842 START_PROFILE(Trans2_findfirst);
9843 call_trans2findfirst(conn, req,
9844 &state->param, state->total_param,
9845 &state->data, state->total_data,
9846 state->max_data_return);
9847 END_PROFILE(Trans2_findfirst);
9851 case TRANSACT2_FINDNEXT:
9853 START_PROFILE(Trans2_findnext);
9854 call_trans2findnext(conn, req,
9855 &state->param, state->total_param,
9856 &state->data, state->total_data,
9857 state->max_data_return);
9858 END_PROFILE(Trans2_findnext);
9862 case TRANSACT2_QFSINFO:
9864 START_PROFILE(Trans2_qfsinfo);
9865 call_trans2qfsinfo(conn, req,
9866 &state->param, state->total_param,
9867 &state->data, state->total_data,
9868 state->max_data_return);
9869 END_PROFILE(Trans2_qfsinfo);
9873 case TRANSACT2_SETFSINFO:
9875 START_PROFILE(Trans2_setfsinfo);
9876 call_trans2setfsinfo(conn, req,
9877 &state->param, state->total_param,
9878 &state->data, state->total_data,
9879 state->max_data_return);
9880 END_PROFILE(Trans2_setfsinfo);
9884 case TRANSACT2_QPATHINFO:
9885 case TRANSACT2_QFILEINFO:
9887 START_PROFILE(Trans2_qpathinfo);
9888 call_trans2qfilepathinfo(conn, req, state->call,
9889 &state->param, state->total_param,
9890 &state->data, state->total_data,
9891 state->max_data_return);
9892 END_PROFILE(Trans2_qpathinfo);
9896 case TRANSACT2_SETPATHINFO:
9897 case TRANSACT2_SETFILEINFO:
9899 START_PROFILE(Trans2_setpathinfo);
9900 call_trans2setfilepathinfo(conn, req, state->call,
9901 &state->param, state->total_param,
9902 &state->data, state->total_data,
9903 state->max_data_return);
9904 END_PROFILE(Trans2_setpathinfo);
9908 case TRANSACT2_FINDNOTIFYFIRST:
9910 START_PROFILE(Trans2_findnotifyfirst);
9911 call_trans2findnotifyfirst(conn, req,
9912 &state->param, state->total_param,
9913 &state->data, state->total_data,
9914 state->max_data_return);
9915 END_PROFILE(Trans2_findnotifyfirst);
9919 case TRANSACT2_FINDNOTIFYNEXT:
9921 START_PROFILE(Trans2_findnotifynext);
9922 call_trans2findnotifynext(conn, req,
9923 &state->param, state->total_param,
9924 &state->data, state->total_data,
9925 state->max_data_return);
9926 END_PROFILE(Trans2_findnotifynext);
9930 case TRANSACT2_MKDIR:
9932 START_PROFILE(Trans2_mkdir);
9933 call_trans2mkdir(conn, req,
9934 &state->param, state->total_param,
9935 &state->data, state->total_data,
9936 state->max_data_return);
9937 END_PROFILE(Trans2_mkdir);
9941 case TRANSACT2_GET_DFS_REFERRAL:
9943 START_PROFILE(Trans2_get_dfs_referral);
9944 call_trans2getdfsreferral(conn, req,
9945 &state->param, state->total_param,
9946 &state->data, state->total_data,
9947 state->max_data_return);
9948 END_PROFILE(Trans2_get_dfs_referral);
9952 case TRANSACT2_IOCTL:
9954 START_PROFILE(Trans2_ioctl);
9955 call_trans2ioctl(conn, req,
9956 &state->param, state->total_param,
9957 &state->data, state->total_data,
9958 state->max_data_return);
9959 END_PROFILE(Trans2_ioctl);
9964 /* Error in request */
9965 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9966 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9970 /****************************************************************************
9971 Reply to a SMBtrans2.
9972 ****************************************************************************/
9974 void reply_trans2(struct smb_request *req)
9976 connection_struct *conn = req->conn;
9981 unsigned int tran_call;
9982 struct trans_state *state;
9985 START_PROFILE(SMBtrans2);
9987 if (req->wct < 14) {
9988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9989 END_PROFILE(SMBtrans2);
9993 dsoff = SVAL(req->vwv+12, 0);
9994 dscnt = SVAL(req->vwv+11, 0);
9995 psoff = SVAL(req->vwv+10, 0);
9996 pscnt = SVAL(req->vwv+9, 0);
9997 tran_call = SVAL(req->vwv+14, 0);
9999 result = allow_new_trans(conn->pending_trans, req->mid);
10000 if (!NT_STATUS_IS_OK(result)) {
10001 DEBUG(2, ("Got invalid trans2 request: %s\n",
10002 nt_errstr(result)));
10003 reply_nterror(req, result);
10004 END_PROFILE(SMBtrans2);
10008 if (IS_IPC(conn)) {
10009 switch (tran_call) {
10010 /* List the allowed trans2 calls on IPC$ */
10011 case TRANSACT2_OPEN:
10012 case TRANSACT2_GET_DFS_REFERRAL:
10013 case TRANSACT2_QFILEINFO:
10014 case TRANSACT2_QFSINFO:
10015 case TRANSACT2_SETFSINFO:
10018 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10019 END_PROFILE(SMBtrans2);
10024 if ((state = talloc(conn, struct trans_state)) == NULL) {
10025 DEBUG(0, ("talloc failed\n"));
10026 reply_nterror(req, NT_STATUS_NO_MEMORY);
10027 END_PROFILE(SMBtrans2);
10031 state->cmd = SMBtrans2;
10033 state->mid = req->mid;
10034 state->vuid = req->vuid;
10035 state->setup_count = SVAL(req->vwv+13, 0);
10036 state->setup = NULL;
10037 state->total_param = SVAL(req->vwv+0, 0);
10038 state->param = NULL;
10039 state->total_data = SVAL(req->vwv+1, 0);
10040 state->data = NULL;
10041 state->max_param_return = SVAL(req->vwv+2, 0);
10042 state->max_data_return = SVAL(req->vwv+3, 0);
10043 state->max_setup_return = SVAL(req->vwv+4, 0);
10044 state->close_on_completion = BITSETW(req->vwv+5, 0);
10045 state->one_way = BITSETW(req->vwv+5, 1);
10047 state->call = tran_call;
10049 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10050 is so as a sanity check */
10051 if (state->setup_count != 1) {
10053 * Need to have rc=0 for ioctl to get job id for OS/2.
10054 * Network printing will fail if function is not successful.
10055 * Similar function in reply.c will be used if protocol
10056 * is LANMAN1.0 instead of LM1.2X002.
10057 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10058 * outbuf doesn't have to be set(only job id is used).
10060 if ( (state->setup_count == 4)
10061 && (tran_call == TRANSACT2_IOCTL)
10062 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10063 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10064 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10066 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10067 DEBUG(2,("Transaction is %d\n",tran_call));
10068 TALLOC_FREE(state);
10069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10070 END_PROFILE(SMBtrans2);
10075 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10078 if (state->total_data) {
10080 if (trans_oob(state->total_data, 0, dscnt)
10081 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10085 /* Can't use talloc here, the core routines do realloc on the
10086 * params and data. */
10087 state->data = (char *)SMB_MALLOC(state->total_data);
10088 if (state->data == NULL) {
10089 DEBUG(0,("reply_trans2: data malloc fail for %u "
10090 "bytes !\n", (unsigned int)state->total_data));
10091 TALLOC_FREE(state);
10092 reply_nterror(req, NT_STATUS_NO_MEMORY);
10093 END_PROFILE(SMBtrans2);
10097 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10100 if (state->total_param) {
10102 if (trans_oob(state->total_param, 0, pscnt)
10103 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10107 /* Can't use talloc here, the core routines do realloc on the
10108 * params and data. */
10109 state->param = (char *)SMB_MALLOC(state->total_param);
10110 if (state->param == NULL) {
10111 DEBUG(0,("reply_trans: param malloc fail for %u "
10112 "bytes !\n", (unsigned int)state->total_param));
10113 SAFE_FREE(state->data);
10114 TALLOC_FREE(state);
10115 reply_nterror(req, NT_STATUS_NO_MEMORY);
10116 END_PROFILE(SMBtrans2);
10120 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10123 state->received_data = dscnt;
10124 state->received_param = pscnt;
10126 if ((state->received_param == state->total_param) &&
10127 (state->received_data == state->total_data)) {
10129 handle_trans2(conn, req, state);
10131 SAFE_FREE(state->data);
10132 SAFE_FREE(state->param);
10133 TALLOC_FREE(state);
10134 END_PROFILE(SMBtrans2);
10138 DLIST_ADD(conn->pending_trans, state);
10140 /* We need to send an interim response then receive the rest
10141 of the parameter/data bytes */
10142 reply_outbuf(req, 0, 0);
10143 show_msg((char *)req->outbuf);
10144 END_PROFILE(SMBtrans2);
10149 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10150 SAFE_FREE(state->data);
10151 SAFE_FREE(state->param);
10152 TALLOC_FREE(state);
10153 END_PROFILE(SMBtrans2);
10154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10158 /****************************************************************************
10159 Reply to a SMBtranss2
10160 ****************************************************************************/
10162 void reply_transs2(struct smb_request *req)
10164 connection_struct *conn = req->conn;
10165 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10166 struct trans_state *state;
10168 START_PROFILE(SMBtranss2);
10170 show_msg((const char *)req->inbuf);
10172 /* Windows clients expect all replies to
10173 a transact secondary (SMBtranss2 0x33)
10174 to have a command code of transact
10175 (SMBtrans2 0x32). See bug #8989
10176 and also [MS-CIFS] section 2.2.4.47.2
10179 req->cmd = SMBtrans2;
10181 if (req->wct < 8) {
10182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10183 END_PROFILE(SMBtranss2);
10187 for (state = conn->pending_trans; state != NULL;
10188 state = state->next) {
10189 if (state->mid == req->mid) {
10194 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10196 END_PROFILE(SMBtranss2);
10200 /* Revise state->total_param and state->total_data in case they have
10201 changed downwards */
10203 if (SVAL(req->vwv+0, 0) < state->total_param)
10204 state->total_param = SVAL(req->vwv+0, 0);
10205 if (SVAL(req->vwv+1, 0) < state->total_data)
10206 state->total_data = SVAL(req->vwv+1, 0);
10208 pcnt = SVAL(req->vwv+2, 0);
10209 poff = SVAL(req->vwv+3, 0);
10210 pdisp = SVAL(req->vwv+4, 0);
10212 dcnt = SVAL(req->vwv+5, 0);
10213 doff = SVAL(req->vwv+6, 0);
10214 ddisp = SVAL(req->vwv+7, 0);
10216 state->received_param += pcnt;
10217 state->received_data += dcnt;
10219 if ((state->received_data > state->total_data) ||
10220 (state->received_param > state->total_param))
10224 if (trans_oob(state->total_param, pdisp, pcnt)
10225 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10228 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10232 if (trans_oob(state->total_data, ddisp, dcnt)
10233 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10236 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10239 if ((state->received_param < state->total_param) ||
10240 (state->received_data < state->total_data)) {
10241 END_PROFILE(SMBtranss2);
10245 handle_trans2(conn, req, state);
10247 DLIST_REMOVE(conn->pending_trans, state);
10248 SAFE_FREE(state->data);
10249 SAFE_FREE(state->param);
10250 TALLOC_FREE(state);
10252 END_PROFILE(SMBtranss2);
10257 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10258 DLIST_REMOVE(conn->pending_trans, state);
10259 SAFE_FREE(state->data);
10260 SAFE_FREE(state->param);
10261 TALLOC_FREE(state);
10262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10263 END_PROFILE(SMBtranss2);